gpt4 book ai didi

java - BadPaddingException:GCM 中的 mac 检查失败

转载 作者:行者123 更新时间:2023-11-30 10:00:20 26 4
gpt4 key购买 nike

我正在尝试使用 AES-GCM 和 JDK 1.8 CipherOutputStream 进行加密/解密,但在解密过程中出现 BadPaddingException。我在加密和解密期间使用相同的 IV 和 key ,但不确定出了什么问题。请看下面的代码:

 static String AES_GCM_MODE = "AES/GCM/NoPadding";

SecretKey secretKey;

public SymmetricFileEncryption(){

Security.insertProviderAt( new BouncyCastleProvider(), 1);
setSecretKey();
}

public static void main(String[] args) throws Exception {

File inputFile = new File("test.txt");
File outputFile = new File("test-crypt.txt");
File out = new File("test-decrypt.txt");

SymmetricFileEncryption sym = new SymmetricFileEncryption();
sym.encrypt(inputFile, outputFile);
sym.decrypt(outputFile, out);
}

public Cipher getEncryptionCipher() throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException {

Cipher cipher = Cipher.getInstance(AES_GCM_MODE, "BC");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, getInitializationVector());
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(), new IvParameterSpec(getInitializationVector()) );
return cipher;
}

private Cipher getDecryptionCipher(File inputFile) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, IOException, NoSuchProviderException {
//initialize cipher
Cipher cipher = Cipher.getInstance(AES_GCM_MODE, "BC");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, getInitializationVector());
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(),new IvParameterSpec(getInitializationVector()) );
return cipher;
}

public void encrypt(File inputFile, File outputFile) throws Exception {
Cipher cipher = getEncryptionCipher();
FileOutputStream fos = null;
CipherOutputStream cos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(inputFile);
fos = new FileOutputStream(outputFile);
cos = new CipherOutputStream(fos, cipher);
byte[] data = new byte[16];
int read = fis.read(data);
while (read != -1) {
cos.write(data, 0, read);
read = fis.read(data);
}
cos.flush();
}catch (Exception e){
e.printStackTrace();
}
finally {
fos.close();
cos.close();
fis.close();
}
String iv = new String(cipher.getIV());
}

public void decrypt(File inputFile, File outputFile) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, IOException, NoSuchProviderException {

Cipher cipher = getDecryptionCipher(inputFile);
FileInputStream inputStream = null;
FileOutputStream outputStream = null;
CipherInputStream cipherInputStream = null;

try{
inputStream = new FileInputStream(inputFile);
cipherInputStream = new CipherInputStream(inputStream, cipher);
outputStream = new FileOutputStream(outputFile);
byte[] data = new byte[16];
int read = cipherInputStream.read(data);
while(read != -1){
outputStream.write(data);
read = cipherInputStream.read(data);
}
outputStream.flush();
}catch (Exception e){
e.printStackTrace();
}
finally {
cipherInputStream.close();
inputStream.close();
outputStream.close();
}
}

public void setSecretKey(){
SecureRandom secureRandom = new SecureRandom();
byte[] key = new byte[16];
secureRandom.nextBytes(key);
secretKey = new SecretKeySpec(key, "AES");
}

public SecretKey getSecretKey(){
return secretKey;
}

public byte[] getInitializationVector(){

String ivstr = "1234567890ab"; //12 bytes
byte[] iv = ivstr.getBytes();//new byte[12];
return iv;
}

以上代码在行解密期间导致以下错误int read = cipherInputStream.read(data);

javax.crypto.BadPaddingException: mac check in GCM failed
at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:128)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:246)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:222)
at com.rocketsoftware.abr.encryption.SymmetricFileEncryption.decrypt(SymmetricFileEncryption.java:107)

最佳答案

  • 加密无法正常工作:在 encrypt 中,CipherOutputStream#close必须在 FileOutputStream#close 之前调用。这是因为 CipherOutputStream#close 调用了 Cipher#doFinal生成标签并将其附加到密文。如果尚未调用 FileOutputStream#close,则此部分只能写入 FileOutputStream 实例。顺便说一句,不需要调用 CipherOutputStream#flush

  • 解密也有问题:decrypt中,outputStream.write(data)必须换成outputStream.write(data, 0, 读)。否则通常会将太多数据写入 FileOutputStream 实例。

  • 类(class) javax.crypto.CipherInputStreamjavax.crypto.CipherOutputStream可能会执行身份验证误报,因此适合 GCM 模式,例如来自 CipherInputStream 的文档 (Java 12):

    This class may catch BadPaddingException and other exceptions thrown by failed integrity checks during decryption. These exceptions are not re-thrown, so the client may not be informed that integrity checks failed. Because of this behavior, this class may not be suitable for use with decryption in an authenticated mode of operation (e.g. GCM). Applications that require authenticated encryption can use the Cipher API directly as an alternative to using this class.

    因此,要么按照文档中的建议直接使用 Cipher API,要么使用 BouncyCaSTLe 实现 org.bouncycastle.crypto.io.CipherInputStreamorg.bouncycastle.crypto.io.CipherOutputStream ,例如用于加密:

    import org.bouncycastle.crypto.io.CipherInputStream;
    import org.bouncycastle.crypto.io.CipherOutputStream;
    import org.bouncycastle.crypto.engines.AESEngine;
    import org.bouncycastle.crypto.modes.AEADBlockCipher;
    import org.bouncycastle.crypto.modes.GCMBlockCipher;
    import org.bouncycastle.crypto.params.AEADParameters;
    import org.bouncycastle.crypto.params.KeyParameter;
    ...
    public void encrypt(File inputFile, File outputFile) throws Exception {

    AEADBlockCipher cipher = getEncryptionCipher();
    // Following code as before (but with fixes described above)
    ...
    }

    public AEADBlockCipher getEncryptionCipher() throws Exception {

    AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine());
    cipher.init(true, // encryption
    new AEADParameters(
    new KeyParameter(getSecretKey().getEncoded()),
    128, // tag length
    getInitializationVector(),
    "Optional Associated Data".getBytes()));
    return cipher;
    }
    ...

    和模拟解密。

    请注意,即使认证失败,也会执行解密,因此开发者必须确保在这种情况下丢弃和不使用结果。

关于java - BadPaddingException:GCM 中的 mac 检查失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58059932/

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