這里主要是openssl常用的編碼Base64, 摘要算法MD5,對(duì)稱(chēng)加密AES, 非對(duì)稱(chēng)加密RSA與Java互通
一: openssl交叉編譯
openssl源碼下載, NDK下載
這里下載的openssl版本是1.1.0f, NDK版本是21, Ubuntu18,解壓openssl代碼包執(zhí)行 config或者Configure可以查看編譯時(shí)的附加參數(shù)列表, NDK如何編譯,在developer NDK文檔中都有詳細(xì)介紹,也有編譯時(shí)的示例腳本,要編譯的第三庫(kù)也一般會(huì)提供config, configure相關(guān)編譯參數(shù)文件,./執(zhí)行即可查看
就是根據(jù)下載的NDK包配置好編譯時(shí)對(duì)應(yīng)的CC(編譯C代碼)/CXX(編譯C++),在NDK21時(shí)都已經(jīng)采用clang(棄用了gcc)和SYSROOT等路徑,openssl1.1.0f是純C寫(xiě)的只要配置CC就行,這里編譯的shell腳本在項(xiàng)目源碼中,已經(jīng)編譯了arm64-v8a和armeabi-v7a的包
二:openssl與java互相加解密
openssl中文手冊(cè),這里只介紹C++與JAVA相互編解,加解密時(shí)的注意點(diǎn)
1:Base64
android已經(jīng)提供好android.util.Base64類(lèi), 編解碼時(shí)注意byte[]轉(zhuǎn)換編碼格式一致即可
const char *data = env->GetStringUTFChars(_data, JNI_FALSE);
//GetStringUTFChars 與java代碼data.getBytes(UTF8)對(duì)應(yīng)編碼一致即可
Base64.encode(data.getBytes(UTF8))
2:MD5
同樣在byte[]轉(zhuǎn)換時(shí)統(tǒng)一編碼格式,摘要算法后的byte[]統(tǒng)一轉(zhuǎn)16進(jìn)制及統(tǒng)一大小寫(xiě)即可
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結(jié)果 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[]轉(zhuǎn)換base64時(shí)的編碼也要一致 (如下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格式的公私鑰通過(guò)bouncycastlel轉(zhuǎn)換成DER格式及生成密鑰時(shí)的長(zhǎng)度一致即可, 加解密時(shí)的填充方式如(PKCS1Padding)一致
如部分轉(zhuǎn)換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);
}
測(cè)試如