Is RSA PKCS1-OAEP padding supported in bouncycastle? - java

I'm implementing encryption code in Java/Android to match iOS encryption. In iOS there are encrypting with RSA using the following padding scheme: PKCS1-OAEP
However when I try to create Cipher with PKCS1-OAEP.
Cipher c = Cipher.getInstance("RSA/None/PKCS1-OAEP", "BC");
Below is the stacktrace
javax.crypto.NoSuchPaddingException: PKCS1-OAEP unavailable with RSA.
at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineSetPadding(CipherSpi.java:240)
at javax.crypto.Cipher.getCipher(Cipher.java:324)
at javax.crypto.Cipher.getInstance(Cipher.java:237)
Maybe this RSA/None/PKCS1-OAEP is incorrect? but can't find any definitive answer to say either PKCS1-OAEP is unsupported or the correct way to define it.
I'm using the spongycastle library so have full bouncycastle implementation.

The code in the first answer does work, but it's not recommended as it uses BouncyCastle internal classes, instead of JCA generic interfaces, making the code BouncyCastle specific. For example, it will make it difficult to switch to SunJCE provider.
Bouncy Castle as of version 1.50 supports following OAEP padding names.
RSA/NONE/OAEPWithMD5AndMGF1Padding
RSA/NONE/OAEPWithSHA1AndMGF1Padding
RSA/NONE/OAEPWithSHA224AndMGF1Padding
RSA/NONE/OAEPWithSHA256AndMGF1Padding
RSA/NONE/OAEPWithSHA384AndMGF1Padding
RSA/NONE/OAEPWithSHA512AndMGF1Padding
Then proper RSA-OAEP cipher initializations would look like
Cipher c = Cipher.getInstance("RSA/NONE/OAEPWithSHA1AndMGF1Padding", "BC");

The following code works, if anyone else is stuck with similar encryption encoding/padding issues
SubjectPublicKeyInfo publicKeyInfo = new SubjectPublicKeyInfo(
ASN1Sequence.getInstance(rsaPublicKey.getEncoded()));
AsymmetricKeyParameter param = PublicKeyFactory
.createKey(publicKeyInfo);
AsymmetricBlockCipher cipher = new OAEPEncoding(new RSAEngine(),
new SHA1Digest());
cipher.init(true, param);
return cipher.processBlock(stuffIWantEncrypted, 0, 32);

Related

Android AES/ECB/PKCS7PADDING generate key bouncy castle

I want to generate Random key using AES/ECB/PKCS7PADDING but java does not support PKCS7 padding and in my algo I have to use the same padding, bouncy castle does support PKCS7PADDING but I am unable to understand how to generate key using that
My code :
Security.addProvider(new BouncyCastleProvider());
private byte[] generateSessionKey() throws NoSuchAlgorithmException, NoSuchProviderException {
KeyGenerator kgen = KeyGenerator.getInstance("AES/ECB/PKCS7PADDING", "BC");
kgen.init(SYMMETRIC_KEY_SIZE);
SecretKey key = kgen.generateKey();
return key.getEncoded();
}
I am receiving error of no such algorithm
Key generation for AES does not have to do anything with padding. Padding is required for some modes of operation such as ECB and CBC. But the key itself doesn't rely on the mode or the padding. So you should just use:
KeyGenerator kgen = KeyGenerator.getInstance("AES", "BC");
which will undoubtedly work.
Do not use PKCS#7 padding, substitute "PKCS5Padding" for "PKCS7Padding".
Please take a look here to understand the difference between the padding mechanisms and here for the difference in Java.
I guess Android is using a stripped down Bouncy Castle provider (it was one of the reasons that SpongyCastle was lounged), which would explain the differences between Android and the Java SE provider.

Cannot get bouncycaste cipher instance

I cannot seem to get a bouncy castle Cipher to load an instance.
I printed out all the algorithms and all the providers, and part of the list is as follows:
RSA/ECB/PKCS1Padding : [SunMSCAPI version 1.7]
RSA/ISO9796-1 : [BC version 1.46]
RSA/OAEP : [BC version 1.46]
RSA/PKCS1 : [BC version 1.46]
According to examples I have seen, this should work
try
{
Cipher cipherb = Cipher.getInstance("RSA/PKCS1", "BC");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
...
}
catch(Exception e)
{
e.printStackTrace();
return ;
}
But I get an exception on the the call to Cipher.getInstance
java.security.NoSuchAlgorithmException:
Invalid transformation format:RSA/PKCS1
However, RSA/PKCS1 is in the list. The only cipher I can get an instance of is the Sun one RSA/ECB/PKCS1Padding, which is not compatible with where my data to be decrypted is coming from. And I can't figure out why this does not work.
Any suggestions greatly appreciated.
The first parameter for Cipher.getInstance(..)is the transformation that have the form:
"algorithm/mode/padding" or
"algorithm"
According to bouncycastle's specification RSA + PKCS1 have the form: "RSA/NONE/PKCS1Padding" in BouncyCastle
This is as Maarten hinted in his comment, the same as what you get with the SUN provider using "RSA/ECB/PKCS1Padding"

