Java 解密创建附加符号

s.s*_*ash 1 java encryption blowfish

我写的加解密代码如下

import java.io.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.BadPaddingException;
import java.nio.file.Files;
import java.util.Scanner;

public class EncryptFile
{
    public static void main(String args[]) throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
//Encrypt Mode
        FileOutputStream outputStream = new FileOutputStream(new File("D:\\encryptedNewStringFile.txt"));
        Key secretKey = new SecretKeySpec("encKey".getBytes(), "Blowfish");
        Cipher cipher = Cipher.getInstance("Blowfish");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] getFileBytes = "writing a file using encryption ".getBytes();
        byte[] outputBytes = cipher.doFinal(getFileBytes);
        outputStream.write(outputBytes);
        getFileBytes = "\n".getBytes();
        outputBytes = cipher.doFinal(getFileBytes);
        outputStream.write(outputBytes);
        getFileBytes = "This is New Line 2 \nThis is NewLine 3".getBytes();
        outputBytes = cipher.doFinal(getFileBytes);
        outputStream.write(outputBytes);
        outputStream.close();
//Decrypt Mode
        File curFile = new File("D:\\encryptedNewStringFile.txt");
        secretKey = new SecretKeySpec("encKey".getBytes(), "Blowfish");
        cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        getFileBytes = Files.readAllBytes(curFile.toPath());
        outputBytes = cipher.doFinal(getFileBytes);
        InputStream bai = new ByteArrayInputStream(outputBytes);
        BufferedReader bfReader = new BufferedReader(new InputStreamReader(bai));
        Scanner scan = new Scanner(bfReader);
        while(scan.hasNextLine())
        {
            System.out.println(scan.nextLine());
        }
}
}
Run Code Online (Sandbox Code Playgroud)

这里我有一个输出问题,即打印输出中有一些额外的符号(即问号和框符号)。
我收到的输出是
在此处输入图片说明

任何建议都会非常有帮助,提前致谢

Art*_* B. 6

Cipher cipher = Cipher.getInstance("Blowfish");
Run Code Online (Sandbox Code Playgroud)

相当于

Cipher cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
Run Code Online (Sandbox Code Playgroud)

这意味着每次调用时cipher.doFinal都会产生额外的填充。

为了写一个没有间歇性填充的文件,你应该使用

outputBytes = cipher.update(getFileBytes);
Run Code Online (Sandbox Code Playgroud)

并且cipher.doFinal仅在最后一次写入文件时使用。然后您将能够在解密期间使用 PKCS5Padding 而不是 NoPadding 以自动删除末尾的有效填充。


安全考虑:

  • ECB 模式不好,不应使用。只有很少的用例可以使用它。至少使用 CBC 模式和随机生成的 IV。IV 不需要是秘密的,而只是不可预测的。我们通常将它添加到密文并在解密之前将其切片。因为它总是有一个预定义的长度,所以这很容易做到。
  • 使用经过身份验证的操作模式(如 GCM)或使用消息身份验证代码(如 HMAC-SHA256)来检测密文的(恶意)操作并做出反应。
  • 今天不应该使用河豚。虽然它没有直接的漏洞,但它的小块大小可能会让你面临不同的基于协议的漏洞。建议使用块大小为 128 位的块密码。AES 浮现在脑海中。