Java openssl加密/解密密钥生成
我正在使用Java8,并试图用Java模拟以下openssl调用 加密:Java openssl加密/解密密钥生成,java,openssl,cryptography,aes,sha256,Java,Openssl,Cryptography,Aes,Sha256,我正在使用Java8,并试图用Java模拟以下openssl调用 加密: echo-n'hello world'| openssl enc-a-aes-256-cbc-md sha256-pass:97DE:4F76 U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc= 解密: echo U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc=| openssl enc-d-a-aes-256-cbc-md sha256-pas
echo-n'hello world'| openssl enc-a-aes-256-cbc-md sha256-pass:97DE:4F76
U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc=
解密:
echo U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc=| openssl enc-d-a-aes-256-cbc-md sha256-pass-pass:97DE:4F76
你好,世界
问题:
PBKDF2WithHmacSHA256
更改为PBKDF2WithHmacSHA1
package test;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
public class Test {
public static final String PASSWORD = "97DE:4F76";
public static String encryptString(String clearText, String password) {
return "";
}
// echo U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc= | openssl enc -d -a -aes-256-cbc -md sha256 -pass pass:97DE:4F76
//
// see https://stackoverflow.com/a/992413, https://stackoverflow.com/a/15595200,
// https://stackoverflow.com/a/22445878, https://stackoverflow.com/a/11786924
public static String decryptString(String cypherText, String password) {
byte[] dataBase64 = DatatypeConverter.parseBase64Binary(cypherText);
byte[] salt = {
(byte)0x0, (byte)0x0, (byte)0x0, (byte)0x0,
(byte)0x0, (byte)0x0, (byte)0x0, (byte)0x0
};
try {
// generate the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); // "PBKDF2WithHmacSHA1"
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
// decrypt the message
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] decrypted = cipher.doFinal(dataBase64);
String answer = new String(decrypted, "UTF-8");
return answer;
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
public static void main(String[] args) {
System.out.println(decryptString("U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc=", PASSWORD));
}
}
这是运行上述代码的当前输出:
java.security.InvalidKeyException: Illegal key size at
javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039) at
javax.crypto.Cipher.init(Cipher.java:1393) at
javax.crypto.Cipher.init(Cipher.java:1327) at
test.Test.decryptString(Test.java:42) at
test.Test.main(Test.java:55)
更新: 这是我在使用这个答案后最终实现的代码:->包含EVP_BytesToKey的其余常量和实现
public static String decryptString(String cypherText, String password) {
try {
// decode the base64 cypherText into salt and encryptedString
byte[] dataBase64 = DatatypeConverter.parseBase64Binary(cypherText);
byte[] salt = Arrays.copyOfRange(dataBase64, SALT_OFFSET, SALT_OFFSET + SALT_SIZE);
byte[] encrypted = Arrays.copyOfRange(dataBase64, CIPHERTEXT_OFFSET, dataBase64.length);
System.out.println("dataBase64 = " + new String(dataBase64));
System.out.println("salt: " + new BigInteger(1, salt).toString(16));
System.out.println("encrypted: " + new BigInteger(1, encrypted).toString(16));
// --- specify cipher and digest for EVP_BytesToKey method ---
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
MessageDigest sha1 = MessageDigest.getInstance("SHA-256");
// create key and IV
final byte[][] keyAndIV = EVP_BytesToKey(
KEY_SIZE_BITS / Byte.SIZE,
cipher.getBlockSize(),
sha1,
salt,
password.getBytes("ASCII"),
ITERATIONS);
SecretKeySpec key = new SecretKeySpec(keyAndIV[INDEX_KEY], "AES");
IvParameterSpec iv = new IvParameterSpec(keyAndIV[INDEX_IV]);
// initialize the Encryption Mode
cipher.init(Cipher.DECRYPT_MODE, key, iv);
// decrypt the message
byte[] decrypted = cipher.doFinal(encrypted);
String answer = new String(decrypted, "UTF-8"); // should this be "ASCII"?
return answer;
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
由于某些法律原因,256位AES在Java中受到限制。您需要在JDK中显式启用强加密。搜索“无限制力量管辖权政策”您的2)可能。试试看。@Thilo,早些时候我下载了JCE,并将其与其他JAR一起放入java文件夹。然而,我刚刚意识到我安装了多个版本的java,并且我将这些JAR放在了错误的文件夹版本中。明天早上我回来工作的时候,我会用正确的java版本再试一次。我已经把这个标记为重复,因为另一个答案解决了我的问题@蒂洛,关于JCE你是对的。此外,从EVP_BytesToKey的另一个答案中实现算法也很有魅力!用于某些内部组件。以前使用MD5,1.1.0切换到SHA256。请注意,此更改不会影响
EVP\u BytesToKey
和openssl enc
等命令。