3

We have a client server system where client(Android phone) and server(spring ) both are using java.security.KeyFactory to get an instance of java.security.KeyFactory as shown below:

KeyFactory factory = KeyFactory.getInstance("RSA"); 

But if we do that, when we use this factory to encrypt data, the server gives a different output and the client gives different output. When we checked providers, it was coming to SunRsaSign for server and was OpenSSLRSA for the client. So we tried to set the same on the client using the following:

KeyFactory factory = KeyFactory.getInstance("RSA", "SunRsaSign"); 

But we get java.security.NoSuchProviderException error. Similarly when we try to set OpenSSLRSA on server, they also face the same error.

Complete code to encrypt is same on server and client is following:

String pubKey = "<key here>" byte[] keyData = DatatypeConverter.parseHexBinary(pubKey); System.out.println("key data" + Arrays.toString(keyData)); KeyFactory factory = KeyFactory.getInstance("RSA"); //System.out.println("provide = " + factory.getProvider()); PublicKey pub = factory.generatePublic(new X509EncodedKeySpec(keyData)); Cipher encryptCipher = Cipher.getInstance("RSA"); encryptCipher.init(Cipher.ENCRYPT_MODE, pub); byte[] secretMessageBytes = msg.getBytes(StandardCharsets.UTF_8); System.out.println("secret msg" +Arrays.toString(secretMessageBytes)); byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes); System.out.println("enc data" +Arrays.toString(encryptedMessageBytes)); 

encryptedMessageBytes generated are different. Can that be a problem? I think it is because of different Providers being used by different platform.

Can somebody pls help me on how to set the provider for KeyFactory or how to remove the decryption error(javax.crypto.BadPaddingException)?

9
  • What exactly do you use the factory for, for the key import? How sure are you that the problem is really the factory? Maybe you should post the code for import and encryption of both sides. Which Android version are you using? Commented Jul 14, 2021 at 9:07
  • 1
    Also note that RSA encryption generates different ciphertexts for identical input data. This alone is not an indication of a problem. Commented Jul 14, 2021 at 9:20
  • @user9014097 added the encryption code. Commented Jul 14, 2021 at 10:05
  • 1
    Try also Cipher.getInstance("RSA/ECB/PKCS1Padding"). Possibly different padding defaults on each side. Commented Jul 14, 2021 at 10:14
  • 1
    I've elaborated on my comment and posted it as an answer. Commented Jul 14, 2021 at 15:13

1 Answer 1

1

The posted code, used on both the Android and Java/Spring sides, only specifies the algorithm and not the padding when instantiating the cipher:

Cipher.getInstance("RSA") 

Without explicit specification of the padding, the default padding of the providers of both sides is used. However, different providers generally define different default paddings (e.g. NoPadding, PKCS1Padding or OAEPPadding). The different paddings cause the decryption to fail, because a prerequisite for successful decryption is that the same padding is used as for encryption.

To avoid such things, the padding should always be specified when instantiating the cipher, especially in a cross-platform environment, e.g.:

Cipher.getInstance("RSA/ECB/PKCS1Padding") 

On the left is the algorithm and on the right the padding. Note that the middle part (ECB) has no meaning for RSA (it is an artifact of using the scheme of symmetric encryption specifying the operation mode in the middle, which is not defined for asymmetric encryption).

Fixing the issue with the explicit specification of the padding proves that the padding was indeed the problem.


I can only speculate about the default paddings used in your environment.

I could not test the OpenSSLRSA provider, as it is not available in my environment. On my machine Android (API Level 28, P) applies the AndroidOpenSSL provider (aka Conscrypt). This defaults to NoPadding, while Java's SunJCE provider defaults to PKCS1Padding. Encryption on Android and decryption on Java would result in an exception (or non-removed padding for the other direction).

You can determine the default padding of your environment as follows: Encrypt with the default padding (by specifying only the algorithm) and vary the padding on decryption until decryption is successful and the original plaintext is decrypted.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.