我有一个Java AES 256加密代码,如下所示:
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;
}
}
在这种情况下,我硬编码salt字节和iv字节只是为了确保我的编码正确加密消息,所以它可以被另一台服务器中的cryptoJS读取。但是当我通过调用加密方法发送加密文本时,它总是被cryptoJS拒绝,说我的加密消息不正确
CryptoJS在另一台服务器上,它是这样的:
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();
有人能帮我找到我的java代码中的错误吗?非常感谢你
编辑: 根据Artjom.B的评论和建议,我试过这个:
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;
}
但仍无济于事。 CryptoJS一直说我传递了错误的密码。 有人可以帮忙吗?非常感谢你