user1118764
user1118764

Reputation: 9845

Is it possible to generate 2 identical RSA ciphertext given the same plaintext and public key?

I'm playing around with RSA on Android, and I realize that RSA encryption generates different ciphertext given the same plaintext and public key, due to padding Is there a way to generate the same ciphertext given the same plaintext and public key?

Similarly, do digital signatures differ between runs given the same plaintext and private key, and is there a way to generate the same digital signatures?

Here's my keygen:

        KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
        AlgorithmParameterSpec spec = null;
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1 && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            spec = new KeyPairGeneratorSpec.Builder(ctx)
                    .setAlias(mAlias)
                    .setSubject(new X500Principal("CN=" + mAlias))
                    .setSerialNumber(BigInteger.valueOf(1337))
                    .setStartDate(start.getTime())
                    .setEndDate(end.getTime())
                    .build();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            spec = new KeyGenParameterSpec.Builder(mAlias,
                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                    .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                    .build();
        kpGenerator.initialize(spec);
        KeyPair kp = kpGenerator.generateKeyPair();

Here's how I'm encrypting:

        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(mAlias, null);
        Cipher cip = null;

        RSAPublicKey pubKey = (RSAPublicKey)entry.getCertificate().getPublicKey();
        cip = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cip.init(Cipher.ENCRYPT_MODE, pubKey);

        byte[] encryptBytes = cip.doFinal(challenge.getBytes());

Thanks.

Upvotes: 1

Views: 1637

Answers (1)

pedrofb
pedrofb

Reputation: 39291

To generate always the same cipher text use an algorithm with no padding. Replace RSA/ECB/PKCS1Padding with RSA/ECB/NoPadding.

But, for security reasons, I suggest to use an algorithm with padding, and if possible OAEP RSA/ECB/OAEPWithSHA-1AndMGF1Padding(It is available from android 23). The padding should not be a problem for the decryption side

A PCKS#1 digital signature will produce the same result for the same private key and data to sign

Upvotes: 2

Related Questions