音视频后端砖头

android使用openssl实现C++与JAVA互相RSA,

2022-04-22  本文已影响0人  youxiaochen

这里主要是openssl常用的编码Base64, 摘要算法MD5,对称加密AES, 非对称加密RSA与Java互通

一: openssl交叉编译

openssl源码下载, NDK下载
这里下载的openssl版本是1.1.0f, NDK版本是21, Ubuntu18,解压openssl代码包执行 config或者Configure可以查看编译时的附加参数列表, NDK如何编译,在developer NDK文档中都有详细介绍,也有编译时的示例脚本,要编译的第三库也一般会提供config, configure相关编译参数文件,./执行即可查看

NDK官方文档

就是根据下载的NDK包配置好编译时对应的CC(编译C代码)/CXX(编译C++),在NDK21时都已经采用clang(弃用了gcc)和SYSROOT等路径,openssl1.1.0f是纯C写的只要配置CC就行,这里编译的shell脚本在项目源码中,已经编译了arm64-v8a和armeabi-v7a的包

二:openssl与java互相加解密

openssl中文手册,这里只介绍C++与JAVA相互编解,加解密时的注意点

1:Base64

android已经提供好android.util.Base64类, 编解码时注意byte[]转换编码格式一致即可

const char *data = env->GetStringUTFChars(_data, JNI_FALSE);

//GetStringUTFChars 与java代码data.getBytes(UTF8)对应编码一致即可

Base64.encode(data.getBytes(UTF8))
2:MD5

同样在byte[]转换时统一编码格式,摘要算法后的byte[]统一转16进制及统一大小写即可

std::string MD5Code::md5(const char *src, size_t src_len) {
    unsigned char md[16];
    MD5((unsigned char *) src, src_len, md);
    char md5str[33]{0};  //MD5结果 32 + \0
    for (int i = 0; i < 16; i++) {
        sprintf(md5str, "%s%02x", md5str, md[i]);
    }
    return md5str;
}
3:AES

加密模式如ECB,CBC,填充方式一致即可如PKCS5Padding,ZEROPading,加密后的byte[]转换base64时的编码也要一致 (如下openssl部分填充方式代码)

void Padding::padding(std::string &src, int alignSize, PaddingModel mode) {
    int remainder = src.length() % alignSize;
    int paddingSize = (remainder == 0) ? alignSize : (alignSize - remainder);
    switch (mode) {
        case PKCS5OR7:
            src.append(paddingSize, paddingSize);
            break;
        case ZERO:
        default:
            src.append(paddingSize, 0);
            break;
    }
}
4: RSA (一般用加密AES需要的KEY)

openssl的公私钥采用的是PEM格式,JAVA采用的是DER格式,openssl生成的PEM格式的公私钥通过bouncycastlel转换成DER格式及生成密钥时的长度一致即可, 加解密时的填充方式如(PKCS1Padding)一致
如部分转换PEM成DER格式公钥代码

public static PublicKey getFromPemPublicKey(String public_key) throws Exception {
        byte[] keyBytes = new sun.misc.BASE64Decoder().decodeBuffer(public_key);
        ASN1InputStream in = new ASN1InputStream(keyBytes);
        DERObject obj = in.readObject();
        RSAPublicKeyStructure pStruct = RSAPublicKeyStructure.getInstance(obj);
        RSAPublicKeySpec spec = new RSAPublicKeySpec(pStruct.getModulus(), pStruct.getPublicExponent());
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(spec);
    }

测试如


测试!!

最后是源码地址

上一篇下一篇

猜你喜欢

热点阅读