> 文档中心 > 基于GmSSL的国密SSL单向验证客户端Java源码/JNI

基于GmSSL的国密SSL单向验证客户端Java源码/JNI

 

1 安装GmSSL和搭建测试Nginx服务器

基于GmSSL搭建Nginx国密反代服务器

 

2 安装openJDK

> yum install -y java-1.8.0-openjdk.x86_64 java-1.8.0-openjdk-devel.x86_64>vi $HOME/.bashrc# 添加环境变量export JAVA_HOME=/usr/lib/jvm/java-1.8.0export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/jre/lib/rt.jarexport PATH=$PATH:$JAVA_HOME/bin> source .bashrc

 

3 GmSSLClient.java

文件路径:GmSSL-master/java/GmSSLClient.java

package org.gmssl;public class GmSSLClient {    public native String exec(String host, int port, String send, int timeout);    static { System.loadLibrary("gmsslclientjni");    } public static void main(String args[]){ GmSSLClient client = new GmSSLClient(); String ip   = "192.168.218.141"; int    port = 1443; int    timeout = 10;  String body = "{\"loginName\":\"jiean\"}"; String send; String recv; send = "POST /horn/pushmsg HTTP/1.1\r\n"      + "Accept: */*\r\n"      + "Accept-Language: zh-cn\r\n"      + "Content-Type: application/json\r\n"      + "User-Agent: herve\r\n"      + "Host: "+ip+":"+port+"\r\n"      + "Content-Length: "+body.length()+"\r\n"      + "Connection: close\r\n"      + "Cache-Control: no-cache\r\n\r\n"      + body; recv = client.exec(ip,port,send,timeout); if (null == recv) {     System.out.println("exec error"); } else {     System.out.println(recv); }    }}

编译代码

> cd GmSSL-master/java> javac -d . GmSSLClient.java> javah org.gmssl.GmSSLClient   # 生成 org_gmssl_GmSSLClient.h

4 org_gmssl_GmSSLClient.c

文件路径:GmSSL-master/java/org_gmssl_GmSSLClient.c

