PBEWithSHAAnd128BitRC4 implementation in java - java

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.

Related

Why AES Produce Different result and Why DES not Produce

I'm trying to change encryption algorithm of existing project. But i have a little bit confusion. When i use "PBEWithHmacSHA512AndAES_256" as a parameter, it produce different result but when i use "PBEWithMD5AndDES" as a parameter it produce same result. My functions are :
public static synchronized String encrypt1(final String textToEncrypt, final String pathPublicKey) throws Exception {
final KeySpec pbeKeySpec = new PBEKeySpec(DbKeyHandler.getDbKey(pathPublicKey).toCharArray());
final SecretKey pbeKey = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(pbeKeySpec);
// Prepare the parameter to the ciphers
final AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
final Cipher cipher = Cipher.getInstance(pbeKey.getAlgorithm());
// Create the ciphers
cipher.init(Cipher.ENCRYPT_MODE, pbeKey, paramSpec);
// Encode the string into bytes using utf-8
final byte[] utf8 = textToEncrypt.getBytes("UTF8");
// Encrypt
final byte[] enc = cipher.doFinal(utf8);
// Encode bytes to base64 to get a string
return new sun.misc.BASE64Encoder().encode(enc);
}
public static synchronized String encrypt2 (final String textToEncrypt, final String pathPublicKey) throws Exception {
final KeySpec pbeKeySpec = new PBEKeySpec(DbKeyHandler.getDbKey(pathPublicKey).toCharArray());
final SecretKey pbeKey = SecretKeyFactory.getInstance("PBEWithHmacSHA512AndAES_256").generateSecret(pbeKeySpec);
// Prepare the parameter to the ciphers
final AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
final Cipher cipher = Cipher.getInstance(pbeKey.getAlgorithm());
// Create the ciphers
cipher.init(Cipher.ENCRYPT_MODE, pbeKey, paramSpec);
// Encode the string into bytes using utf-8
final byte[] utf8 = textToEncrypt.getBytes("UTF8");
// Encrypt
final byte[] enc = cipher.doFinal(utf8);
// Encode bytes to base64 to get a string
return new sun.misc.BASE64Encoder().encode(enc);
}
Any suggestions, ideas will help me to figure out what's going on here.
Also this is produce different results:
KeyStore keyStore = KeyStore.getInstance("JCEKS");
keyStore.load(new FileInputStream((pathOfJKSfile)), password.toCharArray());
Key key = keyStore.getKey(keyName, keyPass.toCharArray());
byte[] raw = key.getEncoded();
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "PBEWithHmacSHA512AndAES_256");
final AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, ITERATIONS);
final Cipher cipherEncrypt = Cipher.getInstance(ALGORITHM);
cipherEncrypt.init(Cipher.ENCRYPT_MODE, secretKeySpec, paramSpec);
final byte[] enc = cipherEncrypt.doFinal(messageBytes);
System.out.println( new sun.misc.BASE64Encoder().encode(enc));
And i know that cipher.init() using "JceSecurity.RANDOM" for pruducing different results.
Both algorithms, PBEWithHmacSHA512AndAES_256 and PBEWithMD5AndDES, first generate an encryption key by processing a password, a salt and an iteration count (using HmacSHA512 and MD5, respectively) and then encrypt the plain text (with AES-256 and DES, respectively) using this key and the CBC-mode. When the Cipher-instance is initialized, a pseudo-random initialization vector (IV) is generated that is required for the CBC- mode.
In the context of PBEWithHmacSHA512AndAES_256, the IV is generated using the SecureRandom implementation of the highest-priority installed provider, at least for the Cipher#init()-method used in the code (note that there are several overloads of the Cipher#init()-method and that a SecureRandom-instance can also be passed explicitly). I.e. with each Cipher-initialization a new (random) IV is generated and therefore the encrypted text is always different, even for an identical plain text. For this reason, the encrypted text in your examples changes in this context.
In the context of PBEWithMD5AndDES, the IV is only determined by the password, the salt, the iteration count (and of course the MD5-hash-algorithm itself). Therefore, the IV and the encrypted text do not change in case of repetition (provided that password, salt, iteration count etc. are the same). For this reason, the encrypted text in your example does not change in this context.
The generation of a new, random IV during the Cipher-initalization makes sense with regard to the following requirements for the IV: For security reasons, an IV in CBC-mode (btw this also applies to other modes) may only be used once under the same key. In addition the IV must be unpredictable.
PBEWithMD5AndDES is deprecated.
EDIT:
The use of an IV is standard nowadays (for security reasons). A lot of information can be found on the Internet on this topic e.g. here. In the following I will only describe a few basic things.
The IV used for encryption must be stored in some way because it is required for decryption. The IV does not have to be kept secret, so that it is usually concatenated with the encrypted data (e.g. before the encrypted data) and stored together with them. During decryption, both parts can be separated because the length of the IV is known (16 Byte for AES). E.g for the concatenation in the encryption-method something like the following is used (let iv and enc be the byte-arrays with the IV and the encrypted data, respectively):
byte[] result = new byte[enc.length + iv.length];
System.arraycopy(iv, 0, result, 0, iv.length);
System.arraycopy(enc, 0, result, iv.length, enc.length);
and in the decryption-method the corresponding counterpart (having in mind that the length of an IV in AES is 16 Byte).
In the encryption-method the IV can be determined with Cipher#getIV() (this must of course happen after calling Cipher#init()).
In the decryption-method you have to pass the IV to the PBEParameterSpec-ctor (e.g. let iv be the byte-array with the IV):
IvParameterSpec ivSpec = new IvParameterSpec(iv);
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount, ivSpec);
The generation of an IV can also take place outside the Cipher-class, see e.g. Generating random IV for AES in Java. Then you have to pass that IV in the encryption-method in the same way as above described for the decryption-method.
Note, in connection with an IV some points have to be considered e.g. using a mode without an IV (e.g. ECB), using an IV consisting exclusively of 0-values, using a predictable IV or using an IV more than once under the same key etc. drastically reduces security in general, see e.g. here!

java.security.NoSuchAlgorithmException: PBKDF2WithHmacSHA512 SecretKeyFactory not available Android [duplicate]

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));

Java cryptography routine to run under both Java SE and Android class libraries

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?

AES key wrap encryption

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);
}

What "SecretKeyFactory not available" does mean?

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));

Categories

Resources