I tried to use AES/ECB/PKCS7Padding to encrypt a file, but am getting the following exception.
java.security.NoSuchAlgorithmException: Cannot find any provider supporting AES/ECB/PKCS7Padding
Apparently PKCS7Padding is not supported. If I use AES/ECB/PKCS5Padding, then it works fine.
The requirement given to me is that EBC and PKCS7 with padding are to be used.
Someone answered in the below question that "Java is actually performing PKCS #7 padding, but in the JCA specification, PKCS5Padding is the name given"
AES-256 and PKCS7Padding fails in Java
In the below question, someone said that " I will point out that PKCS#5 and PKCS#7 actually specify exactly the same type of padding ..."
java.security.NoSuchAlgorithmException:Cannot find any provider supporting AES/ECB/PKCS7PADDING
What does that mean? AES/ECB/PKCS5Padding and AES/ECB/PKCS7Padding are the same? So both will produce exactly the same encrypted output?
TIA.
Related
I am developing a digital signature java class using the SHA1withRSA algorithm with a 256 bits certificate. But I am getting this error:
Signature length not correct: got 344 but was expecting 256.
I am using the SunJSSE provider (that not implements the SHA256withRSA algorithm) because he uses the PKCS12 keystore type. And I need this, because this is a batch application.
Is the SAH1withRSA algorithm incompatible with 256 bits certificate?
First, you can't possibly have a 256-bit RSA certificate, or key. 256-bit RSA wasn't secure when RSA was published in 1977 much less anytime close to now. That exception says it is looking for a 256 byte signature, which is 2048 bits, implying a key and certificate also of 2048 bits, which is currently (since 2015) the standard and widely used size for RSA.
Second, yes SHA1withRSA technically works with a 2048-bit RSA key (and certificate), although it is less secure. SHA1 was originally rated for only 80-bit strength against collision, and has been broken (at significantly lower cost, about 63 bits) about a year ago -- see https://shattered.io -- making it insecure for signatures in many cases, and thus leading more and more systems, programs, and users to reject SHA1 signatures. For example, all Oracle Java packages from 8u144 up (roughly last summer) have java.security jdk.certpath.disabledAlgorithms configured by default to prohibit use of SHA1-signed certificates in TLS (including SSL, but SSL is also broken and prohibited by default). Java doesn't currently prohibit other uses of SHA1 signatures, but may be changed to. And lots and lots of things you might want to communicate or interoperate with, like browsers, webservers, email systems, repositories, etc, either have already prohibited SHA1 or probably will.
But it isn't necessary. You can use multiple providers in one program, and in particular you can use the KeyStore PKCS12 from SunJSSE while also using the Signature SHA256withRSA (or other SHA2+RSA variants) from SunRsaSign. In fact it's easiest to not specify the provider(s) at all and just let KeyStore.getInstance() and Signature.getInstance() (and the other JCA interface classes) find the correct provider automatically.
Finally, your signature is probably base64-encoded: ceil(256/3)*4=344. Take a look at the data and see if it consists of base64 characters, and if so which set. If it is base64, decode it to binary (i.e. byte[] in Java) and use that. In Java8+ just use java.util.Base64 which supports both variants now common: the 'MIME' variant and the 'URL-safe' (primarily JSON) variant. In older Java you can use javax.xml.bind.DatatypeConverter for MIME, or any number of third-party libraries with varying capabilities.
We’re using a Java libarary called license3j for license management. The library uses asymmetric encryption and relies itself on Bouncycastle. We create a license file using a simple gpg command and verify the license within our software using our public key. So far everything worked fine. BUT: In 1,000 generated licenses, there is a very small fraction which cannot be verified correctly, although, they are in fact valid (approximately 5/1000).
What happens in this case: When the license is to be verified in com.verhas.licensor.License.setLicenseEncoded(InputStream), the org.bouncycastle.openpgp.PGPOnePassSignature.verify(PGPSignature) throws the following exception:
org.bouncycastle.openpgp.PGPRuntimeOperationException: unable to verify signature: Signature length not correct: got 511 but was expecting 512
Sounds rather obscure to me, having only basic cryptography knowledge. Spending hours googling, gave me the clue, that there is something about "leading zeros". So, in the given example, obviously a leading zero was stripped away somewhere (where?), and the lengths of the signature data to compare do not match. Makes sense.
Now, I’ve no clue, where the issue might be located. Is it during creation of the license file? Essentially, we’re just doing the following:
gpg --armor --local-user=name.of.software --sign
Which will give us the license file.
Or does the error happen during verification? Do I have to modify any Bouncycastle configuration to correctly address the leading zero issue? Their FAQ gives some hints, but the License3j source obviously never makes use of any Cipher instance, so I’m totally lost on how to integrate this into the given API.
I’m aware that this is a very special problem with a library which is obviously not very well known. Thus, I appreciate any little feedback or input.
Looks like it is a bug in bouncycastle, only encountered in versions of Java after 1.6, bouncycastle has always created the data wrong, but Java became more strict since 1.7 in the data it will accept during verification.
Bouncycastle is failing to pad the signature to the right length when it serializes it to the file, if the integer has enough leading zeros then the byte representation of it will be smaller.
Java versions 1.7 and above expect RSA signature bytes to be the same length as the key.
Bouncycastle converts the RSA signature byte array(returned from Java's RSA JCE provider) into an integer and it discards information about its length.
Line 263 of the PGPSignatureGenerator shows where the RSA signature bytes are returned from JCE and converted into an integer.
This integer is eventually written to the outputstream using MPInteger#encode which just uses the bitlength of the underlying biginteger to determine how much data to write.
This answer describes more about why you see this aproximatley one in every 200 cases and how the version of Java plays a role.
I need to decrypt messages via RSA in order to send it over an unsecured channel, but I'm afraid of the Padding Oracle Attack. Therefore I already have asked the follwoing questions:
How to verify the integrity of RSA encrypted messages?
How to ensure message integrity for RSA ciphers by using javax.crypto.Cipher
Like suggested in the first question,
However, since you are using a high level cryptographic library, this is something you shouldn't have to worry about. The writers of that library should have taken care of it.
I shouldn't consider about. As far I know, the RSA implementation of PKCS#1 v1.5 is vulnerable to the Padding Oracale Attack whereby OAEP isn't (assumed it's implemented correctly)
Hence I want to know which padding implementation is used by javax.crypt.Cipher by Java 7
It depends on the chosen or default provider which padding is actually used when you instantiate a Cipher without fully qualifying it like:
Cipher.getInstance("RSA")
Doing so is a bad practice, because if you switch Java implementations, there might be different defaults and suddenly, you won't be compatible with the old ciphertexts anymore. Always fully qualify the cipher.
As I said before, the default will probably (there are many providers, one can't be sure) be PKCS#1 v1.5 padding. If you need another, you would have to specify it. If you want to use OAEP, here is a fully qualified cipher string from here:
Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
That's not a good advice given in the first link to the cryptography site. You should never rely on the defaults of cryptographic libraries cryptographic algorithms. There are quite a few reasons for this:
Different implementations, different defaults (there are no requirements for cryptography providers concerning defaults, although most will copy the Oracle/Sun defaults);
What's secure now may not be considered secure tomorrow, and because for backwards compatibility, you can never change the default;
It's unclear to anybody reading your software what the default is (you could document it, but in that case you might as well write it out).
The SunJCEProvider provided by Oracle defaults to PKCS#1 padding ("PKCS1Padding") for historical reasons (see reason #2 above). This is not well documented.
At that time that default was set you basically had just the insecure textbook RSA ("NoPadding") and the PKCS#1 v1.5 version ("PKCS1Padding" or RSAES-PKCS1-v1_5 in the PKCS#1 v2.1 standard). At that time RSAES-PKCS1-v1_5 was definitely the more secure choice. Changing the default now to OAEP would break every RSA implementation out there that uses the default.
The advice of otus (in the first link within this answer) is be better suited to protocol implementations in libraries than to cryptographic algorithms. In the end you should be able to defend the security of the choices made, whatever you choose.
The default for bouncy-castle when you just specify RSA is RSA/NONE/NOPADDING
This is the same result as RSA/ECB/NOPADDING as well.
I am trying to decrypt the data using RSA Algorithm. While doing the decryption, I am getting an exception.That is,
java.security.NoSuchAlgorithmException: Cannot find any provider supporting RSA/ECB/PKCS5Padding
at javax.crypto.Cipher.getInstance(DashoA13*..)
How to solve this exception? Currently, I am using java version "1.6.0_26".
It's a typo. The correct name for RSA with PKCS #1 v1.5 padding is "RSA/ECB/PKCS1Padding".
Generally, it is a good idea to compare with a list of available algorithms.
E.g. this question contains some ways to print such a list.
(And of course using OAEP instead of v1.5 padding would be preferable, especially if your
main field is not cryptography).
The error means that the library you use cna't decrypt the data because there isn't an algorithm in the Lib which decrypts RSA.
You can use a library like Bouncy Calste or GNU Crypto to decrypt data using RSA. There are plenty of samples how to do this on the web.
I need encrypt data using exactly the PKCS#1 V2.0 encryption method (defined in item 7.2.1 of the PKCS#1V2 specification).
Is it already implemented for Java?
I'm thinking in something like just pass a parameter to javax.crypto.Cipher specifying "PKCS#1V2", I wonder if there is something like this?
PKCS#1 v2.0 encryption is usually called OAEP encryption. So:
Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
The place to look is the Java Cryptography Architecture documents: Standard Algorithm Name Documentation or Sun Providers Documentation.
As you can see the SunJCE provider supports the following variations of OAEP:
OAEPWITHMD5ANDMGF1PADDING
OAEPWITHSHA1ANDMGF1PADDING
(OAEPWITHSHA-1ANDMGF1PADDING)
OAEPWITHSHA-256ANDMGF1PADDING
OAEPWITHSHA-384ANDMGF1PADDING
OAEPWITHSHA-512ANDMGF1PADDING