微信小程序RSA加密与 Java RSA加密结果相同

mac2024-04-07  27

业务需要,小程序上送到后台的数据需要使用RSA加密,后台返回的数据需要RSA解密。折腾了好久,微信小程序的加解密结果始终不一样。终于解决这问题记录一下。

PS:后续使用过程中,发现小程序加密内容过长的话就会报错,又整理了一下小程序分段加解密放在另一篇文章中吧!

1.注意区分RSA私钥的类型,分为pkcs1和pkcs8, pkcs8格式的私钥主要用于Java中,微信小程序使用的私钥格式主要为pkcs1。所以要先生成pkcs1格式的私钥,然后转换成pkcs8格式私钥供java使用。

(需要用到OpenSSL,我是Win10,可以参考这里安装使用OpenSSL安装使用无需编译源代码原文链接)

生成pkcs1私钥:openssl genrsa -out rsa_private_key.pem 1024

pkcs1私钥转pkcs8私钥:openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform pem -nocrypt -out rsa_private_key_8.pem

pkcs1私钥转pkcs1公钥:openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

pkcs8私钥转pkcs8公钥:openssl rsa -in rsa_private_key_8.pem -pubout -out rsa_public_key_8.pem

(在私钥不使用密码的情况下,公钥的 pkcs1 和 pkcs8 格式内容应该是一模一样的)

java加密代码

