我只是尝试使用以下代码,但我不明白为什么代码会这样做:
public class Test
{
public static void main(String args[]) throws Exception
{
CertificateFactory certificateFactory1 = CertificateFactory.getInstance("X.509");
X509Certificate certificate1 = (X509Certificate)certificateFactory1.generateCertificate(Test.class.getResourceAsStream("pub.cer"); //Loading ssl certificate
PublicKey pk1 = certificate1.getPublicKey();
Cipher cipher1 = Cipher.getInstance("RSA/ECB/NOPADDING");
cipher1.init(Cipher.ENCRYPT_MODE, pk1);
bytes[] encrypted = cipher1.doFinal("dummy".getBytes("UTF-8");
CertificateFactory certificateFactory2 = CertificateFactory.getInstance("X.509");
X509Certificate certificate2 = (X509Certificate)certificateFactory2.generateCertificate(Test.class.getResourceAsStream("pub.cer"); //Loading ssl certificate
PublicKey pk2 = certificate2.getPublicKey();
Cipher cipher2 = Cipher.getInstance("RSA/ECB/NOPADDING");
cipher2.init(Cipher.DECRYPT_MODE, pk2);
bytes[] decrypted = cipher2.doFinal(encrypted);
}
}
为什么在解密的byte[]
中我得到了doFinal
的输出?我使用的是jdk1.8.0_192。
因为我使用公钥进行解密,并且在非对称公钥加密中,我们可以使用公钥加密并使用私钥解密。
有人可以解释一下并希望用文档来支持它吗?
最佳答案
如果您指定NoPadding
,那么您基本上会得到模幂。当然,在此之前有一个将二进制输入转换为数字的步骤,然后再次从数字编码为二进制。有趣的是,对于加密和解密来说都是如此,因为这些操作对于 RSA 来说是相当对称的。
唯一的区别是您首先使用公钥进行加密,然后使用私钥进行解密。但是,有时您必须创建自己的验证方案。在这种情况下,使用公钥进行原始模幂运算将很好地给出(通常是填充的)结果。因此,使用公钥解密是有意义的,即使它在技术上不应该被称为解密。
总而言之,如果您的输入大小正确,而不仅仅是将输入解码为数字,则模块化加密(或解密)以及最终对结果进行编码将永远失败。因此,您只会得到与模数大小相同的输出,即 key 大小(以字节为单位)。 RSA 的取消填充可能会失败。但是您的代码只会运行,因为您没有执行任何取消填充操作。
当然,如果你使用了错误的模数和指数,解密的结果将没有任何意义;它看起来像一个介于 0 和上次操作使用的模数之间的随机数。
关于Java rsa解密模式行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58240432/