gpt4 book ai didi

java - "Wrong algorithm"尝试在 Java 中解密时出错

转载 作者:塔克拉玛干 更新时间:2023-11-02 07:54:15 27 4
gpt4 key购买 nike

我首先要描述我遇到的问题,然后介绍我正在尝试做的事情的一些背景。最后,我将粘贴一些相关的代码片段。

我正在尝试使用 https://stackoverflow.com/a/992413/171993 中指定的方法实现 key 加密/解密.如果我按原样使用该示例,它会起作用(尽管我确实注意到我需要重新实例化 Cipher 类,否则解密会产生垃圾)。但是,在我的实现中出现以下异常:

java.security.InvalidKeyException: Wrong algorithm: AES or Rijndael required
at com.sun.crypto.provider.AESCrypt.init(AESCrypt.java:77)
at com.sun.crypto.provider.CipherBlockChaining.init(CipherBlockChaining.java:91)
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:469)
at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:217)
at javax.crypto.Cipher.implInit(Cipher.java:790)
at javax.crypto.Cipher.chooseProvider(Cipher.java:848)
at javax.crypto.Cipher.init(Cipher.java:1347)
at javax.crypto.Cipher.init(Cipher.java:1281)
at securitytest.SecurityManager.getCipher(SecurityManager.java:175)
at securitytest.SecurityManager.decryptSecretKey(SecurityManager.java:379)
at securitytest.SecurityManager.<init>(SecurityManager.java:82)
at securitytest.Test.main(Test.java:44)

为了解决这个明显的问题,是的,我确实使用了相同的算法:事实上,我将 AES/CBC/PKCS5Padding 分配给一个常量,并使用它来实例化 Cipher 加密和解密类。我也尝试过仅使用 AES 实例化 Cipher 进行解密,但这也不起作用。

我想做的是使用 AES/CBC/PKCS5Padding 密码保护 key 。我生成一个随机盐和初始化 vector 。加密 key 后,我将初始化 vector (一个字节数组)附加到加密值(也是一个字节数组,创建一个新数组)。然后,我在 Base64 中对该值进行编码,并将其与 salt 一起存储在 Sqlite 数据库中(为了简单起见,我将其存储为以逗号分隔的值字符串)。但是,当我尝试解密时,出现上述异常。我可以验证在调用加密方法之后和解密方法之前,以下值完全相同(转换为 Base64 以便打印出来):

  1. 初始化 vector
  2. 加密 key (即密文)

我已经尝试过 Java 6 和 7:两者的结果相同。我还排除了无限强度管辖政策文件的问题。事实上,如果我用另一种算法替换“AES”并相应地调整盐的长度(例如,IV 长度为 8 的“Blowfish”,它会产生 java.security.InvalidKeyException:错误的算法:需要河豚)。

Google 无法帮助我解决这个问题。如果有人能对此有所了解,我将不胜感激。

以下是一些代码片段(抱歉,有点粗糙):

private static final int INIT_VECTOR_LENGTH = 16;
private static final int PRIVATE_KEY_LENGTH = 128;
private static final int SALT_LENGTH = 16;
private static final int PBE_KEYSPEC_ITERATIONS = 65536;

private static final String CIPHER_ALGORITHM = "AES";
private static final String CIPHER_ALGORITHM_MODE = "CBC";
private static final String CIPHER_ALGORITHM_PADDING = "PKCS5Padding";
private static final String DIGEST = "SHA1";
private static final String PLAINTEXT_ENCODING = "UTF8";
private static final String PRNG = DIGEST + "PRNG";
private static final String SECRET_KEY_FACTORY = "PBKDF2WithHmac" + DIGEST;

private static final String CIPHER = CIPHER_ALGORITHM + "/" + CIPHER_ALGORITHM_MODE + "/" + CIPHER_ALGORITHM_PADDING;

private IvParameterSpec ivSpec;
private final BASE64Encoder encoder = new BASE64Encoder();
private final BASE64Decoder decoder = new BASE64Decoder();

