java.security.NoSuchAlgorithmException:Cannot find any provider supporting AES/ECB/PKCS7PADDING
Asked Answered
S

5

40

I was trying to encrypt data using AES algorithm. However, with the following exception has occurred.

java.security.NoSuchAlgorithmException:
    Cannot find any provider supporting AES/ECB/PKCS7PADDING

Someone know a solution to this issue? My JDK's version is 1.7.

Solange answered 17/4, 2012 at 14:51 Comment(1)
Note that ECB is not CPA secure, use CBC instead (if you just want confidentiality of stored data).Impotent
M
56

You don't want to specify PKCS#7 padding for block cipher use. You want to specify PKCS#5 padding. PKCS#5 is specified for use with block ciphers while PKCS#7 is not (it's use for different places like in S/MIME). I will point out that PKCS#5 and PKCS#7 actually specify exactly the same type of padding (they are the same!), but it's called #5 when used in this context. :)

So, instead of "AES/ECB/PKCS7PADDING", you want "AES/ECB/PKCS5PADDING". This is a cipher implementation that every implementation of the Java platform is required to support. See the documentation of the Cipher class for more details.

Milzie answered 17/4, 2012 at 15:21 Comment(8)
thanks alot for your answer.Then JCE provider does not support PKCS7PADDING?Solange
Correct. It does not (well, since #5 and #7 are the same padding...I guess you could say it does?). And, you're welcome. Remember to Accept the answer if you're happy with it. :)Milzie
This answer is okay, but a little confusing because you do want to use PKCS #7 padding for a block cipher. It's just that PKCS7Padding is the wrong name, according to the Standard Algorithm Names. PKCS #7 uses this padding scheme for padding messages that are encrypted with block ciphers. It doesn't matter what the larger context is.Fervor
And to add to the confusion, .NET call the exact same padding algorithm PKCS7 padding.Shock
While Java considers PKCS5 and PKCS7 padding to be the "same" (and one should always use the string "AES/CBC/PKCS5Padding" because "AES/CBC/PKCS7Padding" will cause NoSuchAlgorithmException to be thrown when initializing an AES block cipher using the Java crypto API), I consider this a gross misnaming in the Java platform because the pure technical definitions of these paddings are not the same. PKCS5 explicitly defines its block size as being strictly 8 bytes, while PKCS7 is defined for block sizes from 1 to 255 (with block sizes of 8 bytes being the same thing as PKCS5).Orvalorvan
The answer is kind of correct, but the explanation is definitely not. If the specification is any indication, then PKCS#5 padding should only be used for password based encryption, as that is what PKCS#5 specifies. To disallow PKCS#7 padding as general padding for a block cipher because PKCS#7 mainly specifies the Cryptographic Message Syntax is therefore bunk. Only the last sentence makes sense (but that's most of the answer, fortunately)Impotent
To make my crypto lib in Java and .NET understand each other, I have to use PKCS#5 (Java) ~ PKCS7 (.NET). Oh my god, thanks for the challenge...Colleencollege
2020: helpful regarding a java6-decryption for a value encrypted with java8, has been done with commons-codes, which resulted in a NoSuchMethodException, maybe because of a commons-codec 1.2 in an "quite" old JBOSS classpath - THANK YOU :)Jazmin
I
5

For a very comprehensive explanation of the issue that includes the text of the PKCS#5 and PKCS#7 cryptographic standards, please take a look here.


PKCS#5 padding means padding 1 to 8 bytes. The padding bytes themselves contain the amount of padding bytes encoded as a byte. PKCS#5 padding was specified for DES, but it would be suitable for any block cipher with a block size of 8 bytes.

Now the DES specifications and even the PKCS#5 specification for password based encryption precede and Java by quite a long time. AES was only standardized in 2002, long after Java and even Java 2 was introduced. So (triple) DES and PKCS#5 padding was integrated into Java before AES made its appearance.

When Java - or more precisely, the Sun JCE provider - gained AES functionality it required a padding method for a block size of 16 bytes. PKCS#7 specifies this padding method that is identical to PKCS#5 padding, except that it is defined for block sizes of 2 to 255 bytes (the maximum value of a byte if it encodes a zero based unsigned integer). However, the padding method was already there; it was named "PKCS5Padding". So instead of introducing a new name, "PKCS5Padding" was simply re-used.

