Java RSA解密模式行为

问题描述 投票:-1回答:2

我只是在尝试下面的代码,但是我不明白为什么代码会像这样运行:

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。

因为我使用公共密钥进行解密,并且在非对称公共密钥加密中,我们可以使用公共密钥进行加密,而可以使用私有密钥进行解密。

有人可以解释一下并希望通过文档进行备份吗?

java encryption cryptography rsa public-key-encryption
2个回答
1
投票
如果指定NoPadding,则基本上可以得到模幂。当然,在此之前,有一个步骤将二进制输入转换为数字,然后再将编码从数字转换为二进制。有趣的是,加密和解密都是如此,因为这些操作对于RSA而言是相当对称的。

唯一的区别是您首先使用公共密钥进行加密,并使用

私有密钥进行解密。但是,有时您必须创建自己的verification方案。在这种情况下,原始的模块化指数使用公钥将很好地给您(通常填充)结果。因此,使用decryption和公钥是有道理的,即使从技术上讲不应将其称为解密。

总而言之,如果您输入的大小不仅仅只是将输入解码为数字,则模块化加密(或解密)并最终对结果进行编码将

从不

失败。因此,您只会得到与模数大小相同的输出,即密钥大小(以字节为单位)。 RSA的取消填充可能会失败。但是您的代码将只运行,因为您无需进行任何填充。当然,如果使用错误的模数和指数,则解密的结果将毫无意义;它看起来像是介于0和上一次操作所使用的模数之间的随机数。

0
投票
https://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html#init(int,%20java.security.Key)

抛出:InvalidKeyException-如果给定密钥不适合初始化此密码,或者需要无法从给定密钥确定的算法参数,或者给定密钥的密钥大小超过最大允许密钥大小(由配置的管辖权策略文件确定) 。

RSA在解密模式下要求使用PrivateKey实例而不是PublicKey,因此,上例的情况2将引发此异常。

[如果您想知道为什么它不会产生编译时错误,PublicKey和PrivateKey都扩展了Key Class,因此,两种情况都满足了Cipher.init(int,Key)签名。

© www.soinside.com 2019 - 2024. All rights reserved.