private Cipher getCipher(SecretKey key, int mode) {

Cipher cipher = null;

try {
cipher = Cipher.getInstance(CIPHER);
}
catch (NoSuchAlgorithmException e) {System.err.println(System.err.println(e.getMessage());}
catch (NoSuchPaddingException e) {System.err.println(e.getMessage());}

try {
if (mode == Cipher.ENCRYPT_MODE) {
cipher.init(mode, key);
AlgorithmParameters params = cipher.getParameters();
ivSpec = params.getParameterSpec(IvParameterSpec.class);
}
else {
/* This is my point-of-failure. */
cipher.init(mode, key, ivSpec);
}
}
catch (InvalidKeyException e) {System.err.println(e.getMessage());}
catch (InvalidAlgorithmParameterException e) {System.err.println(e.getMessage());}
catch (InvalidParameterSpecException e) {System.err.println(e.getMessage());}

return cipher;

}

private SecurityData.Secrets generateSecrets(SecretKey decryptedKey, byte[] salt, String passphrase) {

/* Generate a new key for encrypting the secret key. */
byte[] raw = null;
PBEKey key = null;
PBEKeySpec password = new PBEKeySpec(passphrase.toCharArray(), salt, PBE_KEYSPEC_ITERATIONS, PRIVATE_KEY_LENGTH);
SecretKeyFactory factory = null;
byte[] initVector = null;
byte[] secretKeyBytes = decryptedKey.getEncoded();

try {
factory = SecretKeyFactory.getInstance(SECRET_KEY_FACTORY);
key = (PBEKey) factory.generateSecret(password);
}
catch (NoSuchAlgorithmException e) {System.err.println(e.getMessage());}
catch (InvalidKeySpecException e) {System.err.println(e.getMessage());}

SecretKeySpec newKey = new SecretKeySpec(key.getEncoded(), CIPHER_ALGORITHM);

/* Encrypt the secret key. */
IvParameterSpec ivSpec = new IvParameterSpec(initVector);
Cipher cipher = getCipher(newKey, ivSpec, Cipher.ENCRYPT_MODE);

try {
raw = cipher.doFinal(secretKeyBytes);
}
catch (IllegalBlockSizeException e) {System.err.println(e.getMessage());}
catch (BadPaddingException e) {System.err.println(e.getMessage());}

return new SecurityData.Secrets(encoder.encode(concatByteArrays(initVector, raw)), joinByteArray(salt));

}

private SecretKey decryptSecretKey(String encryptedKey, String salt, String passphrase) {

/* Get initialisation vector. */
byte[] raw = null, decoded = null, initVector = new byte[INIT_VECTOR_LENGTH];
try {
decoded = decoder.decodeBuffer(encryptedKey);
} catch (IOException e) {System.err.println(e.getMessage());}
System.arraycopy(decoded, 0, initVector, 0, INIT_VECTOR_LENGTH);
raw = new byte[decoded.length-INIT_VECTOR_LENGTH];
System.arraycopy(decoded, INIT_VECTOR_LENGTH, raw, 0, decoded.length-INIT_VECTOR_LENGTH);
IvParameterSpec ivSpec = new IvParameterSpec(initVector);

/* Generate the key. */
byte[] rawSalt = splitByteArrayString(salt);
PBEKeySpec password = new PBEKeySpec(passphrase.toCharArray(), rawSalt, PBE_KEYSPEC_ITERATIONS, PRIVATE_KEY_LENGTH);
SecretKeyFactory factory = null;
PBEKey key = null;
try {
factory = SecretKeyFactory.getInstance(SECRET_KEY_FACTORY);
key = (PBEKey) factory.generateSecret(password);
}
catch (NoSuchAlgorithmException e) {System.err.println(e.getMessage());}
catch (InvalidKeySpecException e) {System.err.println(e.getMessage());}

Cipher cipher = getCipher(key, Cipher.DECRYPT_MODE);

/* Decrypt the message. */
byte[] stringBytes = null;
try {
stringBytes = cipher.doFinal(raw);
}
catch (IllegalBlockSizeException e) {System.err.println(e.getMessage());}
catch (BadPaddingException e) {System.err.println(e.getMessage());}

/* Converts the decoded message to a String. */
String clear = null;
try {
clear = new String(stringBytes, PLAINTEXT_ENCODING);
}
catch (UnsupportedEncodingException e) {System.err.println(e.getMessage());}

return new SecretKeySpec(clear.getBytes(), CIPHER_ALGORITHM);

}

最佳答案

SecretKey 对象需要从其 getAlgorithm() 方法返回“AES”。这就是该示例具有以下步骤的原因:

SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

关于java - "Wrong algorithm"尝试在 Java 中解密时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9670602/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com