By now the Sun provider should really support "PKCS7Padding" as PKCS#5 padding is simply incorrect. It's not just a Java naming issue, it's an issue for any developer that tries to implement cryptographic protocols or port other applications to Java. For now however, you should use "PKCS5Padding" instead of "PKCS7Padding".

Impotent answered 24/1, 2015 at 22:39 Comment(0)
A
4

if you want to use AES/ECB/PKCS7Padding then bouncy castle will support http://www.bouncycastle.org/specifications.html

Arreola answered 15/10, 2013 at 9:43 Comment(1)
True but it's the same padding algorithm underneath.Impotent
A
1

Solution: Step1: Add bcprov-ext-jdk16-1.46.jar (https://mvnrepository.com/artifact/org.bouncycastle/bcprov-ext-jdk16/1.46) to your project

Step2: Add line "Security.addProvider(new BouncyCastleProvider());" to bebore init Cipher common

Then, run the project, OK, successfully decrypted.

Aultman answered 20/3, 2020 at 2:49 Comment(1)
This solution worked when the environment was standalone Java but didn't work on Android. For Android the solution is in this thread itself. https://mcmap.net/q/397238/-java-security-nosuchalgorithmexception-cannot-find-any-provider-supporting-aes-ecb-pkcs7paddingCyclist
C
0

Please consider the following solution if the environment was Android and you were trying to read the Encrypted Private Key or Passphrase protected Private Key in PKCS8 format from the file.

The Exception that I received was as follows:

W/System.err: org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: 1.2.840.113549.1.5.13 not available: No provider found for 2.16.840.1.101.3.4.1.42
W/System.err:     at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source:60)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
W/System.err:     at android.os.Looper.loop(Looper.java:223)
W/System.err:     at android.os.HandlerThread.run(HandlerThread.java:67)
W/System.err: Caused by: org.bouncycastle.operator.OperatorCreationException: 1.2.840.113549.1.5.13 not available: No provider found for 2.16.840.1.101.3.4.1.42
W/System.err:     at org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder$1.get(Unknown Source:322)
W/System.err:     at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source:6)
W/System.err:   ... 8 more
W/System.err: Caused by: java.security.NoSuchAlgorithmException: No provider found for 2.16.840.1.101.3.4.1.42
W/System.err:     at javax.crypto.Cipher.createCipher(Cipher.java:736)
W/System.err:     at javax.crypto.Cipher.getInstance(Cipher.java:619)
W/System.err:     at org.bouncycastle.jcajce.util.DefaultJcaJceHelper.createCipher(Unknown Source:0)
W/System.err:     at org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder$1.get(Unknown Source:101)
W/System.err:   ... 9 more

The only solution that worked was to set the Provider as Bouncy Castle like below:

InputDecryptorProvider decryptorProvider = new JceOpenSSLPKCS8DecryptorProviderBuilder()
    .setProvider(new BouncyCastleProvider())
    .build(mContext.getResources().getString(R.string.password).toCharArray());

The complete block code would look like this:

privateKeyString = privateKeyString.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "").replaceAll(System.lineSeparator(), "")
                .replace("-----END ENCRYPTED PRIVATE KEY-----", "");
byte[] keyStringBytes = DatatypeConverter.parseBase64Binary(privateKeyString);
ASN1Sequence asn1Sequence = ASN1Sequence.getInstance(keyStringBytes);
PKCS8EncryptedPrivateKeyInfo pkcs8EncryptedPrivateKeyInfo = new PKCS8EncryptedPrivateKeyInfo(
    EncryptedPrivateKeyInfo.getInstance(asn1Sequence));
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
InputDecryptorProvider decryptorProvider = new JceOpenSSLPKCS8DecryptorProviderBuilder()
    .setProvider(new BouncyCastleProvider())
    .build(mContext.getResources().getString(R.string.password).toCharArray());
PrivateKeyInfo privateKeyInfo = pkcs8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(decryptorProvider);
mPrivateKey = converter.getPrivateKey(privateKeyInfo);
Cyclist answered 24/2, 2022 at 10:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.