1)我正在使用PKCS1_PADDING的公钥加密ruby中的消息。
2)然后将输出(ASCII-8BIT编码)转换为十六进制并将其发送到android devie。
3)在android上将十六进制转换为字节数组&使用私钥解密它,我得到了很多额外的字符。 (在android方面,它默认为RSA / NONE / PKCS1Padding)。
示例:
预期字符串:你好,你好吗?
实际字符串:V')f rBA ; \ : D .a 〜 A@ .P ( l - ך \ 0} nj。 ˚F@ƧWr[kEzo偣的 rK1D涮ú!t.UI?GA | XO @vKƏ'nF的 P܆09M9 * U S1和S2;→1; 3_〜 - )$ U *“ %/Oѡ k@ hello你好吗?
public String Decrypt (String result,String privKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
PrivateKey privateKey = getPrivateKeyFromString(privKey);
Cipher cipher1 = Cipher.getInstance("RSA");
cipher1.init(Cipher.DECRYPT_MODE, privateKey);
String decrypted="";
try {
byte[] bytes = hexStringToByteArray(result);
byte[] decryptedBytes = cipher1.doFinal(bytes);
decrypted = new String(decryptedBytes);
}catch (Exception e)
{
e.printStackTrace();
}
return decrypted;
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len/2];
for(int i = 0; i < len; i+=2){
data[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
}
return data;
}
require 'openssl'
require 'base64'
public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn6fT8ScFrW2FR5bxTeFzsD77nN1W+gL5XUB1yQVNL699y6WISopbQ6lls76XvKfyhJHn7ca8i5rDRXrNnaY1BVvX9n/jKWLw13AQcVG4SjMewMQbW1KXOWFe2cltGxB7dX+4xlnxRtXz26xtOpEoBdMN2LBB39WdMghaLIrzcNu9uj363KK8szs9x9rO9E5BNfaqePFwajJoOXjkc5PUwRHeW2DodQnKfxJhaBwotoBbD6zrx+XPqpEzXD7XLjq2i/MGEuw6XGLCGQ+/zaytiYCDe8gboQ5WkWQtfa0FALve9zguqjpoNouWaK4SBq1kyeFKsdsbmZLC8NdJlSruUQIDAQAB"
rsa_public_key = OpenSSL::PKey::RSA.new(Base64.decode64(public_key))
encrypted_string = rsa_public_key.public_encrypt('hello how are you doing ?', OpenSSL::PKey::RSA::PKCS1_PADDING)
encrypted_string.unpack("H*")
答案 0 :(得分:1)
为了获得最大的可移植性,您应该使用"RSA/ECB/PKCS1Padding"
作为密码的初始化字符串。
此字符串实际上已在Java Standard Algorithm Names中根据任何Java实现的要求进行了定义。当然Android还没有正式的Java,但是你可以肯定Google会尝试确保Java尽可能接近Java。所以这应该与任何Java(-ish)实现兼容。
Sun要求不的原因是上述字符串中的操作模式("ECB"
)和填充方案("PKCS1Padding"
)是{{1}的默认值}。这就是你必须明确指定的原因。永远不要依赖提供者特定的默认值 - 除非指定随机数生成器。
您目前获得的是"RSA"
方案,它使所有填充完好无损。因此,当您查看以字节为单位的明文大小时,它将与模数的字节大小相同。并且内容将是PKCS#1-padding,其(大部分)随机化用于每个加密。随机字节不能轻易转换为文本,所以你得到的主要看起来像垃圾。
注意:
"RSA/ECB/NoPadding"
对Sun来说有点用词不当,应该是"ECB"
,因为只有一个明文块可以加密(一般情况下); "None"
则更是如此。