Android CMake轻松实现基于OpenSSL的RSA签名和验证

安全加密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,转载。

源码:https://github.com/GitPhoenix/OpenSSL

你可能感兴趣的:(Android CMake轻松实现基于OpenSSL的RSA签名和验证)