最近项目中,突然不想把加密算法直接写到java上面,毕竟很简单的一个反编译就能看到你的实现逻辑或者是公钥私钥/种子。于是,就有了想利用jni来进行加密算法处理。
首先,先在windows平台下面进行开发。编辑工具就直接使用vs 2019的社区版了。
创建c++的jni项目
创建项目:(我这里是使用英文版的,如果想用就下载个对应的语言包就好)
点击菜单栏 File->new->project
然后
之后,就自己选择好对应的项目位置,再点击create来进行创建即可。这里就直接略过。
JNI依赖库引入
创建好项目后,如我这里为 MyTestProject 项目
1、点击创建好的项目,右键,选择properties
2、选择 VC++ Directories (VC++目录 ),然后把你的 $JAVA_HOME/include 以及 $JAVA_HOME/include/win32添加到 Include Directories (包含目录)下,因为我这里不知道变量是否有用,所以我就选择了全地址的方式。
如图(为了方便不用分别配置 x86 跟 x64 这里选择 All Platform 的全平台方式)
点击下拉 再点击edit
输入你对应的目录 (如我这里的java是安装在D:\tools\Java\jdk1.8.0_231 下面 )
点击OK,基本上你的vs环境中的jni已经配置好了。
编写对应的java类
MyJni.java
package com.tk.jni;
/**
* jni类
*
* @Autor Tricky
* @Date 2020-08-25 17:43:46
*/
public class MyJni {
/**
* 加密 使用默认公钥加密
*
* @param text
* @param length
* @return
*/
public static native byte[] encrypt(byte[] text, int length);
/**
* 解密 使用默认私钥解密
*
* @param encryptData
* @param length
* @return
*/
public static native byte[] decrypt(byte[] encryptData, int length);
}
然后 生成对应的xxx.h类
首先,我们cd到这个java项目的java目录下
cd /d xxx/xxx/src/main/java
编译对应的头文件
javah -o MyJni.h -jni com.tk.jni.MyJni
其中 -o参数后面表示你输出的文件名字
输出的 MyJni.h文件内容。很多人都把 <jni.h>的尖括号改成使用引号,主要原因是因为他们的vs的jni环境还没搭建好导致的。我们自己直接复制进去 啥都不需要改
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_tk_jni_MyJni */
#ifndef _Included_com_tk_jni_MyJni
#define _Included_com_tk_jni_MyJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_tk_jni_MyJni
* Method: encrypt
* Signature: ([BI)[B
*/
JNIEXPORT jbyteArray JNICALL Java_com_tk_jni_MyJni_encrypt
(JNIEnv *, jclass, jbyteArray, jint);
/*
* Class: com_tk_jni_MyJni
* Method: decrypt
* Signature: ([BI)[B
*/
JNIEXPORT jbyteArray JNICALL Java_com_tk_jni_MyJni_decrypt
(JNIEnv *, jclass, jbyteArray, jint);
#ifdef __cplusplus
}
#endif
#endif
使用c++来实现
1、准备一个 rsa的公钥&私钥
2、把上面生成的头文件,放到你的c++项目中去,这里放到对应的文件夹是不够的,还需要在项目中进行Add item来加入到项目中
3、创建对应的cpp文件 MyJni.cpp,然后同样的add item进去。
#include <jni.h>
#include "MyJni.h"
/*
* Class: com_tk_jni_MyJni
* Method: encrypt
* Signature: ([BI)[B
*/
JNIEXPORT jbyteArray JNICALL Java_com_tk_jni_MyJni_encrypt
(JNIEnv*, jclass, jbyteArray, jint) {
return NULL;
}
/*
* Class: com_tk_jni_MyJni
* Method: decrypt
* Signature: ([BI)[B
*/
JNIEXPORT jbyteArray JNICALL Java_com_tk_jni_MyJni_decrypt
(JNIEnv*, jclass, jbyteArray, jint) {
return NULL;
}
4、编译c++项目 (快捷键 ctrl+shift+B).如果没有问题,就表示你的jni环境都可以了!
5、编译好之后,就会在c++项目中的 x64/Debug 目录下,生成一个 MyTestProject.dll 的dll文件(文件名字跟你创建的项目名一致)。之后,只需要把该文件放到 C:\Windows\System32 目录下。然后使用 System.loadLibrary(“MyTestProject”); 进行加载就好。
这里主要是你放的目录,需要是 ${java.library.path} 里面。如果不知道你的 java.library.path 目录为哪个,可以直接 String value = System.getProperty(“java.library.path”) 来查看该value值。
6、到这里,一个简单的项目就可以了。
未完待续。
相关的rsa加密解密方法实现,请看 Jni:使用openssl库进行rsa加密解密(实现篇)