Java RSA加密不可重复?

时间:2011-01-21 11:34:27

标签: java cryptography rsa

我一直无法使用RSA公钥加密。以下是重现问题的示例JUnit代码:

public class CryptoTests {

private static KeyPair keys;

@BeforeClass
public static void init() throws NoSuchAlgorithmException{
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
    SecureRandom random = CryptoUtils.getSecureRandom();
    keyGen.initialize(2176, random);
    keys = keyGen.generateKeyPair();
}
@Test
public void testRepeatabilityPlainRSAPublic() throws EdrmCryptoException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{
    byte[] plaintext = new byte [10];
    Random r = new Random();
    r.nextBytes(plaintext);

    Cipher rsa = Cipher.getInstance("RSA");
    rsa.init(Cipher.ENCRYPT_MODE, keys.getPublic());
    byte[] encrypted1 =  rsa.doFinal(plaintext);

    rsa = Cipher.getInstance("RSA");
    rsa.init(Cipher.ENCRYPT_MODE, keys.getPublic());
    byte[] encrypted2 =  rsa.doFinal(plaintext);

    rsa = Cipher.getInstance("RSA");
    rsa.init(Cipher.ENCRYPT_MODE, keys.getPublic());
    byte[] encrypted3 =  rsa.doFinal(plaintext);

    assertArrayEquals(encrypted1, encrypted2);
    assertArrayEquals(encrypted1, encrypted3);
}
}

结果呢?断言失败了。

为什么会出现这种行为?据我记得我的加密类,任何密钥都可以用于加密。然而,这不是这里发生的事情。 我用私钥测试了同样的东西,我得到了一个可重复的输出。

如果出于某种原因,禁止使用公钥进行RSA加密,那么为什么我没有得到例外?

我该怎样做才能获得可重复的结果?

P.S。我的JDK是在Ubuntu 10.10盒子上运行的1.6.0_22。

3 个答案:

答案 0 :(得分:7)

我的猜测是它正在应用随机填充,正是为了使其更安全。来自RSA wikipedia page

  

由于RSA加密是一种确定性加密算法 - 即没有随机组件 - 攻击者可以通过加密公钥下的可能明文并测试它们是否等于密文,成功启动对密码系统的选定明文攻击。如果攻击者无法区分两个加密,即使攻击者知道(或已选择)相应的明文,也称为密码系统在语义上是安全的。如上所述,没有填充的RSA在语义上不安全。

...

  

为了避免这些问题,实际的RSA实现通常在加密之前将某种形式的结构化随机填充嵌入到值m中。这个填充确保m不会落入不安全的明文范围内,并且一旦填充,给定的消息将加密到大量不同的可能密文中的一个。

答案 1 :(得分:1)

您可以通过使用字符串“RSA / ECB / NoPadding”初始化您的密码来确认正在发生的事情是添加了随机填充。现在,您应该看到密文在每种情况下都是相同的(尽管出于另一个回答者所说的原因,您实际上不应该在实践中这样做。)

答案 2 :(得分:0)

为Jon的答案添加额外的细节:

当您执行Cipher.getInstance("...")时,您可能会收集许多选项。 The Standard Algorithm Names指明这些是什么。

您要求的那个,RSA默认为PKCS1下的RSA,引用维基百科文章:

  

有两种加密方案   和解密:

     
      
  • RSAES-OAEP:改进的加密/解密方案;基于   最优非对称加密   Mihir提出的填充方案   Bellare和Phillip Rogaway。
  •   
  • RSAES-PKCS1-v1_5:首先是较旧的加密/解密方案   在PKCS#1版本1.5中标准化。
  •   

有关所述填充方案的详细信息,请参阅RSALab的PKCS1 documentation