在Android开发中,JNI(Java Native Interface)允许Java代码调用C/C++代码,这使得我们可以使用一些在Java标准库中不直接支持的底层功能,比如RSA加密。RSA是一种非对称加密算法,它使用两个密钥:公钥和私钥。公钥用于加密信息,而私钥用于解密信息。以下是如何在Android中使用JNI实现RSA加密的详细步骤。
1. 准备工作
首先,确保你的Android项目中已经包含了必要的C/C++开发环境。你需要在Android Studio中配置NDK(Native Development Kit)。
2. 创建C/C++源文件
创建一个C/C++源文件,比如native-lib.c,用于编写RSA加密的代码。
#include <jni.h>
#include <string.h>
#include <android/log.h>
#define LOG_TAG "RSAEncryption"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
// 引入RSA加密库的头文件
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
JNIEXPORT jstring JNICALL
Java_com_example_myapp_MainActivity_encrypt(JNIEnv *env, jobject thiz, jstring key, jstring data) {
const char *nativeKey = (*env)->GetStringUTFChars(env, key, 0);
const char *nativeData = (*env)->GetStringUTFChars(env, data, 0);
// 解析公钥
RSA *rsa = RSA_new();
BIO *pubBio = BIO_new_mem_buf((void *)nativeKey, strlen(nativeKey));
if (pubBio == NULL || !PEM_read_bio_RSAPublicKey(pubBio, &rsa, NULL, NULL)) {
LOGI("Failed to parse public key");
(*env)->ReleaseStringUTFChars(env, key, nativeKey);
(*env)->ReleaseStringUTFChars(env, data, nativeData);
return NULL;
}
// 加密数据
unsigned char *encrypted;
int encrypted_len = RSA_public_encrypt(strlen(nativeData), (unsigned char *)nativeData, &encrypted, rsa, RSA_PKCS1_OAEP_PADDING);
if (encrypted_len <= 0) {
LOGI("Failed to encrypt data");
(*env)->ReleaseStringUTFChars(env, key, nativeKey);
(*env)->ReleaseStringUTFChars(env, data, nativeData);
RSA_free(rsa);
BIO_free_all(pubBio);
return NULL;
}
// 转换为字符串
char *encrypted_str = (char *)malloc(encrypted_len * 2 + 1);
base64_encode(encrypted_str, encrypted_len, encrypted);
// 释放资源
RSA_free(rsa);
BIO_free_all(pubBio);
(*env)->ReleaseStringUTFChars(env, key, nativeKey);
(*env)->ReleaseStringUTFChars(env, data, nativeData);
free(encrypted);
// 返回加密后的字符串
jstring result = (*env)->NewStringUTF(env, encrypted_str);
free(encrypted_str);
return result;
}
注意:这里使用了OpenSSL库进行RSA加密,你需要确保你的Android设备上安装了OpenSSL。
3. 配置CMakeLists.txt
在Android项目的CMakeLists.txt文件中,添加以下代码来包含OpenSSL库:
find_library(
# Sets the name of the path variable.
openssl-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log
# Specifies the minimum version of the NDK
# library that you want CMake to locate.
1.1.3
)
find_library(
# Sets the name of the path variable.
openssl-ssl-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
ssl
# Specifies the minimum version of the NDK
# library that you want CMake to locate.
1.1.3
)
find_library(
# Sets the name of the path variable.
openssl-crypto-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
crypto
# Specifies the minimum version of the NDK
# library that you want CMake to locate.
1.1.3
)
target_link_libraries(
# Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${openssl-lib}
# Links the target library to the ssl library
# included in the NDK.
${openssl-ssl-lib}
# Links the target library to the crypto library
# included in the NDK.
${openssl-crypto-lib}
)
4. 编译并加载库
在Android Studio中,编译并加载你的JNI库。确保在build.gradle文件中配置了正确的NDK路径。
android {
...
ndk {
...
cppFlags += "-I${android.ndk.dir}/sources/cxx-stl/gnu-libstdc++/4.9/include"
cppFlags += "-I${android.ndk.dir}/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a"
}
...
}
5. 在Java中调用JNI方法
在你的Java代码中,调用JNI方法进行RSA加密:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("native-lib");
}
public native String encrypt(String key, String data);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String key = "your_public_key_here";
String data = "data_to_encrypt";
String encryptedData = encrypt(key, data);
Log.d("RSAEncryption", "Encrypted data: " + encryptedData);
}
}
这样,你就在Android中实现了JNI RSA加密。注意,这里只是一个简单的示例,实际应用中需要考虑更多的安全性和错误处理。