安全加密C语言库OpenSSL,在Android中服务器和客户端之间的签名验证和数据加密通信等。
OpenSSL系列文章:
一、Android CMake轻松实现基于OpenSSL的HmacSHA1签名
二、Android CMake轻松实现基于OpenSSL的SHA(1-512)签名
三、Android CMake轻松实现基于OpenSSL的MD5信息摘要&异或加解密
四、Android CMake轻松实现基于OpenSSL的AES加解密
五、Android CMake轻松实现基于OpenSSL的RSA加解密
六、Android CMake轻松实现基于OpenSSL的RSA签名和验证
七、在Retrofit的基础上结合OpenSSL实现服务器和客户端之间数据加密通信
RSA签名和验证:
RSA不仅仅用于数据加密中,还常常用于数据文件的签名验证中。假设A要向B发送消息,A要先计算出消息的摘要,然后用自己的私钥加密这段摘要,最后将加密后的消息摘要和消息一起发送给B,被加密的消息摘要就是“签名”。B收到消息后,也会使用和A相同的方法提取消息摘要,然后使用A的公钥解密A发来的签名,并与自己计算出来的消息摘要进行比较,如果相同则说明消息是A发送给B的;同时,A也无法否认自己发送消息的给B的事实。
A用自己的私钥给消息摘要加密称为“签名”,B使用A的公钥解密签名文件的过程叫做“验签”。
实现过程:
JNIEXPORT jbyteArray JNICALL
Java_com_alley_openssl_util_JniUtils_signByRSAPrivateKey(JNIEnv *env, jobject instance, jbyteArray keys_, jbyteArray src_) {
LOGI("RSA->非对称密码算法,也就是说该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密");
jbyte *keys = env->GetByteArrayElements(keys_, NULL);
jbyte *src = env->GetByteArrayElements(src_, NULL);
jsize src_Len = env->GetArrayLength(src_);
unsigned int siglen = 0;
unsigned char digest[SHA_DIGEST_LENGTH];
RSA *rsa = NULL;
BIO *keybio = NULL;
LOGI("RSA->从字符串读取RSA公钥");
keybio = BIO_new_mem_buf(keys, -1);
LOGI("RSA->从bio结构中得到RSA结构");
rsa = PEM_read_bio_RSAPrivateKey(keybio, NULL, NULL, NULL);
LOGI("RSA->释放BIO");
BIO_free_all(keybio);
unsigned char *sign = (unsigned char *) malloc(129);
memset(sign, 0, 129);
SHA1((const unsigned char *) src, src_Len, digest);
RSA_sign(NID_sha1, digest, SHA_DIGEST_LENGTH, sign, &siglen, rsa);
RSA_free(rsa);
LOGI("RSA->CRYPTO_cleanup_all_ex_data");
CRYPTO_cleanup_all_ex_data();
LOGI("RSA->从jni释放数据指针");
env->ReleaseByteArrayElements(keys_, keys, 0);
env->ReleaseByteArrayElements(src_, src, 0);
jbyteArray cipher = env->NewByteArray(siglen);
LOGI("RSA->在堆中分配ByteArray数组对象成功,将拷贝数据到数组中");
env->SetByteArrayRegion(cipher, 0, siglen, (jbyte *) sign);
LOGI("RSA->释放内存");
free(sign);
return cipher;
}
RSA签名验证,保持摘要算法一致。
JNIEXPORT jint JNICALL
Java_com_alley_openssl_util_JniUtils_verifyByRSAPubKey(JNIEnv *env, jobject instance, jbyteArray keys_, jbyteArray src_, jbyteArray sign_) {
LOGI("RSA->非对称密码算法,也就是说该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密");
jbyte *keys = env->GetByteArrayElements(keys_, NULL);
jbyte *src = env->GetByteArrayElements(src_, NULL);
jbyte *sign = env->GetByteArrayElements(sign_, NULL);
jsize src_Len = env->GetArrayLength(src_);
jsize siglen = env->GetArrayLength(sign_);
int ret;
unsigned char digest[SHA_DIGEST_LENGTH];
RSA *rsa = NULL;
BIO *keybio = NULL;
LOGI("RSA->从字符串读取RSA公钥");
keybio = BIO_new_mem_buf(keys, -1);
LOGI("RSA->从bio结构中得到RSA结构");
rsa = PEM_read_bio_RSA_PUBKEY(keybio, NULL, NULL, NULL);
LOGI("RSA->释放BIO");
BIO_free_all(keybio);
SHA1((const unsigned char *) src, src_Len, digest);
ret = RSA_verify(NID_sha1, digest, SHA_DIGEST_LENGTH, (const unsigned char *) sign, siglen, rsa);
RSA_free(rsa);
LOGI("RSA->CRYPTO_cleanup_all_ex_data");
CRYPTO_cleanup_all_ex_data();
LOGI("RSA->从jni释放数据指针");
env->ReleaseByteArrayElements(keys_, keys, 0);
env->ReleaseByteArrayElements(src_, src, 0);
env->ReleaseByteArrayElements(sign_, sign, 0);
return ret;
}
下载代码运行,在控制台中输入“body”,将看到所有调试信息。欢迎star,fork,转载。