Java RSA encryption not repeated?

I have a problem with RSA public key encryption. Here is a sample JUnit code that reproduces the problem:

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); } } 

Result? The statement fails.

Why is this behavior observed here? As far as I remember from my cryptographic classes, any key can be used for encryption. But that is not what is happening here. I tested the same with the private key, and get repeatable output.

If, for some reason, RSA public key encryption is prohibited, then why am I not getting an exception?

What should I do to get duplicate results?

PS My JDK is 1.6.0_22 working in a Ubuntu 10.10 window.

0
source share
3 answers

I guess he uses randomized padding to make it safer. On the RSA wikipedia page:

Since RSA encryption is a deterministic encryption algorithm, that is, it does not have a random component, an attacker can successfully launch a selected plaintext attack against the cryptosystem, by encrypting the likely plaintexts under the public key and checking if they are equal to the encrypted text. The cryptosystem is called semantically secure if the attacker cannot distinguish two encryption from each other, even if the attacker knows (or chose) the appropriate plaintexts. As described above, RSA without padding is not semantically safe.

...

To avoid these problems, practical RSA implementations usually embed some form of structured randomized addition into the m value before encrypting it. This filling ensures that m does not fall into the range of unsafe plaintexts and that this message, after filling, will encrypt one of the large number of different possible encrypted texts.

+7
source

You can confirm that a random addition is being added by initializing your cipher with the string "RSA / ECB / NoPadding". Now you should see that the ciphertext is identical in each case (although for the reasons indicated by another responder, you really should not do this in practice).

+1
source

To add additional information to Jon's answer:

When you execute Cipher.getInstance("...") , you have several options, as you probably have compiled. The names of standard algorithms determine what it is.

The one you requested, RSA by default is RSA under PKCS1 , which, citing a wikipedia article:

There are two encryption schemes and decryption:

  • RSAES-OAEP: advanced encryption / decryption scheme; based on Optimal asymmetric encryption Layout scheme proposed by Mihir Bellar and Phillip Rogaway.
  • RSAES-PKCS1-v1_5: an earlier encryption / decryption scheme as the first is standardized in version 1.5 of PKCS # 1.

See the RSALab PKCS1 documentation for details of these fill patterns.

0
source

Source: https://habr.com/ru/post/918149/


All Articles