c语言实现rsa nopadding非对称加密算法(openssl api方式),匹配java后端 bouncycastle
来源:互联网 发布:淘宝法院拍卖怎么查找 编辑:程序博客网 时间:2024/06/05 05:13
公私钥:
—–BEGIN PUBLIC KEY—–
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC32V2IAfotG8bZhPF8/Bx8y65g
EDycAMyTWmvpPCfagEKORO/WvdkTYim7yhG/+pMs58wu86edP3LOK73VVlG1eeOg
shGVLsKRMYkFRFJ2a81VL2eOaZ8EyZazJ9bkGbNz+JRecx4LkPHdEZTRiSr7zQxN
f0UWR9Dxna1T7/C3twIDAQAB
—–END PUBLIC KEY—–
—–BEGIN RSA PRIVATE KEY—–
MIICXQIBAAKBgQC32V2IAfotG8bZhPF8/Bx8y65gEDycAMyTWmvpPCfagEKORO/W
vdkTYim7yhG/+pMs58wu86edP3LOK73VVlG1eeOgshGVLsKRMYkFRFJ2a81VL2eO
aZ8EyZazJ9bkGbNz+JRecx4LkPHdEZTRiSr7zQxNf0UWR9Dxna1T7/C3twIDAQAB
AoGBAIS0EDAhBTzUJOdTb6AAtmtZ9eb/MVCFvyTJisTSmA2+sMvSdLAzXuH/5BHZ
nJBPRTaPpjFpzF3Ts4GfzymTYev762lDaVNTId/md6mOcDHdkrBMpjLQcdJa8kv4
2gdxb9+1N+6X4wRh7DyIsow2gCKwrWE1rpf3M7xnqIBI3qSpAkEA3VzD/PAU9aDn
i3VJwEsML2eTJ52FdVAUtlvfaSnbUIgnTHNldCjVQUyT99bLs5FsRILnxM1+iFmH
dVUvZgGN6wJBANSd6NdtTcijOqy9wb/cqTaInCLNObGmLOHSrJcngpWOXtrrk5ZV
9JpKiNFycvM0j6+WS0aVERWjb3xo9msarmUCQAk1IJnWyqhk5vywBj9PX9Rg9IgD
T1fP2uyy6ZoQOaUh5LCTZDbus+AhdU4ryxFPDTfUUhuniInXX4EL6ArQKb0CQCY9
XGJag1Hhoazt2An02u429bYAqS69T3cyF957ua3CVGcVVY8FWJ/jZeYdqnT5cBpJ
crJ4HwGASo3apu8udk0CQQCzJ28e0WVCIwxgYK81FZgTxusaSjtkv4Dbz0BXvZLH
NX6zYO1fqM1Cm/FMqGtPvI8/O3AVJrcNeo4lgKvyDQVv
—–END RSA PRIVATE KEY—–
java中的公私钥 (只是去掉了头尾和换行,这样才能在java中使用):
static String prikey1024 = “MIICXQIBAAKBgQC32V2IAfotG8bZhPF8/Bx8y65gEDycAMyTWmvpPCfagEKORO/WvdkTYim7yhG/+pMs58wu86edP3LOK73VVlG1eeOgshGVLsKRMYkFRFJ2a81VL2eOaZ8EyZazJ9bkGbNz+JRecx4LkPHdEZTRiSr7zQxNf0UWR9Dxna1T7/C3twIDAQABAoGBAIS0EDAhBTzUJOdTb6AAtmtZ9eb/MVCFvyTJisTSmA2+sMvSdLAzXuH/5BHZnJBPRTaPpjFpzF3Ts4GfzymTYev762lDaVNTId/md6mOcDHdkrBMpjLQcdJa8kv42gdxb9+1N+6X4wRh7DyIsow2gCKwrWE1rpf3M7xnqIBI3qSpAkEA3VzD/PAU9aDni3VJwEsML2eTJ52FdVAUtlvfaSnbUIgnTHNldCjVQUyT99bLs5FsRILnxM1+iFmHdVUvZgGN6wJBANSd6NdtTcijOqy9wb/cqTaInCLNObGmLOHSrJcngpWOXtrrk5ZV9JpKiNFycvM0j6+WS0aVERWjb3xo9msarmUCQAk1IJnWyqhk5vywBj9PX9Rg9IgDT1fP2uyy6ZoQOaUh5LCTZDbus+AhdU4ryxFPDTfUUhuniInXX4EL6ArQKb0CQCY9XGJag1Hhoazt2An02u429bYAqS69T3cyF957ua3CVGcVVY8FWJ/jZeYdqnT5cBpJcrJ4HwGASo3apu8udk0CQQCzJ28e0WVCIwxgYK81FZgTxusaSjtkv4Dbz0BXvZLHNX6zYO1fqM1Cm/FMqGtPvI8/O3AVJrcNeo4lgKvyDQVv”;
static String pubkey1024 = “MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC32V2IAfotG8bZhPF8/Bx8y65gEDycAMyTWmvpPCfagEKORO/WvdkTYim7yhG/+pMs58wu86edP3LOK73VVlG1eeOgshGVLsKRMYkFRFJ2a81VL2eOaZ8EyZazJ9bkGbNz+JRecx4LkPHdEZTRiSr7zQxNf0UWR9Dxna1T7/C3twIDAQAB”;
java后端 使用bouncycastle的代码(bouncycastle需要去其官网下载http://www.bouncycastle.org/download/bcprov-debug-jdk15on-158.jar,或者下载其他可用版本也行):
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); public static String encrypt(String publicKey, String plainTextData) throws Exception {// if (TextUtils.isEmpty(publicKey)) {// throw new Exception("加密公钥为空, 请设置");// } X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(Base64.decode(publicKey,Base64.DEFAULT)); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey pubKey = keyFactory.generatePublic(bobPubKeySpec); Cipher cipher; try { cipher = Cipher.getInstance("RSA/NONE/nopadding"); cipher.init(Cipher.ENCRYPT_MODE, pubKey); byte[] output = cipher.doFinal(plainTextData.getBytes("UTF-8")); return Base64.encodeToString(output, Base64.NO_WRAP); } catch (Exception e) { e.printStackTrace(); throw new Exception(); } } public static String decrypt(String privateKey, String cipherData) throws Exception { if (privateKey == null) { throw new Exception("解密私钥为空, 请设置"); } PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey,Base64.DEFAULT)); KeyFactory keyf = KeyFactory.getInstance("RSA"); PrivateKey myprikey = keyf.generatePrivate(priPKCS8); Cipher cipher = null; try { cipher = Cipher.getInstance("RSA/NONE/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, myprikey); byte[] output = cipher.doFinal(Base64.decode(cipherData,Base64.DEFAULT)); return new String(output); } catch (Exception e) { e.printStackTrace(); throw new Exception(); } }
c语言通过编译openssl并调用api实现java中的RSA/NONE/NoPadding非对称加解密算法,代码(注意加密后要进行base64编码,解密前要进行base64解码):
string decryptRSA(const std::string& data) { int ret, flen; BIO *bio = NULL; RSA *r = NULL; if ((bio = BIO_new_mem_buf((void *)prikey1024, -1)) == NULL) //从字符串读取RSA私钥 { //LOGE("BIO_new_mem_buf failed!\n"); } // r = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); r = RSA_new(); PEM_read_bio_RSAPrivateKey(bio, &r, 0, 0);//读取私钥 flen = RSA_size(r); static std::string gkbn; gkbn.clear(); const char *gkbnP = gkbn.c_str(); char de[512] = {0}; memset(de, 0, (size_t)(512)); const char *dataP = data.c_str(); //RSA_private_encrypt rsa_ossl_private_decrypt ret = RSA_private_encrypt(flen, (const unsigned char *)dataP, (unsigned char *)de, r, RSA_NO_PADDING);//RSA_NO_PADDING //RSA_PKCS1_PADDING RSA_free(r); BIO_free(bio); CRYPTO_cleanup_all_ex_data(); //清除管理CRYPTO_EX_DATA的全局hash表中的数据,避免内存泄漏 char *result_c; int len; for (size_t i = 0; i < flen; i++) { if (de[i] != '\0') { result_c = &de[i]; break; } } len = strlen(result_c); printf("\ndecrypto:%s\n", result_c); gkbn.assign(result_c); // LOGD("解密明文:%s ret:%d",gkbn.c_str(), ret); return gkbn;string encryptRSA(const std::string& data, int *lenreturn) { int ret, flen,bio_len; BIO *bio = NULL; RSA *r = NULL; if ((bio = BIO_new_mem_buf((void *)pubkey1024, strlen(pubkey1024))) == NULL) //从字符串读取RSA公钥 { //LOGE("BIO_new_mem_buf failed!\n"); } PEM_read_bio_RSA_PUBKEY(bio, &r, 0, 0); flen = RSA_size(r); lenreturn = &flen; static std::string gkbn; gkbn.clear(); unsigned char *src = NULL; unsigned char *dst = NULL; src = (unsigned char *)OPENSSL_malloc(flen * 2);//填充0 到 128 长度 dst = (unsigned char *)OPENSSL_malloc(flen); memset(src, 0, flen * 2); memcpy(src, data.c_str(), data.size()); memset(dst, 0, flen + 1); // RSA_PKCS1_PADDING 最大加密长度 为 128 -11 //RSA_NO_PADDING 最大加密长度为 128 ret = RSA_public_encrypt(flen, src, dst, r, RSA_NO_PADDING);//RSA_NO_PADDING //RSA_PKCS1_PADDING gkbn.assign((char *)dst,ret); RSA_free(r); //OPENSSL_free(src); //OPENSSL_free(dst); BIO_free(bio); CRYPTO_cleanup_all_ex_data(); //清除管理CRYPTO_EX_DATA的全局hash表中的数据,避免内存泄漏 return gkbn;}}
测试:
c语言加密字符串”ceshi123”,通过调用encryptRSA函数加密
char origin_text[117] = "ceshi123";int retlen;string crypto = encryptRSA(origin_text,&retlen);crypto = TDBASE64::base64_encodestring(crypto);printf("%s", crypto.c_str());
得到结果:PC5At5PvCitwSio5TQK1gj/vsp3ffQMnu6LpXTJyhwZbCOS3t+PFZoYvUtUyZNvstp7KZMie8CoAVDbhfJP2H+AZDcnVQljKAQTpeb+VjjZJGQzFV42cxzKgNo2Oq3M/7EoAvJYWp7XFE7Y1/lOJSFdcfFjDD3zFX26I4c+TzDI=,然后用java解密,java解密后的结果为 :
发现末尾有乱码,暂时不管,后文再讨论
现在使用java加密”ceshi123”得到结果B3I3nI+DnI+Y8W8rzNOs9cRhWjfFu0CW+ac3Cf/b/vgR3fm/vQkM1oekT1hhm9BaYSc1usby3il0X1dv41s6d6mtFImUjs1p0ILWChHG0Nu6cAilE34bFhkBdp1eQJJXJ8gJ/6FxsH7yfNOsgtF9H+bjYDJNkofl+MiHfsVQAU8=,发现和c语言加密的结果不一样,不管,用c语言解密,解密代码
string testText = "B3I3nI+DnI+Y8W8rzNOs9cRhWjfFu0CW+ac3Cf/b/vgR3fm/vQkM1oekT1hhm9BaYSc1usby3il0X1dv41s6d6mtFImUjs1p0ILWChHG0Nu6cAilE34bFhkBdp1eQJJXJ8gJ/6FxsH7yfNOsgtF9H+bjYDJNkofl+MiHfsVQAU8="; testText = TDBASE64::base64_decodestring(testText); decryptRSA(testText);
观察结果发现结果有点怪异,虽然解密成功了,解密后的内存区域占用128个字节,但解密后的结果”ceshi123”并不在数组开始区域,而是在数组末尾,,后来通过翻看openssl源码发现,openssl在rsa nopadding下会在解密前和加密后进行填充,可以看到源码中的rsa_none.c源文件中的代码:
int RSA_padding_add_none(unsigned char *to, int tlen, const unsigned char *from, int flen){ if (flen > tlen) { RSAerr(RSA_F_RSA_PADDING_ADD_NONE, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); return (0); } if (flen < tlen) { RSAerr(RSA_F_RSA_PADDING_ADD_NONE, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE); return (0); } memcpy(to, from, (unsigned int)flen); return (1);}int RSA_padding_check_none(unsigned char *to, int tlen, const unsigned char *from, int flen, int num){ if (flen > tlen) { RSAerr(RSA_F_RSA_PADDING_CHECK_NONE, RSA_R_DATA_TOO_LARGE); return (-1); } memset(to, 0, tlen - flen); memcpy(to + tlen - flen, from, flen); return (tlen);}
函数 RSA_padding_add_none 会在加密前调用,而 RSA_padding_check_none会在解密后调用,
针对明文”ceshi123”解密测试中发现 ,openssl内部解密调用 RSA_padding_check_none 时,tlen=128,flen=8,num=128,(num在这里好像没看到调用) ,调用memset(to, 0, tlen - flen);
memcpy(to + tlen - flen, from, flen) 后就导致了数组中前面全是0,明文在末尾的情况,
结论,openssl的rsa nopadding并不能与 java bouncycastle 的 rsa nopadding完全匹配,当然手动处理出现0的情况也是可以的,比如去掉结果中出现0的字符,但可能某些情况会出现bug,推荐使用rsa pkcs1padding方式,这种方式openssl 可以完美匹配java bouncycastle的算法,可以互相加解密而不会出现上面有0的情况 ,下一篇直接上java 和c语言调用openssl的RSA/NONE/PCKS1PADDING代码
- c语言实现rsa nopadding非对称加密算法(openssl api方式),匹配java后端 bouncycastle
- c语言(openssl)实现rsa/none/pcks1padding算法,匹配java后端
- JAVA实现RSA非对称加密算法
- JAVA实现RSA加密,非对称加密算法
- RSA非对称加密算法Java实现
- 典型非对称加密算法RSA(Java)
- openssl 的RSA 非对称加密算法
- openssl 非对称加密算法RSA命令详解
- openssl 非对称加密算法RSA命令详解
- openssl 非对称加密算法RSA命令详解
- JAVA 非对称加密算法RSA
- Java非对称加密算法--RSA
- Java非对称加密算法RSA
- Java非对称加密算法--RSA加密算法
- 【RSA】openssl 非对称加密算法RSA命令详解
- RSA非对称加密算法Java实现之输出key文件
- C#RSA非对称加密算法/数字签名算法
- 非对称加密算法RSA
- linux内核panic/oops/crash分析(addr2line,objdump,gdb)
- sdnu-并查集-weeklyexam ——E
- Android系统开机动画修改
- Windows平台C++截屏程序
- 三维视觉之基础矩阵
- c语言实现rsa nopadding非对称加密算法(openssl api方式),匹配java后端 bouncycastle
- HTML画布
- 思科防火墙
- extjs4 grid combobox 联动
- Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www
- 【iOS】Xcode9 自动化脚本打包
- DOM操作
- ORA-01940: cannot drop a user that is currently connected 的解决办法
- pdf在线转换图片该如何进行操作