基于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.0
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/jre/lib/rt.jar
export 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 <stdio.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/err.h>
#include <openssl/ssl.h>

#include "org_gmssl_GmSSLClient.h"

#define Eprintf printf("[%s][%s][%d] ",__FILE__,__func__,__LINE__);printf

#define SSL_RECV_BUF 2048

static 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 <= 0) {
		Eprintf("SSL_read err [%d:%s]", errno,strerror(errno));
		goto _ErrorRet;
	}
    recv_buf[ret] = '\0';

    recv = (*env)->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.1
HTTP/1.1 404 Not Found
Server: nginx/1.20.1
Date: Fri, 15 Apr 2022 15:46:51 GMT
Content-Type: text/html
Content-Length: 153
Connection: close

<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.20.1</center>
</body>
</html>

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hlovefp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值