What's wrong with this?
for (Object obj : java.security.Security.getAlgorithms("Cipher")) {
System.out.println(obj);
}
javax.crypto.SecretKeyFactory.getInstance("AES");
This is the output (JDK 1.6 on Mac OS 10.6):
BLOWFISH
ARCFOUR
PBEWITHMD5ANDDES
RC2
RSA
PBEWITHMD5ANDTRIPLEDES
PBEWITHSHA1ANDDESEDE
DESEDE
AESWRAP
AES
DES
DESEDEWRAP
PBEWITHSHA1ANDRC2_40
java.security.NoSuchAlgorithmException: AES SecretKeyFactory not available
at javax.crypto.SecretKeyFactory.<init>(DashoA13*..)
at javax.crypto.SecretKeyFactory.getInstance(DashoA13*..)
...
This is a verified java bug. See https://bugs.openjdk.java.net/browse/JDK-7022467
EDIT: Different java versions support different algorithms, you can also extend it with custom providers and so on. Oracle has a list for java 6 here http://docs.oracle.com/javase/6/docs/technotes/guides/security/SunProviders.html . For KeyFactory this is DSA.
You don't really need to use SecretKeyFactory. You can create an AES key with the following;
byte[] keyData = ........
SecretKeySpec key = new SecretKeySpec(keyData, "AES");
If you want to do password based encryption (PBE) then simply choose a secure hashing algorithm that gives you a hash the same size as the required key. For example, if you want a 256 bit key for AES, here is a method to build the key;
private Key buildKey(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest digester = MessageDigest.getInstance("SHA-256");
digester.update(password.getBytes("UTF-8"));
byte[] key = digester.digest();
SecretKeySpec spec = new SecretKeySpec(key, "AES");
return spec;
}
Edit:
I would recommend against using MD5 and DES unless this is a play project, both have weaknesses and are considered obsolete.
Not all versions of Java provide a SecretKeyFactory for "AES" in their default providers.
If you want to generate a new key, choose the desired number of bits (128, 192, or 256) from a SecureRandom instance, and use that random number to initialize a SecretKeySpec instance.
If you are using password-based encryption, create a SecretKeyFactory for the "PBKDF2WithHmacSHA1" algorithm, and use it to initialize a SecretKeySpec instance as illustrated here.
If you try to print all your providers, you probably missed the one that you need.
Try to call this method and see what it prints out.
for (Object obj : java.security.Security.getProviders()) {
System.out.println(obj);
}
In case for example you need a specific provider (like the Bouncy Castle one), add the dependency to your App and add it on Security Providers as follows:
java.security.Security.addProvider(new BouncyCastleProvider());
and then see again your provider list.
Give a try with all of your algorithm and see which one are supported. An example can be done with jasypt encryption
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
import org.jasypt.registry.AlgorithmRegistry;
with the following code:
Set<String> supported = new TreeSet<>();
Set<String> unsupported = new TreeSet<>();
for (Object oAlgorithm : AlgorithmRegistry.getAllPBEAlgorithms()) {
String algorithm = (String) oAlgorithm;
try {
SimpleStringPBEConfig pbeConfig = new SimpleStringPBEConfig();
pbeConfig.setAlgorithm(algorithm);
pbeConfig.setPassword("changeme");
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setConfig(pbeConfig);
String encrypted = encryptor.encrypt("foo");
String decrypted = encryptor.decrypt(encrypted);
supported.add(algorithm);
} catch (EncryptionOperationNotPossibleException e) {
unsupported.add(algorithm);
}
}
System.out.println("Supported");
supported.forEach((String alg) -> System.out.println(" " + alg));
System.out.println("Unsupported");
unsupported.forEach((String alg) -> System.out.println(" " + alg));
Related
What's wrong with this?
for (Object obj : java.security.Security.getAlgorithms("Cipher")) {
System.out.println(obj);
}
javax.crypto.SecretKeyFactory.getInstance("AES");
This is the output (JDK 1.6 on Mac OS 10.6):
BLOWFISH
ARCFOUR
PBEWITHMD5ANDDES
RC2
RSA
PBEWITHMD5ANDTRIPLEDES
PBEWITHSHA1ANDDESEDE
DESEDE
AESWRAP
AES
DES
DESEDEWRAP
PBEWITHSHA1ANDRC2_40
java.security.NoSuchAlgorithmException: AES SecretKeyFactory not available
at javax.crypto.SecretKeyFactory.<init>(DashoA13*..)
at javax.crypto.SecretKeyFactory.getInstance(DashoA13*..)
...
This is a verified java bug. See https://bugs.openjdk.java.net/browse/JDK-7022467
EDIT: Different java versions support different algorithms, you can also extend it with custom providers and so on. Oracle has a list for java 6 here http://docs.oracle.com/javase/6/docs/technotes/guides/security/SunProviders.html . For KeyFactory this is DSA.
You don't really need to use SecretKeyFactory. You can create an AES key with the following;
byte[] keyData = ........
SecretKeySpec key = new SecretKeySpec(keyData, "AES");
If you want to do password based encryption (PBE) then simply choose a secure hashing algorithm that gives you a hash the same size as the required key. For example, if you want a 256 bit key for AES, here is a method to build the key;
private Key buildKey(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest digester = MessageDigest.getInstance("SHA-256");
digester.update(password.getBytes("UTF-8"));
byte[] key = digester.digest();
SecretKeySpec spec = new SecretKeySpec(key, "AES");
return spec;
}
Edit:
I would recommend against using MD5 and DES unless this is a play project, both have weaknesses and are considered obsolete.
Not all versions of Java provide a SecretKeyFactory for "AES" in their default providers.
If you want to generate a new key, choose the desired number of bits (128, 192, or 256) from a SecureRandom instance, and use that random number to initialize a SecretKeySpec instance.
If you are using password-based encryption, create a SecretKeyFactory for the "PBKDF2WithHmacSHA1" algorithm, and use it to initialize a SecretKeySpec instance as illustrated here.
If you try to print all your providers, you probably missed the one that you need.
Try to call this method and see what it prints out.
for (Object obj : java.security.Security.getProviders()) {
System.out.println(obj);
}
In case for example you need a specific provider (like the Bouncy Castle one), add the dependency to your App and add it on Security Providers as follows:
java.security.Security.addProvider(new BouncyCastleProvider());
and then see again your provider list.
Give a try with all of your algorithm and see which one are supported. An example can be done with jasypt encryption
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
import org.jasypt.registry.AlgorithmRegistry;
with the following code:
Set<String> supported = new TreeSet<>();
Set<String> unsupported = new TreeSet<>();
for (Object oAlgorithm : AlgorithmRegistry.getAllPBEAlgorithms()) {
String algorithm = (String) oAlgorithm;
try {
SimpleStringPBEConfig pbeConfig = new SimpleStringPBEConfig();
pbeConfig.setAlgorithm(algorithm);
pbeConfig.setPassword("changeme");
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setConfig(pbeConfig);
String encrypted = encryptor.encrypt("foo");
String decrypted = encryptor.decrypt(encrypted);
supported.add(algorithm);
} catch (EncryptionOperationNotPossibleException e) {
unsupported.add(algorithm);
}
}
System.out.println("Supported");
supported.forEach((String alg) -> System.out.println(" " + alg));
System.out.println("Unsupported");
unsupported.forEach((String alg) -> System.out.println(" " + alg));
I am wanting to write a cryptographic routine in Java that can be run under both the standard Java class libraries and the Android ones. The routine is for encrypting/decrypting byte arrays using a password-based key and a standard symmetric cipher (such as AES).
Here is the nub of what I have in mind:
static final int ITERATION_COUNT = 10_000;
static final byte[] SALT = {37, -19, . . . 88, 0, 127, 3, 82};
static final PBEParameterSpec PBE_PARAM_SPEC =
new PBEParameterSpec(SALT, ITERATION_COUNT);
static final String ALGORITHM = "PBEwithSHAand128bitAES-CBC-BC";
char[] passwordChars = “SECRET!”.toCharArray();
PBEKeySpec pbeKeySpec = new PBEKeySpec(passwordChars);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec);
Cipher encryptingCipher = Cipher.getInstance(ALGORITHM);
encryptingCipher.init(Cipher.ENCRYPT_MODE, pbeKey, PBE_PARAM_SPEC);
Cipher decryptingCipher = Cipher.getInstance(ALGORITHM);
decryptingCipher.init(Cipher.DECRYPT_MODE, pbeKey, PBE_PARAM_SPEC);
byte[] plainBytesIn = . . . the message to be encrypted . . .
byte[] cipherBytes = encryptingCipher.doFinal(plainBytesIn);
byte[] plainBytesOut = decryptingCipher.doFinal(cipherBytes);
I found that this routine runs fine under Android, but fails under Java SE.
The reason for this is that I selected the particular algorithm used (ie, Password-Based Encryption using SHA and 128-bit AES with Cipher-Block-Chaining) from the list of algorithm names generated by the following routine while running under Android:
void listProviders() {
for (Provider provider : Security.getProviders()) {
log(provider.getName());
for (String key : provider.stringPropertyNames()) {
log("\t" + key + "\t" + provider.getProperty(key));
}
}
}
However, when run under Java SE, I found that it generates a list of algorithm names that seem to be quite different. In particular, the above algorithm (“PBEwith...”) does not appear to be available under Java SE – thus causing the encryption routine to fail.
Is there an algorithm (possibly under different names in each list) available for both libraries? (I am not too bothered about the precise details of the algorithm: it just has to be strong enough for routine low-value commercial use.) If not, is it difficult to put together ones own overall encryption algorithm from the basic components provided by the javax.crypto libraries?
I am new to password storage and to Bouncy Castle.
Encryption : Is there a reason to prefer Pkcs5S2ParametersGenerator
over AES to encrypt(salt+hash(password+salt)) ?
An example : How to encrypt and salt the password using BouncyCastle API in Java?
My Java code : is there a better way to get back the salt from the cipher than byte array extraction ?
Here is my java code :
// salt
java.security.SecureRandom rgen = new SecureRandom();
byte[] salt = rgen.generateSeed(20);
// add Bouncy Castle
java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
// aes secret key
javax.crypto.KeyGenerator kgen = KeyGenerator.getInstance("AES", "BC");
Key cleSecrete = kgen.generateKey();
// aes
javax.crypto.Cipher cipher = Cipher.getInstance("AES", "BC");
// sha-256
java.security.MessageDigest sha256 = MessageDigest.getInstance("SHA-256","BC");
// hash the clear password with the salt to avoid collisions
byte[] motDePasseHash = hasherSaler(motDePasseClair.getBytes("UTF-8"),salt);
// Encrypt the hash with the salt to get the salt back
byte[] chiffreBDD = chiffrerSalerHash(salt,motDePasseHash,cleSecrete );
// Store the cipher in DB
...
// Get back the hash and the salt from DB
byte[] deChiffreBDD = deChiffrer(chiffreBDD,cleSecrete );
byte[] saltBDD = extraireOctets(deChiffreBDD,0,19);
byte[] hashBDD = extraireOctets(deChiffreBDD,20,deChiffreBDD.length-1);
// hash the user intput
byte[] motDePasseHashCandidat = hasherSaler(motDePasseClairCandidat.getBytes("UTF-8"),saltBDD);
// Compare hased user input with DB hash
boolean isMotDePasseOK = Arrays.equals(hashBDD,motDePasseHashCandidat);
private final byte[] hasherSaler(byte[] clair,byte[] salt) {
byte[] concat = concatenerOctets(clair,salt);
return sha256.digest(concat);
}
private final byte[] chiffrerSalerHash(byte[] salt,byte[] hash, Key cle) {
cipher.init(true,cle);
return cipher.doFinal(concatenerOctets(salt,hash));
}
private final byte[] deChiffrer(byte[] chiffre, Key cle) {
cipher.init(false,cle);
return cipher.doFinal(chiffre);
}
Thank you.
If you just want to verify a password, you should only use PBKDF2 (or bcrypt/scrypt). A cipher should not be necessary. The salt can be stored without encryption. You may want to use an additional secret to append to the salt that you keep stored in e.g. the source code. Don't forget to store a protocol number with your passwords or you cannot upgrade later on.
As for your code, you should not use generateSeed for salts. You should use update more. "AES" uses ECB mode by default, so specify another mode. Don't rely on defaults. Use a (possibly derived) IV. Don't explicitly use a provider when not necessary.
OK, I could go on for quite a while, but this will have to do for now.
I need crypto-algorithm AES in key wrap mode. Is there some open-source library or implementation that could be helpful?
It is important, that it must be key wrap mode.
The standard SunJCE provider offers an implementation of RFC 3394. Just use the algorithm AESWrap:
Cipher c = Cipher.getInstance("AESWrap", "SunJCE");
c.init(Cipher.WRAP_MODE, secretKey);
byte[] result = c.wrap(someKey);
BouncyCastle supports key wrapping in AES with the AESWrapEngine.
You can look at this StackOverflow post to see more examples of BouncyCastle. The only difference is you will specify the AESWrapEngine instead of the AESEngine.
yes there is a library available named Bouncy Castle you can use that library for wrapping your data encryption key using AES algorithm in WRAP_MODE ,here below code snippet might help you.
public static byte[] wrapKey(SecretKey key, SecretKey keyToWrap) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AESKW", "BCFIPS");
cipher.init(Cipher.WRAP_MODE, key);
return cipher.wrap(keyToWrap);
}
public static SecretKey unwrapKey(SecretKey key, byte[] wrappedKey) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AESKW", "BCFIPS");
cipher.init(Cipher.UNWRAP_MODE, key);
return (SecretKey) cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);
}
I am using IBM JRE and i want to implement PBEWithSHAAnd128BitRC4 algorothm for my cipher so which alorithm should i use for my SecretKeyFactory and SecretKeySpec ,below is the secret key supporting algos which i got from provider.getInfo() methode for IBMJCE provider.
Cipher algorithms : Blowfish, AES, DES, TripleDES, PBEWithMD2AndDES,
PBEWithMD2AndTripleDES, PBEWithMD2AndRC2,
PBEWithMD5AndDES, PBEWithMD5AndTripleDES,
PBEWithMD5AndRC2, PBEWithSHA1AndDES
PBEWithSHA1AndTripleDES, PBEWithSHA1AndRC2
PBEWithSHAAnd40BitRC2, PBEWithSHAAnd128BitRC2
PBEWithSHAAnd40BitRC4, PBEWithSHAAnd128BitRC4
PBEWithSHAAnd2KeyTripleDES, PBEWithSHAAnd3KeyTripleDES
Mars, RC2, RC4, ARCFOUR
RSA, Seal
Key agreement algorithm : DiffieHellman
Key (pair) generator : Blowfish, DiffieHellman, DSA, AES, DES, TripleDES, HmacMD5,
HmacSHA1, Mars, RC2, RC4, RSA, Seal, ARCFOUR
Algorithm parameter generator : DiffieHellman, DSA
Algorithm parameter : Blowfish, DiffieHellman, AES, DES, TripleDES, DSA, Mars,
PBEwithMD5AndDES, RC2
Key factory : DiffieHellman, DSA, RSA
Secret key factory : Blowfish, AES, DES, TripleDES, Mars, RC2, RC4, Seal, ARCFOUR
PKCS5Key, PBKDF1 and PBKDF2(PKCS5Derived Key).
Below is my code which is giving java.security.InvalidKeyException: Missing password exception.
Decrypter(String passPhrase) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount, keyStrength);
SecretKey tmp = factory.generateSecret(spec);
key = new SecretKeySpec(tmp.getEncoded(), "RC4");
dcipher = Cipher.getInstance("PBEWithSHAAnd128BitRC4");
}
public String encrypt(String data) throws Exception {
dcipher.init(Cipher.ENCRYPT_MODE, key);
AlgorithmParameters params = dcipher.getParameters();
System.out.println("getAlgorithm : "+params.getAlgorithm());
iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] utf8EncryptedData = dcipher.doFinal(data.getBytes());
String base64EncryptedData = new sun.misc.BASE64Encoder().encodeBuffer(utf8EncryptedData);
System.out.println("IV " + new sun.misc.BASE64Encoder().encodeBuffer(iv));
System.out.println("Encrypted Data " + base64EncryptedData);
return base64EncryptedData;
}
public String decrypt(String base64EncryptedData) throws Exception {
dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] decryptedData = new sun.misc.BASE64Decoder().decodeBuffer(base64EncryptedData);
byte[] utf8 = dcipher.doFinal(decryptedData);
return new String(utf8, "UTF8");
}
One more question ,Which are the most secure algorithm amoung default java provider because i can not use thrid party like BouncyCastleProvider ?
Thanks .
Secure is a bit of a moving target. Secure against what and for how long. If you are encrypting transaction data that has no value an hour later, almost anything will do. If you need to keep something secure for a long time, you want a long key for your PK systems, the longer the better. But you really pay the price on key generation and some types of stream encryptions/decryptions.
The number one failure of encryption systems is not the algorithm itself, but the implementation of the system, usually how the keys are either generated or stored. That said, Blowfish and AES are both well regarded and when properly implemented should be everything you need. I can't recommend http://www.schneier.com/ highly enough. Applied Cryptography is a bit dated, 10 years or so, but is a cogent explaination of the field specifically geared to programmers. And his blog is a wealth of information. Go there and search if you need more details on algorithms. Won't be a ton of help in java implementation, but you can get that here on SO.