https://www.cnblogs.com/eleclsc/p/12082000.html
轉:https://www.cnblogs.com/zengsf/p/10136886.html
在線rsa加解密工具:http://tool.chacuo.net/cryptrsaprikey
在linux環境中生成公私鑰:
openssl
然后生成私鑰:
genrsa -out app_private_key.pem 2048 # 私鑰的生成
在利用私鑰生成公鑰:
rsa -in app_private_key.pem -pubout -out app_public_key.pem #導出公鑰
這樣就生成了rsa2的私鑰和公鑰了。可以用於支付寶的公密鑰的生成
pkcs1轉pkcs8
openssl pkcs8 -topk8 -inform PEM -in app_private_key.pem -outform pem -nocrypt -out pkcs8.pem
1. 只需要使用pkcs1
Q:拉取的消息如何解密?
A:企業微信對待存儲的消息使用企業最新上傳的公鑰進行加密,企業自行使用對應版本的私鑰進行解密。對json消息體內的encrypt_random_key,base64處理后首先使用對應版本的私鑰進行解密得到字符串內容,將字符串內容與消息體內的encrypt_chat_msg,使用sdk的接口DecryptData,得到真正的明文消息。
這文檔寫的,稀爛。
如果只看上面的描述,並且你用Java去實現,那么在解密時,你十有八九是搞不定的。其實在接口文檔處,還有一處這樣的描述:
encrypt_random_key是使用企業在管理端填寫的公鑰(使用模值為2048bit的秘鑰),采用RSA加密算法進行加密處理后base64 encode的內容,加密內容為企業微信產生。RSA使用PKCS1。
企業得到消息內容后,需先進行base64 decode,使用消息指明版本的私鑰,使用RSA PKCS1算法進行解密,得到解密內容,為下一步進行消息明文解析做准備。
翻譯一下:
需要對接收到的消息中encrypt_random_key進行base64 decode, 然后使用對應的私鑰,使用rsa算法進行解密,注意需要使用RSA PKCS1。對於Java來說,大都使用PKCS8,所以需要注意在實現算法時,需要正確選擇文檔所說的算法。
私鑰是PKCS1(一般以如下開頭:begin rsa private key)或者是PKCS8(一般以 begin private key 開頭)版本的,都ok,只要選擇了正確的私鑰讀取方式就ok。
讀取公鑰:
public static PublicKey getPublicKey(String base64PublicKey){
PublicKey publicKey = null;
try{
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return publicKey;
}
讀取pkcs1格式的private key
public static PrivateKey getPrivateKey(String privKeyPEM) throws Exception{
String privKeyPEMnew = privKeyPEM.replaceAll("\\n", "").replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----", "");
byte[] bytes = java.util.Base64.getDecoder().decode(privKeyPEMnew);
DerInputStream derReader = new DerInputStream(bytes);
DerValue[] seq = derReader.getSequence(0);
BigInteger modulus = seq[1].getBigInteger();
BigInteger publicExp = seq[2].getBigInteger();
BigInteger privateExp = seq[3].getBigInteger();
BigInteger prime1 = seq[4].getBigInteger();
BigInteger prime2 = seq[5].getBigInteger();
BigInteger exp1 = seq[6].getBigInteger();
BigInteger exp2 = seq[7].getBigInteger();
BigInteger crtCoef = seq[8].getBigInteger();
RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, exp2, crtCoef);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
java rsa pkcs1解密實現:
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(cipher.doFinal(data));
加密時只需要在cipher.init時傳入對應mode為Cipher.ENCRYPT_MODE, publicKey即可。
對於已經base64 encode的字符串解密時,只需要先進行base64.decode,得到byte[]作為要解密的data進行解密即可。
參考資料:
https://www.devglan.com/java8/rsa-encryption-decryption-java
http://defned.com/post/java-rsa-pkcs1/
https://github.com/greigdp/Javacard-ALG_RSA_SHA256_PKCS1