How to determine appropriate key sizes.
I'm very naive when it comes to crypto so much of the terminology is over my head but I'm trying to follow the "JWE with Shared Key" example (http://connect2id.com/products/nimbus-jose-jwt/examples/jwe-with-shared-key) and am testing the other available EncryptionMethod(s) to see what works with JDK7+Unlimited Security.
In my testing I'm getting some failures with the error "Couldn't create AES/GCM/NoPadding cipher: Illegal key size". I was using the EncryptionMethod.cekBitLength()
to determine the correct key length. This works for some of the EncryptionMethods but not others.
For example:
Attempting to use: A192CBC-HS384
Key: 384 bits, 48 bytes.
Failed to encrypt using A192CBC-HS384
com.nimbusds.jose.JOSEException: Illegal key size
at com.nimbusds.jose.crypto.AESCBC.createAESCBCCipher(AESCBC.java:101)
at com.nimbusds.jose.crypto.AESCBC.encrypt(AESCBC.java:128)
at com.nimbusds.jose.crypto.AESCBC.encryptAuthenticated(AESCBC.java:176)
at com.nimbusds.jose.crypto.ContentCryptoProvider.encrypt(ContentCryptoProvider.java:158)
at com.nimbusds.jose.crypto.DirectEncrypter.encrypt(DirectEncrypter.java:118)
at com.nimbusds.jose.JWEObject.encrypt(JWEObject.java:353)
at com.katalystdm.encweb.Encryptor.encrypt(Encryptor.java:75)
at com.katalystdm.encweb.Encryptor.main(Encryptor.java:95)
Caused by: java.security.InvalidKeyException: Illegal key size
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1034)
at javax.crypto.Cipher.implInit(Cipher.java:800)
at javax.crypto.Cipher.chooseProvider(Cipher.java:859)
at javax.crypto.Cipher.init(Cipher.java:1370)
at javax.crypto.Cipher.init(Cipher.java:1301)
at com.nimbusds.jose.crypto.AESCBC.createAESCBCCipher(AESCBC.java:92)
... 7 more
How do I programmatically determine the appropriate length for the input key for a particular algorithm?
Here's the code I'm using to test:
import static java.lang.System.err;
import static java.lang.System.out;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;
import java.util.List;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWEHeader;
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.Payload;
import com.nimbusds.jose.crypto.DirectEncrypter;
import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton;
public class Encryptor {
private byte[] key(int length) {
byte[] keymaterial = new byte[length/8];
new SecureRandom().nextBytes(keymaterial);
out.printf("Key: %d bits, %d bytes.\n", length, keymaterial.length);
return keymaterial;
}
public String encrypt(final String input) {
// initialize bouncy castle as well...
Provider bc = BouncyCastleProviderSingleton.getInstance();
Security.addProvider(bc);
List<EncryptionMethod> methodsToTry = Lists.newArrayList(
EncryptionMethod.A128CBC_HS256,
EncryptionMethod.A128GCM,
EncryptionMethod.A192CBC_HS384,
EncryptionMethod.A192GCM,
EncryptionMethod.A256CBC_HS512,
EncryptionMethod.A256GCM
);
out.printf("Security providers: %s\n", Joiner.on(',').join(Security.getProviders()));
String encryptedOutput = null;
for (EncryptionMethod em : methodsToTry) {
try {
out.println("Attempting to use: " + em);
// Set the plain text
Payload payload = new Payload(input);
// Create the header
JWEHeader header = new JWEHeader(JWEAlgorithm.DIR, em);
// Create the JWE object and encrypt it
JWEObject jweObject = new JWEObject(header, payload);
// This doesn't appear to give the correct result!?
byte[] key = key(em.cekBitLength());
jweObject.encrypt(new DirectEncrypter(key));
// Serialise to compact JOSE form...
encryptedOutput = jweObject.serialize();
out.printf("Successfully encrypted using %s giving: %s\n", em, encryptedOutput);
}
catch (Exception e) {
err.printf("Failed to encrypt using %s.\n", em);
e.printStackTrace(err);
}
}
return encryptedOutput;
}
public static void main(String[] args) {
new Encryptor().encrypt("Hello World!");
}
}
Comments (3)
-
-
- changed status to duplicate
Duplicate of
#195. -
Use EncryptionMethod.A128GCM.cekBitLength() to determine required key length programmatically.
Also updated the online docs at http://connect2id.com/products/nimbus-jose-jwt/examples/jwe-with-shared-key
- Log in to comment
This is a valid usage question, we'll think of some helper method, or document this online.