Java RSA加密不可重复?

mal*_*ere 0 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);
}
}
Run Code Online (Sandbox Code Playgroud)

结果?断言失败了.

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

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

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

PS我的JDK是在Ubuntu 10.10盒子上运行的1.6.0_22.

Jon*_*eet 7

我的猜测是,它正在应用随机填充,正是为了使其更安全.来自RSA维基百科页面:

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

...

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