I have a Java AES 256 encryption code like this :
public class EncryptDecryptTwo {
static {
try {
Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");
field.setAccessible(true);
field.set(null, java.lang.Boolean.FALSE);
} catch (Exception ex) {
}
}
private static String keyEnc = "BtDMQ7RfNVoRzJ7GYE32";
// Performs Encryption
public static String encrypt(String plainText) throws Exception {
String passphrase = keyEnc;
byte[] iv = DatatypeConverter.parseHexBinary("2aba86027a6f79dd463b81b0539bacb5");
byte[] salt = DatatypeConverter.parseHexBinary("0f3d1b0d514ca313");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
SecretKeySpec sKey = (SecretKeySpec) generateKeyFromPassword(passphrase, salt);
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, sKey, ivParameterSpec);
byte[] encryptedData = c.doFinal(plainText.getBytes());
return DatatypeConverter.printBase64Binary(encryptedData);
}
public static SecretKey generateKeyFromPassword(String password, byte[] saltBytes) throws GeneralSecurityException {
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), saltBytes, 1, 256);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKey secretKey = keyFactory.generateSecret(keySpec);
return new SecretKeySpec(secretKey.getEncoded(), "AES");
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
}
return data;
}
}
In this case, I hardcoded the salt bytes and iv bytes just to make sure my coding is encrypt the message right, so it can be read by cryptoJS in another server. But when I send the encrypted text by calling the encrypt method, it is always rejected by the cryptoJS, saying that my encrypted message is not correct
The CryptoJS is in another server and it is like this :
var CryptoJSAesJson = {
stringify: function (cipherParams) {
var j = {ct: cipherParams.cipherText.toString(CryptoJS.enc.Base64)};
if (cipherParams.iv) j.iv = cipherParams.iv.toString();
if (cipherParams.salt) j.s = cipherParams.salt.toString();
return JSON.stringify(j);
},
parse: function (jsonStr) {
var j = JSON.parse(jsonStr);
var cipherParams = CryptoJS.lib.CipherParams.create({ciphertext: CryptoJS.enc.Base64.parse(j.ct)});
if (j.iv) cipherParams.iv = CryptoJS.enc.Hex.parse(j.iv)
if (j.s) cipherParams.salt = CryptoJS.enc.Hex.parse(j.s)
return cipherParams;
}
}
var encrypted = CryptoJS.AES.encrypt(JSON.stringify($scope.loginData.password), __ENV.AES_KEY, { format: CryptoJSAesJson}).toString();
Can anybody help me finding what's wrong in my java code? Thank you very much
Edited : According to Artjom.B's comment and advise, I tried this :
static {
try {
Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");
field.setAccessible(true);
field.set(null, java.lang.Boolean.FALSE);
} catch (Exception ex) {
}
}
public static void main(String[] args) throws UnsupportedEncodingException, GeneralSecurityException {
String plaintext = "someplaintext";
String password = "BtDMQ7RfNVoRzWGjS2DK";
int keySize = 256;
int ivSize = 128;
byte[] salt = DatatypeConverter.parseHexBinary("5ba2b0e0bb968f47"); // yes, for testing, I use a fixed salt
byte[] key = new byte[keySize/8];
byte[] iv = new byte[ivSize/8];
EvpKDF(password.getBytes("UTF-8"), keySize, ivSize, salt, key, iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
byte[] encryptedText = cipher.doFinal((plaintext).getBytes());
System.out.println("SALT : " + DatatypeConverter.printHexBinary(salt));
System.out.println("IV : " + DatatypeConverter.printHexBinary(iv));
System.out.println("CT : " + DatatypeConverter.printBase64Binary(encryptedText));
// I sent salt, IV, and ciphertext to CryptoJS
}
public static byte[] EvpKDF(byte[] password, int keySize, int ivSize, byte[] salt, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException {
return EvpKDF(password, keySize, ivSize, salt, 1, "MD5", resultKey, resultIv);
}
public static byte[] EvpKDF(byte[] password, int keySize, int ivSize, byte[] salt, int iterations, String hashAlgorithm, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException {
keySize = keySize / 32;
ivSize = ivSize / 32;
int targetKeySize = keySize + ivSize;
byte[] derivedBytes = new byte[targetKeySize * 4];
int numberOfDerivedWords = 0;
byte[] block = null;
MessageDigest hasher = MessageDigest.getInstance(hashAlgorithm);
while (numberOfDerivedWords < targetKeySize) {
if (block != null) {
hasher.update(block);
}
hasher.update(password);
block = hasher.digest(salt);
hasher.reset();
// Iterations
for (int i = 1; i < iterations; i++) {
block = hasher.digest(block);
hasher.reset();
}
System.arraycopy(block, 0, derivedBytes, numberOfDerivedWords * 4,
Math.min(block.length, (targetKeySize - numberOfDerivedWords) * 4));
numberOfDerivedWords += block.length/4;
}
System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4);
System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4);
return derivedBytes; // key + iv
}
/**
* Copied from http://stackoverflow.com/a/140861
* */
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
But still no avail. The CryptoJS keep saying that I pass an incorrect password. Can anybody help? Thank you very much