public class UseRSAUtil { /** *//** * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 117; /** *//** * RSA最大解密密文大小 */ private static final int MAX_DECRYPT_BLOCK = 128; public static final String KEY_ALGORITHM = "RSA"; private static KeyFactory keyFactory = null; public static String PrivateKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALiT90DF4YZ8hAjW\n" + "j5FcjQdNXsCJnhWb8vV9F1iW3glIGKe5RVSiepfXr1nqhy1bK6/FhOPYRIFKzKOd\n" + "+eeRNmOS+ryDdJxbo+/yoDI5u0CV4Ycu1yGzjr3NxW675TextllQKA34XQykZN+9\n" + "h+eC83NM+Wn+7XH0sQHVXKtKA5APAgMBAAECgYB/0+F5V1GPvO4H3OhCqFD3DKsh\n" + "Nm1n07/YKZCghqMw1GBWz+Vm7rtuKy5CXDzPuYMw0N7umFkhHXdJnN90csmx0OnA\n" + "4E91eznT00Gn25ikio7/lruNTLabbTYdy3TT35q7ZHj0v8UeBSjl06VArt2detZt\n" + "vl1Ag9uXh/J9sbv7wQJBAN8O8o+et7vQXhyq/nUjxsSfnjwxSOBjJn/P4kdhpAdI\n" + "L0i4uFiSJA+N+KhKInxnQn8GWU2O3Sk9ZzfOniwLn2ECQQDT1jXAR9GUGp8Liep2\n" + "0EvY3+P8Xv4IcbeUbsQcds+O+xbRFn3XdsQ40S2BdnzJ3eDa7EEFU5mfTb/JxQwG\n" + "9pVvAkEAsPNUrWaF7zJvVmK4FglZp6XQi4O1gnxlkENECMiGrVgwWopfg7P7c3N2\n" + "7VpSXUo1UDujIInTHOIfPgBlLh/SQQJBALuYJk+aCjHjBVedkeIYAiMT2n0izkpC\n" + "EjXDha5DVPmkyAbvqQ+HIKvEKk1M1aOa9sZIlCgYaaHWo3IWKtl7wscCQQCFyINO\n" + "rzyHZTtJfjxVJTHQNpBLMEkZ2wIa3pn14Ruv16YRRcfRSmSDLBnYrqTlTzqoDJid\n" + "R4iA40R/dlGXErZ+"; public static String publicKey="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4k/dAxeGGfIQI1o+RXI0HTV7A\n" + "iZ4Vm/L1fRdYlt4JSBinuUVUonqX169Z6octWyuvxYTj2ESBSsyjnfnnkTZjkvq8\n" + "g3ScW6Pv8qAyObtAleGHLtchs469zcVuu+U3sbZZUCgN+F0MpGTfvYfngvNzTPlp\n" + "/u1x9LEB1VyrSgOQDwIDAQAB"; static { try { keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 解密方法 * @param dataStr 要解密的数据 * @return 解密后的原数据 * @throws Exception */ public static String decrypt(String dataStr) throws Exception{ //要加密的数据 System.out.println("要解密的数据:"+dataStr); //对私钥解密 Key decodePrivateKey = getPrivateKeyFromBase64KeyEncodeStr(PrivateKey); //Log.i("机密",""+decodePrivateKey); Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, decodePrivateKey); byte[] encodedData = Base64.decode(dataStr); byte[] decodedData = cipher.doFinal(encodedData); String decodedDataStr = new String(decodedData,"utf-8"); System.out.println("私钥解密后的数据:"+decodedDataStr); return decodedDataStr; } public static Key getPrivateKeyFromBase64KeyEncodeStr(String keyStr) { byte[] keyBytes = Base64.decode(keyStr); // 取得私钥 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); Key privateKey=null; try { privateKey = keyFactory.generatePrivate(pkcs8KeySpec); } catch (InvalidKeySpecException e) { // TODO Auto-generated catch block e.printStackTrace(); } return privateKey; } /** * 获取base64加密后的字符串的原始公钥 * @param keyStr * @return */ public static Key getPublicKeyFromBase64KeyEncodeStr(String keyStr) { byte[] keyBytes = Base64.decode(keyStr); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); Key publicKey = null; try { publicKey = keyFactory.generatePublic(x509KeySpec); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return publicKey; } /** * 公钥加密方法 * @param dataStr 要加密的数据 * @param dataStr 公钥base64字符串 * @return 加密后的base64字符串 * @throws Exception */ public static String encryptPublicKey(String dataStr) throws Exception{ //要加密的数据 System.out.println("要加密的数据:"+dataStr); byte[] data = dataStr.getBytes(); // 对公钥解密 Key decodePublicKey = getPublicKeyFromBase64KeyEncodeStr(publicKey); // 对数据加密 Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, decodePublicKey); byte[] encodedData = cipher.doFinal(data); String encodedDataStr = new String(Base64.encode(encodedData)); System.out.println("公钥加密后的数据:"+encodedDataStr); return encodedDataStr; } /** * 使用公钥进行分段加密 * @param dataStr 要加密的数据 * @return 公钥base64字符串 * @throws Exception */ public static String encryptByPublicKey(String dataStr) throws Exception { //要加密的数据 System.out.println("要加密的数据:"+dataStr); byte[] data = dataStr.getBytes(); // 对公钥解密 Key decodePublicKey = getPublicKeyFromBase64KeyEncodeStr(publicKey); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 对数据加密 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, decodePublicKey); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); String encodedDataStr = new String(Base64.encode(encryptedData),"utf-8"); System.out.println("公钥加密后的数据:"+encodedDataStr); return encodedDataStr; } /** * 使用私钥进行分段解密 * @param dataStr 使用base64处理过的密文 * @return 解密后的数据 * @throws Exception */ public static String decryptByPrivateKey(String dataStr) throws Exception { byte[] encryptedData = Base64.decode(dataStr); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key decodePrivateKey = getPrivateKeyFromBase64KeyEncodeStr(PrivateKey); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, decodePrivateKey); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); String decodedDataStr = new String(decryptedData,"utf-8"); System.out.println("私钥解密后的数据:"+decodedDataStr); return decodedDataStr; } /** * 仅适用于 String 其他的自己写 ,我用不到 懒得写 * @param context 上下文 * @param spKey key * @param defaultValue value * @return */ public static String acquireDataBySputils(Context context, String spKey, String defaultValue) { String spValue = (String) SPUtil.get(context, spKey, defaultValue); String decryptResult; try { decryptResult = decryptByPrivateKey(spValue); } catch (Exception e) { e.printStackTrace(); return spValue; } return decryptResult; } public static String decryptData(String data) { try { return UseRSAUtil.decryptByPrivateKey(data); } catch (Exception e) { e.printStackTrace(); return "{\"code\":\"999999\", \"data\":null, \"message\":\"数据解析出错(来自前端)\"}"; } } public static void main(String[] args) throws Exception { String jiami = UseRSAUtil.encryptByPublicKey("测试信息 "); System.out.println(jiami); String jiemi = UseRSAUtil.decryptByPrivateKey(jiami); System.out.println(jiemi); } }

小程序RSA加密可以参考这个,有demo。原文链接

最新回复(0)