Translating Ruby encryption code to Java

I have a legacy code in ruby that does the encryption using OpenSSL
However, I would like to translate this in Java and I am lost.
so far my biggest blocker is figuring out how to generate the IV based on this code.
Any help would be greatly appreciated
def func_enc(data, key)
cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
cipher.encrypt
cipher.pkcs5_keyivgen(key)
cipher.update(data)
encrypted_data << cipher.final
return encryptedData
end
EDIT
Just to clarify, I would like to use Java Crypto for this. This is the code I came up with so far:
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithMD5And256AES-CBC");
KeySpec spec = new PBEKeySpec("Password".toCharArray(), null, 2048, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
but "PBKDF2WithMD5And256AES-CBC" does not have any provider and I get NoSuchAlgorithm exception.
java.security.NoSuchAlgorithmException: PBKDF2WithMD5And256AES-CBC SecretKeyFactory not available
Also the salt that pkcs5_keyivgen uses by default is null!! I am not sure if Java lets me use a null salt.
How can I generate the correct IV ?
The warning on this documentation page suggests that the deprecated pkcs5_keyivgen method does something non-standard when used together with AES. First of all, it uses PBKDF1, not PBKDF2.
It might be difficult to replicate what it does, and implementing cryptographic algorithms is generally inadvisable unless you know exactly what you're doing – even experts often get it wrong.

AES-256 encryption with BouncyCastle Lightweight API

I have written some (functional) AES encryption code using Java's built in encryption libraries, as follows, but I'd like to use a 256-bit key. However, I'd like to do this without the user having to install to Unlimited Strength Cryptography Policy files.
Now, I've heard that using the BouncyCastle Lightweight API can allow me to do this, but unfortunately I'm having a great deal of trouble getting my head around it, and am struggling to fit any documentation that helps me.
Here is a my current code, in which 'content' is the byte array to be encrypted:
KeyGenerator kgen = KeyGenerator.getInstance("AES");
int keySize = 128;
kgen.init(keySize);
SecretKey key = kgen.generateKey();
byte[] aesKey = key.getEncoded();
SecretKeySpec aesKeySpec = new SecretKeySpec(aesKey, "AES");
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE, aesKeySpec);
byte[] encryptedContent = aesCipher.doFinal(content);
How would I go about re-implementing this with the BouncyCastle Lightweight API? Can anyone help me out and/or point me in the direction of some simple example code?
I'm also interesting in any other solutions that allow 256-bit key AES encryption without the need for the user to install the unlimited strength policy files.
Many thanks!
This question and answer is a useful starting point.
256bit AES/CBC/PKCS5Padding with Bouncy Castle
The next best place to look is the test code for the LW APIs and then the JCE Provider code. The JCE Provider code is a wrapper around the LW libraries - so if you want to know how to do it, that's the best place to see it.
By the JCE Provider code, I mean the BC implementation.

Java cryptography generated key portability

In Java, I'm generating and serializing a symmetric key for encryption purposes:
KeyGenerator keyGen = KeyGenerator.getInstance(algorithm);
SecretKey symmetricKey = keyGen.generateKey();
Base64.encode(symmetricKey.getEncoded(), new FileOutputStream(filename));
where Base64 is from the Bouncycastle cryptography package and algorithm is AES.
The key, when used with Oracle (Sun) JVM 1.6.0_21, works perfectly is moved from, e.i, Windows to Linux (even between 32/64 bits OSs).
On OS X (Intel), with Apple's JVM, the key is loaded without exception but every string encrypted on Windows or Linux generates a BadPaddingException.
A string is encoded with the following code:
Cipher cipher = Cipher.getInstance(algorithm, "BC");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
encryptedString = new String(Base64.encode(cipher.doFinal(string.getBytes())));
where algorithm is AES.
Any clues?
Padding has nothing to do with the key.
What padding algorithm are you specifying when creating the Cipher?
If you are literally using just "AES" as the cipher algorithm, you should be explicit about the mode and padding. Otherwise, the crypto provider is free to choose some default of its own, and that's likely to vary from machine to machine.

Categories