java jni openssl nginx证书私钥有效性校验
1、安装openssl
wget https://www.openssl.org/source/openssl-1.1.1b.tar.gz
./config --prefix=/usr/local/openssl --shared
--shared为添加动态库,生成libssl.so,默认只有libssl.a静态库
make
make install
ln -s /usr/local/openssl/bin/openssl /usr/bin/openssl
cp /usr/local/openssl/lib/openssl/libssl.so.1.1 /lib/x86_64-linux-gnu/
cp /usr/local/openssl/lib/openssl/libcrypto.so.1.1 /lib/x86_64-linux-gnu/
2、新建jni工程(eclipse为例)
新建java工程PemCheck
src下新建class com.jni.OpenSSLUtils.java
package com.jni;
public class OpenSSLUtils {
public native static int checkPem(String pem,String key);
}
cd ${workspace}/PemCheck
javah -classpath . -d . com.jni.OpenSSLUtils
javah -jni com.jni.OpenSSLUtils
此时src下生成com_jni_OpenSSLUtils.h头文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jni_OpenSSLUtils */
#ifndef _Included_com_jni_OpenSSLUtils
#define _Included_com_jni_OpenSSLUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jni_OpenSSLUtils
* Method: checkPem
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_jni_OpenSSLUtils_checkPem
(JNIEnv *, jclass, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endif
3、新建C++工程(eclipse为例)
new project >> C++ Project >> ShardLibrary

设置编译环境
include jdk的头文件path
include jdk的头文件 linux path
include openssl 头文件path

编译参数加上-fPIC

链接库加上ssl,crypto

可以配置个命令将编译后的so库cp到测试或使用的工程路径下

4、编写openssl检测代码
新建src文件夹,将com_jni_OpenSSLUtils.h复制到该目录下,
同时新建com_jni_OpenSSLUtils.cpp
#include "com_jni_OpenSSLUtils.h"
#include "openssl/pem.h"
#include "openssl/bio.h"
#include "openssl/ssl.h"
#include <iostream>
using namespace std; // @suppress("Symbol is not resolved")
/*
* Class: com_jni_OpenSSLUtils
* Method: checkPem
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_jni_OpenSSLUtils_checkPem
(JNIEnv *env, jclass jc, jstring pem, jstring key){
BIO* keyBIO;
EVP_PKEY* pkey;
BIO* pemBIO = BIO_new_mem_buf(env->GetStringUTFChars(pem,0),-1);
X509* cert = PEM_read_bio_X509(pemBIO,NULL,NULL,NULL);
if (cert == NULL) {
cout << "PEM_read_bio_X509_AUX() failed" << endl;
if(NULL != pemBIO)
BIO_free(pemBIO);
return -1;
}
keyBIO = BIO_new_mem_buf(env->GetStringUTFChars(key,0),-1);
pkey = PEM_read_bio_PrivateKey(keyBIO,NULL,NULL,NULL);
if (pkey == NULL) {
cout << "PEM_read_bio_PrivateKey() failed" << endl;
if(NULL != cert)
X509_free(cert);
if(NULL != pemBIO)
BIO_free(pemBIO);
if(NULL != keyBIO)
BIO_free(keyBIO);
return -1;
}
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
if (ctx == NULL) {
cout << "ctx create failed" << endl;
goto bad;
}
if(SSL_CTX_use_certificate(ctx,cert)<=0){
cout << "user certificate fail" << endl;
goto bad;
}
if(SSL_CTX_use_PrivateKey(ctx,pkey) <=0){
cout << "user key fail" << endl;
goto bad;
}
if(!SSL_CTX_check_private_key(ctx)){
cout << "key does not match the certificate" << endl;
goto bad;
}
if(NULL != pemBIO)
BIO_free(pemBIO);
if(NULL != keyBIO)
BIO_free(keyBIO);
if(NULL != pkey)
EVP_PKEY_free(pkey);
if(NULL != cert)
X509_free(cert);
if(NULL != ctx)
SSL_CTX_free(ctx);
return 0;
bad:
if(NULL != cert)
X509_free(cert);
if(NULL != pemBIO)
BIO_free(pemBIO);
if(NULL != keyBIO)
BIO_free(keyBIO);
if(NULL != pkey)
EVP_PKEY_free(pkey);
if(NULL != ctx)
SSL_CTX_free(ctx);
return -1;
}
Build All.
5、测试
在java工程下新建Test 类
package com.jni;
public class Test {
static {
System.load("${solibpath}/libPemCheck.so");
}
public static void main(String[] args) {
System.out.println(
OpenSSLUtils.checkPem("cert","pem"));
}
}

浙公网安备 33010602011771号