java解密创建附加符号

csbfibhn  于 2021-06-29  发布在  Java
关注(0)|答案(3)|浏览(316)

我正在写一个加密和解密代码如下

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());
        }
}
}

在这里,我有一个输出的问题,这是打印输出有一些额外的符号(即问号和方框符号)在它。
我收到的输出是

任何建议都会很有帮助的,谢谢

mepcadol

mepcadol1#

Cipher cipher = Cipher.getInstance("Blowfish");

相当于

Cipher cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");

也就是说每次你打电话 cipher.doFinal 产生额外的填充物。
为了编写一个没有间断填充的文件,应该使用

outputBytes = cipher.update(getFileBytes);

使用 cipher.doFinal 只在最后一次写入文件时。然后您将能够在解密期间使用pkcs5padding而不是nopadding,以便自动删除结尾处的有效填充。
安全注意事项:
ecb模式不好,不应使用。只有很少的用例使用它是有意义的。至少使用随机生成的静脉注射的cbc模式。静脉注射不需要保密,只需要不可预知。我们通常在解密前把它预先编到密文中,然后把它切掉。因为它总是预定义的长度,所以这很容易做到。
使用诸如gcm之类的经过身份验证的操作模式,或者使用诸如hmac-sha256之类的消息身份验证代码,以便检测(恶意)操纵密文并作出React。
今天不应该用河豚。尽管它没有直接的漏洞,但它的小数据块大小可能会使您面临不同的基于协议的漏洞。建议使用块大小为128位的分组密码。我想到了aes。

nwnhqdif

nwnhqdif2#

结合@artjom b的答案。在第5列鼠标上,你会得到一个文件加密程序,它可以用blowfish在cbc模式下对文件进行加密。加密和解密是分块进行的,因此大文件(高达一些gb)可以在没有“内存不足错误”的情况下进行加密和解密。
密钥是随机生成的,您应该记住—如果不知道密钥,就不可能对文件进行解密。
输出:

file encryption with Blowfish CBC mode
used key (Base64): jsErS04so1NCC7Jmds6Grr+0tPkNoaj0hx/izLaW5H8=
result encryption: true
result decryption: true

安全警告:代码没有异常处理,没有正确的文件处理(例如,未经通知就覆盖),并且仅用于教育目的:

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

public class BlowfishCbcFileEncryption {
    public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException,
            InvalidKeyException, InvalidAlgorithmParameterException {
        System.out.println("file encryption with Blowfish CBC mode");

        String uncryptedFilename = "uncrypted.txt";
        String encryptedFilename = "encrypted.enc";
        String decryptedFilename = "decrypted.txt";

        // random blowfish 256 key
        byte[] key = new byte[32];
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextBytes(key);
        System.out.println("used key (Base64): " + base64Encoding(key));

        // random iv
        byte[] iv = new byte[8]; // blowfish iv is 8 bytes long
        secureRandom.nextBytes(iv);

        boolean result;
        result = encryptCbcFileBufferedCipherOutputStream(uncryptedFilename, encryptedFilename, key, iv);
        System.out.println("result encryption: " + result);
        result = decryptCbcFileBufferedCipherInputStream(encryptedFilename, decryptedFilename, key);
        System.out.println("result decryption: " + result);

    }

    public static boolean encryptCbcFileBufferedCipherOutputStream(String inputFilename, String outputFilename, byte[] key, byte[] iv)
            throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
        try (FileInputStream in = new FileInputStream(inputFilename);
             FileOutputStream out = new FileOutputStream(outputFilename);
             CipherOutputStream encryptedOutputStream = new CipherOutputStream(out, cipher);) {
            out.write(iv);
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "Blowfish");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] buffer = new byte[8096];
            int nread;
            while ((nread = in.read(buffer)) > 0) {
                encryptedOutputStream.write(buffer, 0, nread);
            }
            encryptedOutputStream.flush();
        }
        if (new File(outputFilename).exists()) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean decryptCbcFileBufferedCipherInputStream(String inputFilename, String outputFilename, byte[] key) throws
            IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
        byte[] iv = new byte[8]; // blowfish iv is 8 bytes long
        Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
        try (FileInputStream in = new FileInputStream(inputFilename); // i don't care about the path as all is local
             CipherInputStream cipherInputStream = new CipherInputStream(in, cipher);
             FileOutputStream out = new FileOutputStream(outputFilename)) // i don't care about the path as all is local
        {
            byte[] buffer = new byte[8192];
            in.read(iv);
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "Blowfish");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
            int nread;
            while ((nread = cipherInputStream.read(buffer)) > 0) {
                out.write(buffer, 0, nread);
            }
            out.flush();
        }
        if (new File(outputFilename).exists()) {
            return true;
        } else {
            return false;
        }
    }

    private static String base64Encoding(byte[] input) {
        return Base64.getEncoder().encodeToString(input);
    }
}
huwehgph

huwehgph3#

每次将字符串转换为字节数组时,都使用vm属性中的默认文件编码,而不是utf-8。
因此,要解决此问题,有两个选项:在java系统属性中定义默认编码:

System.setProperty("file.encoding", StandardCharsets.UTF_8.name());

或通过每次将字符串转换为字节来添加字符集编码:

"writing a file using encryption ".getBytes(StandardCharsets.UTF_8);

相关问题