gpt4 book ai didi

java - 在密码实例算法之间切换会使内容无法解密

转载 作者:行者123 更新时间:2023-11-29 04:28:58 36 4
gpt4 key购买 nike

我们有一个稳定的代码库(我们认为),我们将文件流式传输到代码库中,对其进行加密,然后写入生成的加密文件。然后我们解密加密文件以确保该过程在整个循环中正常运行。

我们一直在使用 PBEWITHSHA1ANDDESEDE 并且它已经正常工作了大约一年,但我们注意到该算法被认为有风险/损坏。但是,我们尝试换用更好的算法,但现在内容无法解密且无法读取。根据我们发现的 Veracode 博客 here,我们换成的算法是 PBEWithHmacSHA512AndAES_128 .

如果我们不做其他代码更改,为什么切换到这个替代算法会导致文件不加密/解密整圈?我们可以做些什么来让它发挥作用?

下面是代码的重要(我认为)部分,带有注释/注释。

// defined outside the below method; this algorithm works:
private static String ALGORITHM = "PBEWITHSHA1ANDDESEDE";

// the new version, which fails:
//private static String ALGORITHM = "PBEWithHmacSHA512AndAES_128";

private static Cipher getCipher(int mode, String password) throws NoSuchAlgorithmException, InvalidKeySpecException,
NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {

// Create secret key using password
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);

// Create the cipher
byte[] salt = new byte[SALT_SIZE];
salt = password.getBytes();

PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, PBEPARAMETERSPEC_ITERATION_COUNT);
Cipher cipher = Cipher.getInstance(ALGORITHM);

// this original line causes crash with the new algorithm, reporting:
// Exception in thread "main" java.security.InvalidAlgorithmParameterException: Missing parameter type: IV expected
// solved as per this S.O. post:
// https://stackoverflow.com/questions/29215274/how-do-i-properly-use-the-pbewithhmacsha512andaes-256-algorithm
cipher.init(mode, secretKey, pbeParameterSpec);

// this new line causes the encryption/decryption to apparently fail, giving results that look like this:
// �0�.�����j�"��ۗP#o˾���IYc� �we����)�Tq(f�C���.��njDt�.pG��
//cipher.init(mode, secretKey, cipher.getParameters());
return cipher;
}

编辑:

我们目前使用PBEWITHSHA1ANDDESEDE进行加解密。我们要做的是切换,以便我们使用 PBEWithHmacSHA512AndAES_128 进行加密和解密。我们不希望使用 PBEWithHmacSHA512AndAES_128 解密使用 PBEWITHSHA1ANDDESEDE 加密的密文。

需要明确的是,这一切都发生在一个类中,并在沙盒中执行一次作为概念证明。我们只想得到 PBEWithHmacSHA512AndAES_128 算法进行加密,并立即解密单个非关键内容。我们只是想根据 Veracode 的建议替换 PBEWITHSHA1ANDDESEDE,但我们无法弄清楚为什么这不起作用。

应要求,这里是整个 PoC:

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

public class FileEncryption {

private static String PASSWORD = "fake-password-for-stack-overflow-post";
private static String SOURCE_PATH = "";
private static String SOURCE_FILE;
private static String ENCRYPTED_FILE;
private static String DECRYPTED_FILE;

private static String ALGORITHM = "PBEWithHmacSHA512AndAES_128";
private static int SALT_SIZE = 8;
private static int PBEPARAMETERSPEC_ITERATION_COUNT = 100;

public static void main(String[] args) throws Exception {
if(args.length != 1) {
System.out.println("Only accept a single variable, the path to input.txt.");
System.out.println("(output will go to same dir)");
return;
}

SOURCE_PATH = args[0];
System.out.println("Set path: " + SOURCE_PATH);

if( SOURCE_PATH.charAt(SOURCE_PATH.length()-1) != '/' ) {
SOURCE_PATH += '/';
}

SOURCE_FILE = SOURCE_PATH + "plainfile.txt";
ENCRYPTED_FILE = SOURCE_PATH + "plainfile.encrypted.txt";
DECRYPTED_FILE = SOURCE_PATH + "plainfile.decrypted.txt";
encryptContent(SOURCE_FILE, ENCRYPTED_FILE, PASSWORD);
decryptContent(ENCRYPTED_FILE, DECRYPTED_FILE, PASSWORD);
}

private static void encryptContent(String inputFile, String outputFile, String password) throws Exception {
Cipher cipher = getCipher(Cipher.ENCRYPT_MODE, password);
performReadWrite(inputFile, outputFile, cipher);
}

private static void decryptContent(String inputFile, String outputFile, String password) throws Exception {
Cipher cipher = getCipher(Cipher.DECRYPT_MODE, password);
performReadWrite(inputFile, outputFile, cipher);
performRead(inputFile, cipher);
}

private static void performReadWrite(String inputFile, String outputFile, Cipher cipher)
throws FileNotFoundException, IOException {

FileInputStream inFile = new FileInputStream(inputFile);
FileOutputStream outFile = new FileOutputStream(outputFile);

CipherOutputStream cos = new CipherOutputStream(outFile, cipher);

int c;
while ((c = inFile.read()) != -1)
{
cos.write(c);
}

cos.close();
cos = null;
inFile.close();
inFile = null;
}

private static void performRead(String inputFile, Cipher cipher)
throws FileNotFoundException, IOException {

FileInputStream inFile = new FileInputStream(inputFile);

ByteArrayOutputStream os = new ByteArrayOutputStream();
CipherOutputStream cos = new CipherOutputStream(os, cipher);

int c;
while ((c = inFile.read()) != -1)
{
cos.write(c);
}

cos.close();
cos = null;
inFile.close();
inFile = null;

// aClass.outputStreamMethod(os);
String aString = new String(os.toByteArray(),"UTF-8");
System.out.println(aString);
}

private static Cipher getCipher(int mode, String password) throws NoSuchAlgorithmException, InvalidKeySpecException,
NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {

// Create secret key using password
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);

// Create the cipher
byte[] salt = new byte[SALT_SIZE];
salt = password.getBytes();

PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, PBEPARAMETERSPEC_ITERATION_COUNT);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(mode, secretKey, cipher.getParameters());
return cipher;
}

}

最佳答案

好的,所以您使用算法 A 加密了一些数据,然后更改代码以使用算法 B,现在您正在尝试解密使用算法 A 加密的密文,对吗?为什么你认为这行得通?毕竟算法不同。

相反,您应该编写一些使用算法 A 解密现有密文并立即使用算法 B 对其进行加密的迁移代码。对所有密文运行迁移代码以获得一组干净的加密文件,然后使用算法 B 直到算法C 来了。


安全考虑

由于您正在更改代码,因此可以使其变得更好。

最好对您的密文进行身份验证,以便像 padding oracle attack 这样的攻击不可能。这可以通过 GCM 或 EAX 等身份验证模式或使用 encrypt-then-MAC 来完成。方案。

关于java - 在密码实例算法之间切换会使内容无法解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44640282/

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