#include #include #include #include #include #include #include #include #include #include #include #include "org_gmssl_GmSSLClient.h"#define Eprintf printf("[%s][%s][%d] ",__FILE__,__func__,__LINE__);printf#define SSL_RECV_BUF 2048static int ssl_alarm_flag;#define SSL_IS_TIMEOUT      (-1 == ssl_alarm_flag)static void ssl_sigset_alarm(int sig){ssl_alarm_flag = -1;    alarm(0);    signal(SIGALRM, SIG_DFL);}static void ssl_set_alarm(int time_out){ssl_alarm_flag = 0;signal(SIGALRM , ssl_sigset_alarm);alarm(time_out);}static void ssl_unset_alarm(void){    alarm(0);    signal(SIGALRM, SIG_DFL);}JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved){SSLeay_add_ssl_algorithms();    SSL_load_error_strings();return JNI_VERSION_1_2;}JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved){}/* * Class:     org_gmssl_GmSSLClient * Method:    exec * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_org_gmssl_GmSSLClient_exec  (JNIEnv *env, jobject this, jstring ip, jint port, jstring send, jint time_out){jstring recv = NULL;int     ret;int    client_fd = -1;    int     total_len = 0;    int     len= 0;    struct sockaddr_in stSockAddr;    char    recv_buf[SSL_RECV_BUF];    SSL_CTX   *ctx  = NULL;    SSL*ssl  = NULL;const SSL_METHOD *meth = NULL;    char *c_ip   = (char*)(*env)->GetStringUTFChars(env,   ip, NULL);    char *c_send = (char*)(*env)->GetStringUTFChars(env, send, NULL);    meth = GMTLS_client_method();  //使用GMTLSv1.1协议    //meth = SSLv23_client_method();   //ssl协议版本,v2,v3 自适应    if(meth == NULL) {    Eprintf("SSLv23_client_method err [%d:%s]\n", errno,strerror(errno));    ret = -1;    goto _ErrorRet;    }    ctx = SSL_CTX_new(meth);  //申请SSL会话环境    if(NULL == ctx) { Eprintf("SSL_CTX_new err [%d:%s]\n", errno,strerror(errno)); goto _ErrorRet;    }    //建立普通的TCP连接    client_fd = socket(AF_INET, SOCK_STREAM, 0);    if(client_fd < 0) { Eprintf("socket fail, err[%d:%s]\n", errno, strerror(errno)); goto _ErrorRet;    }    memset(&stSockAddr, 0, sizeof(stSockAddr));    stSockAddr.sin_family = AF_INET;    stSockAddr.sin_port = htons(port);    stSockAddr.sin_addr.s_addr = inet_addr(c_ip);    Eprintf("connect[%s:%d]\n" , c_ip, port);    ssl_set_alarm(time_out);    ret = connect(client_fd,(struct sockaddr *) &stSockAddr, sizeof(stSockAddr));    ssl_unset_alarm();    if (SSL_IS_TIMEOUT) {    Eprintf("connect server[%s:%d] time out\n", c_ip,port);goto _ErrorRet;    } else if(ret != 0) { Eprintf("connect server[%s:%d] fail, err[%d:%s]\n", c_ip, port, errno, strerror(errno)); goto _ErrorRet;    }    ssl = SSL_new(ctx);   //创建SSL套接字    if(NULL == ssl)    { Eprintf("SSL_new err [%d:%s]\n", errno,strerror(errno)); goto _ErrorRet;    }    SSL_set_fd(ssl, client_fd); //将TCP套接字与SSL套接字联系起来    ssl_set_alarm(time_out);    ret = SSL_connect(ssl);     //启动SSL链接    ssl_unset_alarm();if (SSL_IS_TIMEOUT) {Eprintf("SSL_connect [%s:%d] time out\n", c_ip,port);goto _ErrorRet;} else if(ret <= 0) { ERR_print_errors_fp(stderr); Eprintf("SSL_connect ret[%d][%d:%s]\n", ret, errno, strerror(errno)); goto _ErrorRet;    }    total_len = strlen(c_send);    len= 0;    while (len < total_len) {    ssl_set_alarm(time_out);ret = SSL_write(ssl, c_send+len, total_len-len);ssl_unset_alarm();if (SSL_IS_TIMEOUT) {Eprintf("SSL_write server[%s:%d] time out\n", c_ip,port);goto _ErrorRet;} else if(ret <= 0) {Eprintf("SSL_write err [%d:%s]\n", errno,strerror(errno));goto _ErrorRet;}len += ret;    }    ssl_set_alarm(time_out);ret = SSL_read(ssl, recv_buf, SSL_RECV_BUF-1);ssl_unset_alarm();if (SSL_IS_TIMEOUT) {Eprintf("SSL_read server[%s:%d] time out\n", c_ip,port);goto _ErrorRet;} else if(ret NewStringUTF(env, recv_buf);_ErrorRet:if(NULL != ssl) {SSL_shutdown(ssl);    //结束SSL通信SSL_free(ssl); //释放SSL套接字}if(-1 != client_fd) {close(client_fd);}if(NULL != ctx) {SSL_CTX_free(ctx);    //释放SSL会话环境} /*通知虚拟机平台相关代码无需再访问*/(*env)->ReleaseStringUTFChars(env, ip, c_ip);(*env)->ReleaseStringUTFChars(env, ip, c_send);return recv;}

编译代码:

>gcc -shared -fPIC -Wall -I./jni org_gmssl_GmSSLClient.c -lcrypto -lssl -o libgmsslclientjni.so

5 执行HTTPS请求

> java -Djava.library.path=./ org.gmssl.GmSSLClient

[org_gmssl_GmSSLClient.c][Java_org_gmssl_GmSSLClient_exec][106] connect[192.168.218.141:1443][org_gmssl_GmSSLClient.c][Java_org_gmssl_GmSSLClient_exec][141] SSL using cipher : SM2-WITH-SMS4-SM3[org_gmssl_GmSSLClient.c][Java_org_gmssl_GmSSLClient_exec][142] SSL using cipher_name   : SM2-WITH-SMS4-SM3[org_gmssl_GmSSLClient.c][Java_org_gmssl_GmSSLClient_exec][143] SSL using cipher_version: GMTLSv1.1HTTP/1.1 404 Not FoundServer: nginx/1.20.1Date: Fri, 15 Apr 2022 15:46:51 GMTContent-Type: text/htmlContent-Length: 153Connection: close404 Not Found

404 Not Found


nginx/1.20.1