android JNI RSA 3DES BASE64 加解密实现

来源:互联网 发布:安恒数据库审计系统 编辑:程序博客网 时间:2024/05/15 13:02

android JNI RSA 3DES BASE64 加解密实现


2016-12-8 最新代码,基于Androidstudio 编译

鉴于之前c 代码用eclispe 编译,不太方便,现在已经 是 studio时代,重新写了一份demo,供大家参考。

开发工具:Android studio
库: openssl
编译环境: mac os
jni开发语言:C++
包含加密种类:RSA 3DES AES MD5 BASE64

此次基于android studio 的CmakeList 方式编译。
不会的话,可以看看这位大神的博客,写的很详细
http://blog.csdn.net/wzzfeitian/article/details/40963457/
还有不少示例,看懂了就没问题了。

gradle 配置:

apply plugin: 'com.android.application'android {    compileSdkVersion 25    buildToolsVersion "25.0.0"    defaultConfig {        applicationId "demo.rsa.gkbn.rsademo"        minSdkVersion 15        targetSdkVersion 25        versionCode 1        versionName "1.0"        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"        externalNativeBuild {            cmake {                cppFlags "-std=c++11 -frtti -fexceptions"                abiFilters "armeabi"            }        }    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }    externalNativeBuild {        cmake {            path "CMakeLists.txt"        }    }}dependencies {    compile fileTree(dir: 'libs', include: ['*.jar'])    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {        exclude group: 'com.android.support', module: 'support-annotations'    })    compile 'com.android.support:appcompat-v7:25.0.0'    testCompile 'junit:junit:4.12'}

CmakeList 文件配置:

cmake_minimum_required(VERSION 3.4.1)#导入头文件路径INCLUDE_DIRECTORIES(src/main/cpp/openssllib/include/openssl/)#链接库文件路径(.a .so 文件)LINK_DIRECTORIES(src/main/cpp/openssllib/)#编译源代码 ADD_LIBRARY(native SHARED src/main/cpp/native-lib.cpp  src/main/cpp/MyRSA.cpp  src/main/cpp/MyBASE64.cpp  src/main/cpp/My3DES.cpp  src/main/cpp/MyMD5.cpp  src/main/cpp/MyAES.cpp)#链接Android 日志库文件find_library( log-lib log)#编译.so 文件TARGET_LINK_LIBRARIES(  native  libcrypto.a libssl.a ${log-lib}) # 链接动态库

工程目录:
这里写图片描述

native文件:

#include <jni.h>#include <string>#include "MyRSA.h"#include <android/log.h>#include <iostream>#include "MyBASE64.h"#include "My3DES.h"#include "MyMD5.h"#include "Log.h"#include "MyAES.h"extern "C" {__attribute ((visibility ("default")))JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) //这是JNI_OnLoad的声明,必须按照这样的方式声明{    return JNI_VERSION_1_4; //这里很重要,必须返回版本,否则加载会失败。}__attribute ((visibility ("default")))JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {    //   __android_log_print(ANDROID_LOG_ERROR, "tag", "library was unload");}/** * base64加密 */__attribute ((visibility ("default")))JNIEXPORT jstring JNICALLJava_demo_rsa_gkbn_rsademo_JniDemo_encryptBase64(JNIEnv *env, jobject instance, jstring msg_) {    const char *msg = env->GetStringUTFChars(msg_, 0);    std::string msgC;    msgC.assign(msg);    std::string base64 = MyBASE64::base64_encodestring(msgC);    env->ReleaseStringUTFChars(msg_, msg);    return env->NewStringUTF(base64.c_str());}/** * base64 解密 */__attribute ((visibility ("default")))JNIEXPORT jstring JNICALLJava_demo_rsa_gkbn_rsademo_JniDemo_decryptBase64(JNIEnv *env, jobject instance, jstring msg_) {    const char *msg = env->GetStringUTFChars(msg_, 0);    std::string msgC;    msgC.assign(msg);    std::string base64 = MyBASE64::base64_decodestring(msgC);    env->ReleaseStringUTFChars(msg_, msg);    return env->NewStringUTF(base64.c_str());}/** * MD5加密算法 */__attribute ((visibility ("default")))JNIEXPORT jstring JNICALLJava_demo_rsa_gkbn_rsademo_JniDemo_MD5(JNIEnv *env, jobject instance, jstring msg_) {    const char *msg = env->GetStringUTFChars(msg_, 0);    std::string msgC;    msgC.assign(msg);    std::string f = MyMD5::encryptMD5(msgC);    env->ReleaseStringUTFChars(msg_, msg);    return env->NewStringUTF(f.c_str());}/** * AES加密算法 */__attribute ((visibility ("default")))JNIEXPORT jstring JNICALLJava_demo_rsa_gkbn_rsademo_JniDemo_encodeAES(JNIEnv *env, jobject instance, jstring msg_) {    const char *msg = env->GetStringUTFChars(msg_, 0);    std::string msgC;    msgC.assign(msg);    std::string aes = MyAES::encodeAES("1234567812345678", msgC);//密码长度必须大于16 位    std::string base64 = MyBASE64::base64_encodestring(aes);    env->ReleaseStringUTFChars(msg_, msg);    return env->NewStringUTF(base64.c_str());}/** * AES解密算法 */__attribute ((visibility ("default")))JNIEXPORT jstring JNICALLJava_demo_rsa_gkbn_rsademo_JniDemo_decodeAES(JNIEnv *env, jobject instance, jstring msg_) {    const char *msg = env->GetStringUTFChars(msg_, 0);    std::string msgC;    msgC.assign(msg);    int length;    std::string base64 = MyBASE64::base64_decodestring(msgC);    std::string aes = MyAES::decodeAES("1234567812345678", base64);    env->ReleaseStringUTFChars(msg_, msg);    return env->NewStringUTF(aes.c_str());}/** * DES加密算法 */__attribute ((visibility ("default")))JNIEXPORT jstring JNICALLJava_demo_rsa_gkbn_rsademo_JniDemo_encryptDES(JNIEnv *env, jobject instance, jstring msg_) {    const char *msg = env->GetStringUTFChars(msg_, 0);    std::string msgC;    msgC.assign(msg);    int length;    std::string key = "12345678";    std::string des = My3DES::encryptDES(msgC, key, &length);    std::string base64 = MyBASE64::base64_encodestring(des);    env->ReleaseStringUTFChars(msg_, msg);    return env->NewStringUTF(base64.c_str());}/** * * DES解密算法 */__attribute ((visibility ("default")))JNIEXPORT jstring JNICALLJava_demo_rsa_gkbn_rsademo_JniDemo_decryptDES(JNIEnv *env, jobject instance, jstring msg_) {    const char *msg = env->GetStringUTFChars(msg_, 0);    std::string msgC;    msgC.assign(msg);    std::string key = "12345678";    int length;    std::string base64 = MyBASE64::base64_decodestring(msgC);    std::string des = My3DES::decryptDES(base64, key, base64.length());    env->ReleaseStringUTFChars(msg_, msg);    return env->NewStringUTF(des.c_str());}/** * RSA解密算法 */__attribute ((visibility ("default")))JNIEXPORT jstring JNICALLJava_demo_rsa_gkbn_rsademo_JniDemo_decryptRSA(JNIEnv *env, jobject instance, jstring msg_) {    const char *msg = env->GetStringUTFChars(msg_, 0);    std::string msgC;    msgC.assign(msg);    std::string base64 = MyBASE64::base64_decodestring(msgC);    std::string rsa = MyRSA::decryptRSA(base64);    env->ReleaseStringUTFChars(msg_, msg);    return env->NewStringUTF(rsa.c_str());}/** * RSA  加密算法 */__attribute ((visibility ("default")))JNIEXPORT jstring JNICALLJava_demo_rsa_gkbn_rsademo_JniDemo_encryptRSA(JNIEnv *env, jobject instance, jstring msg_) {    const char *msg = env->GetStringUTFChars(msg_, 0);    std::string msgC;    msgC.assign(msg);    std::string rsa = MyRSA::encryptRSA(msgC, NULL);    std::string base64 = MyBASE64::base64_encodestring(rsa);    env->ReleaseStringUTFChars(msg_, msg);    return env->NewStringUTF(base64.c_str());}}

此工程是楼主花了几天心血完成。其他代码太多,请下载demo自行查看,顺便送点积分吧。
工程demo 地址:

http://download.csdn.net/detail/gao1040841994/9705385


基于openssl ,实现androidRSA 3DES BASE64 jni加解密

客户端:使用公钥,加密动态生成的3DES秘钥,用3des秘钥加密报文。拼接报文
服务器:使用私钥,解密到3des秘钥后,用3des秘钥加密报文并返回,改秘钥加密的数据给客户端

java 代码

    private byte[] bkey;    // java 动态层生成的 3des 秘钥的 二进制数据,     如果你的项目 3des 秘钥是写死的 ,那恭喜你,直接在c 代码里面写死    static {        System.loadLibrary("demo");    }    public native  String Encrypt( byte[] deskey,String  msg,);    public native  int Decrypt(String  src, byte[] deskey);    public ConnectionTask(byte[] bkey2){        KeyGenerator kg = KeyGenerator.getInstance("DESede");        kg.init(168);        //生成秘密密钥        SecretKey secretKey = kg.generateKey();        //获得密钥的二进制编码形式        bkey=secretKey.getEncoded();    }

C 语言代码

#include <jni.h>#include <android/log.h>#include <string.h>#include <openssl/bio.h>#include <openssl/buffer.h>#include <openssl/des.h>#include <openssl/evp.h>#include <openssl/rsa.h>#include <unistd.h>#define TAG "myDemo-jni" // 这个是自定义的LOG的标识#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型#define  PUBLIC_EXPONENT   RSA_F4 //默认不用改//RSA 质子  可以用公钥的 密文代替,请自行查阅,或使用公钥 得出质子 替换这个值#define   MODULUS "9c847aae8aa567d36af169dbed35f42f9568d137067b30a204476897020e7d88914d1c03a671c62be4a05fbd645bd358b2ff38ad2e5166003414eb7b155301d1f6cacaa54260261073e1c02947379614e6b6123e5b35af50dc675f1c673565906cc4acb967976e209bad50d24ab38b6822198644de43874e4fb92714f6fd677d"# ifdef  __cplusplusextern "C" {# endif//隐藏符号表 ,加大反编译难度__attribute ((visibility ("default")))JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void *reserved) //这是JNI_OnLoad的声明,必须按照这样的方式声明{return JNI_VERSION_1_4; //这里很重要,必须返回版本,否则加载会失败。}__attribute ((visibility ("default")))JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved){ //   __android_log_print(ANDROID_LOG_ERROR, "tag", "library was unload");}/*** 字符串左补位函数 (超长会自动截断)* @dest 原字符串* @src 填充字符* @len 总长度* return 补位后字符串*/char *Lzero(char *dest,char *src,int len){static char res[1024];memset(res,0x00,sizeof(res));int dlen=strlen(dest);if(dlen>=len){memcpy(res, dest,len);}else{     int blen=0;while(blen<(len-dlen)){res[blen]=src[0];blen++;}memcpy(res+len-dlen,dest,dlen);}return (res);}/** * 字符串右补位函数 (超长会自动截断) * @dest 原字符串 * @src 填充字符 * @len 总长度 * return 补位后字符串 */char *Rzero(char *dest, char *src, int len) {    static char res[1024];    memset(res, 0x00, sizeof(res));    int dlen = strlen(dest);    if (dlen >= len) {        memcpy(res, dest, len);    } else {        memcpy(res, dest, dlen);        while (dlen < len) {            res[dlen] = src[0];            dlen++;        }    }    return (res);}unsigned char * encryptDES(const char *data, char *k,int *lenreturn);unsigned char * decryptDES(const char *data, int data_len, char *k);//jstring to char*char* jstringTostring(JNIEnv* env, jstring jstr) {    char* rtn = NULL;    jclass clsstring = (*env)->FindClass(env, "java/lang/String");    jstring strencode = (*env)->NewStringUTF(env, "utf-8");    jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes",            "(Ljava/lang/String;)[B");    jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid,            strencode);    jsize alen = (*env)->GetArrayLength(env, barr);    jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);    if (alen > 0) {        rtn = (char*) malloc(alen + 1);        memcpy(rtn, ba, alen);        rtn[alen] = 0;    }    (*env)->ReleaseByteArrayElements(env, barr, ba, 0);    return rtn;}/***BASE64 解码*/static void openssl_base64_decode(char *encoded_bytes,        unsigned char **decoded_bytes, int *decoded_length) {    BIO *bioMem, *b64;    size_t buffer_length;    bioMem = BIO_new_mem_buf((void *) encoded_bytes, -1);    b64 = BIO_new(BIO_f_base64());    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);    bioMem = BIO_push(b64, bioMem);    buffer_length = BIO_get_mem_data(bioMem, NULL);    *decoded_bytes = malloc(buffer_length);    if (decoded_bytes == NULL) {        BIO_free_all(bioMem);        *decoded_length = 0;        return;    }    *decoded_length = BIO_read(bioMem, *decoded_bytes, buffer_length);    BIO_free_all(bioMem);}/* Return NULL if failed, REMEMBER to free()  BASE64 加密*/static char *openssl_base64_encode(unsigned char *decoded_bytes,        size_t decoded_length) {    int x;    BIO *bioMem, *b64;    BUF_MEM *bufPtr;    char *buff = NULL;    b64 = BIO_new(BIO_f_base64());    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);    bioMem = BIO_new(BIO_s_mem());    b64 = BIO_push(b64, bioMem);    BIO_write(b64, decoded_bytes, decoded_length);    x = BIO_flush(b64);    if (x < 1)        goto END;    BIO_get_mem_ptr(b64, &bufPtr);    buff = (char *) malloc(bufPtr->length + 1);    if (buff == NULL)        goto END;    memcpy(buff, bufPtr->data, bufPtr->length);    buff[bufPtr->length] = 0;    END: BIO_free_all(b64);    return buff;}// demo请求格式: BASE64(RSA(3DES密钥))| BASE64(3DES(报文原文))  仿httpS原理 实现__attribute ((visibility ("default")))jstring  Java_com_example_demojiami_ConnectionTask_Encrypt(JNIEnv *env,        jclass obj, jbyteArray Deskey, jstring msg ) {    jsize i4PlaintTextLen = (*env)->GetArrayLength(env, Deskey);    jbyte * pKey = (jbyte*) (*env)->GetByteArrayElements(env, Deskey, 0);    int ret, flen;    BIGNUM *bnn, *bne;    bnn = BN_new();    bne = BN_new();    BN_hex2bn(&bnn, MODULUS);    BN_set_word(bne, PUBLIC_EXPONENT);    RSA *r = RSA_new();    r->n = bnn;    r->e = bne;    RSA_print_fp(stdout, r, 5);    flen = RSA_size(r);    static char cipherText[129];        memset(cipherText, 0x00, sizeof(cipherText));        unsigned char *pCipherText = cipherText;  char * gkbna= Rzero( (unsigned char *) pKey,"000",128);    ret = RSA_public_encrypt(flen-11 ,gkbna, pCipherText, r,    RSA_PKCS1_PADDING);    RSA_free(r);//***************************************************************************************************************//  BASE64(RSA(3DES密钥))    char *two = openssl_base64_encode(pCipherText,128);//  LOGE("two=%s", two);//*********************************************************************************RSA***// 第二段内容    unsigned char *cipher;    unsigned char *pmsg = jstringTostring(env, msg);int lenadd=strlen(pmsg)%8;char *des= Rzero(pmsg,"\0",strlen(pmsg)+(8-lenadd));int lenth;    cipher = encryptDES(pmsg, (char *) pKey,&lenth);    if(pmsg!=NULL){        free(pmsg);        pmsg=NULL;        }    if(cipher==NULL)  return (*env)->NewStringUTF(env, "null");    (*env)->ReleaseByteArrayElements(env, Deskey, pKey, 0);    char *three = openssl_base64_encode(cipher, lenth);    char * line = "|";    char *result = malloc(            strlen(two) + strlen(line)                    + strlen(three) + 1); //+1 for the zero-terminator    strcat(result, two);    strcat(result, line);    strcat(result, three);    two = NULL;    three = NULL;    cipher = NULL;    three = NULL;    line = NULL;    pmsg = NULL;    machid = NULL;    return (*env)->NewStringUTF(env, result);}//解密方法 __attribute  ((visibility ("default")))jstring  Java_com_example_demojiami_ConnectionTask_Decrypt(JNIEnv *env, jclass thiz,        jstring msg, jbyteArray key ) {    jbyte * pKey = (jbyte*) (*env)->GetByteArrayElements(env, key, 0);    if (!pKey ) {        return (*env)->NewStringUTF(env, "null");    }unsigned char *pmsg = jstringTostring(env, msg); unsigned char *decode;int lenth;openssl_base64_decode(pmsg,&decode, &lenth);    char *result = decryptDES(decode, lenth,(char *)pKey );    (*env)->ReleaseByteArrayElements(env, key, pKey, 0);        decode=NULL; if(pmsg!=NULL){    free(pmsg);    pmsg=NULL;    }    if(result!=NULL){    return (*env)->NewStringUTF(env, result);    }    return (*env)->NewStringUTF(env, "null");}unsigned char * encryptDES(const char *data, char *key, int * lenreturn) {    int docontinue = 1;//  char *data = "gubojun"; /* 明文 */    int data_len;    int data_rest;    unsigned char ch;    unsigned char *src = NULL; /* 补齐后的明文 */    unsigned char *dst = NULL; /* 解密后的明文 */    int len;    unsigned char tmp[8];    unsigned char in[8];    unsigned char out[8];//  char *k = "12345678"; /* 原始密钥 */    int key_len;#define LEN_OF_KEY 24//  unsigned char key[LEN_OF_KEY]; /* 补齐后的密钥 */    unsigned char block_key[9];    DES_key_schedule ks, ks2, ks3;    /* 构造补齐后的密钥 */    //key_len = strlen(k);//  LOGE("key_len=%d", key_len);//  memcpy(key, k, key_len);//  memset(key + key_len, 0x00, LEN_OF_KEY - key_len);    /* 分析补齐明文所需空间及补齐填充数据 */    data_len = strlen(data);    data_rest = data_len % 8;    len = data_len + (8 - data_rest);    ch = 8 - data_rest;    src = (unsigned char *) malloc(len);    dst = (unsigned char *) malloc(len);    if (NULL == src || NULL == dst) {        docontinue = 0;    }    if (docontinue) {        int count;        int i;        /* 构造补齐后的加密内容 */        memset(src, 0, len);        memcpy(src, data, data_len);        memset(src + data_len, ch, 8 - data_rest);        /* 密钥置换 */        memset(block_key, 0, sizeof(block_key));        memcpy(block_key, key + 0, 8);        DES_set_key_unchecked((const_DES_cblock*) block_key, &ks);        memcpy(block_key, key + 8, 8);        DES_set_key_unchecked((const_DES_cblock*) block_key, &ks2);        memcpy(block_key, key + 16, 8);        DES_set_key_unchecked((const_DES_cblock*) block_key, &ks3);        /* 循环加密/解密,每8字节一次 */        count = len / 8;        for (i = 0; i < count; i++) {            memset(tmp, 0, 8);            memset(in, 0, 8);            memset(out, 0, 8);            memcpy(tmp, src + 8 * i, 8);            /* 加密 */////          DES_ecb_encrypt((const_DES_cblock*) tmp, (DES_cblock*) in,//                  &schedule, DES_ENCRYPT);            DES_ecb3_encrypt((const_DES_cblock*) tmp, (DES_cblock*) in, &ks,                    &ks2, &ks3,                    DES_ENCRYPT);            /* 解密 *///          DES_ecb3_encrypt((const_DES_cblock*) in, (DES_cblock*) out, &ks,//                  &ks2, &ks3, DES_DECRYPT);            /* 将解密的内容拷贝到解密后的明文 *///          memcpy(dst + 8 * i, out, 8);            memcpy(dst + 8 * i, in, 8);        }    }    *lenreturn = len;    if (NULL != src) {        free(src);        src = NULL;    }    if (NULL != dst) {        return dst;    }    return NULL;}unsigned char * decryptDES(const char *data, int data_len, char *key) {    int docontinue = 1;//  char *data = "gubojun"; /* 明文 *///  int data_len;    int data_rest;    unsigned char ch;    unsigned char *src = NULL; /* 补齐后的明文 */    unsigned char *dst = NULL; /* 解密后的明文 */    int len;    unsigned char tmp[8];    unsigned char in[8];    unsigned char out[8];//char *k = "12345678"; /* 原始密钥 *///  int key_len;//#define LEN_OF_KEY 24//  unsigned char key[LEN_OF_KEY]; /* 补齐后的密钥 */    unsigned char block_key[9];    DES_key_schedule ks, ks2, ks3;    /* 构造补齐后的密钥 *///  key_len = strlen(k);//  memcpy(key, k, key_len);//  memset(key + key_len, 0x00, LEN_OF_KEY - key_len);    /* 分析补齐明文所需空间及补齐填充数据 */    data_rest = data_len % 8;    len = data_len;    src = (unsigned char *) malloc(len);    dst = (unsigned char *) malloc(len);    if (NULL == src || NULL == dst) {        docontinue = 0;    }    if (docontinue) {        int count;        int i;        /* 构造补齐后的加密内容 */        memset(src, 0, len);        memcpy(src, data, data_len);        /* 密钥置换 */        memset(block_key, 0, sizeof(block_key));        memcpy(block_key, key + 0, 8);        DES_set_key_unchecked((const_DES_cblock*) block_key, &ks);        memcpy(block_key, key + 8, 8);        DES_set_key_unchecked((const_DES_cblock*) block_key, &ks2);        memcpy(block_key, key + 16, 8);        DES_set_key_unchecked((const_DES_cblock*) block_key, &ks3);        /* 循环加密/解密,每8字节一次 */        count = len / 8;        for (i = 0; i < count; i++) {            memset(tmp, 0, 8);            memset(out, 0, 8);            memcpy(tmp, src + 8 * i, 8);            /* 加密 *///          DES_ecb3_encrypt((const_DES_cblock*) tmp, (DES_cblock*) in, &ks,//                  &ks2, &ks3, DES_ENCRYPT);            /* 解密 */            DES_ecb3_encrypt((const_DES_cblock*) tmp, (DES_cblock*) out, &ks,                    &ks2, &ks3,                    DES_DECRYPT);            /* 将解密的内容拷贝到解密后的明文 */            memcpy(dst + 8 * i, out, 8);        }        for (i = 0; i < len; i++) {            if (*(dst + i) < 9) {                *(dst + i) = 0;                break;            }        }    }    if (NULL != src) {        free(src);        src = NULL;    }    if (NULL != dst) {        return dst;    }    return NULL;}#  ifdef  __cplusplus}#  endif

附demo代码地址:http://download.csdn.net/detail/gao1040841994/9630750

0 0