【问题标题】:I Write Encrypted text to a file in my program but I cant Decrypt the text from the file我将加密文本写入程序中的文件,但无法解密文件中的文本
【发布时间】:2020-11-07 08:45:08
【问题描述】:

这是我尝试执行加密/解密过程的方法。当我运行程序时抛出异常缺少参数类型:IV 预期。现在问这个问题这是我能做的最好的。请通知我我的错误。

PBEKeySpec pbeKeySpec;
PBEParameterSpec pbeParamSpec;
SecretKeyFactory keyFac;

byte[] salt = new byte[16];

int count = 1000;

SecureRandom secRandom = SecureRandom.getInstanceStrong();
secRandom.nextBytes(salt);

pbeParamSpec = new PBEParameterSpec(salt , count);

char[] password = "bNm1".toCharArray();
pbeKeySpec = new PBEKeySpec(password);
keyFac = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_256");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

Cipher pbeCipher = Cipher.getInstance("PBEWithHmacSHA256AndAES_256");
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);

byte[] cleartext = "we Are in Encryption Mode".getBytes();

byte[] ciphertext = pbeCipher.doFinal(cleartext);

System.out.println(new String(ciphertext));

//¾y££<—Îðƒr[b®#7Úò¤Á5¢3úÜ>ö

File encryptFile = new File("kulla.txt");

while(!encryptFile .exists()) {
    
    encryptFile .createNewFile();
}
PrintWriter m = new PrintWriter(encryptFile );

m.println(new String(ciphertext));

m.close();

System.out.println("Encrypted File Generated");

BufferedReader n = new BufferedReader(new FileReader("C:\\kulla.txt"));
String h = n.readLine();
byte[] l = h.getBytes();

byte[] ciphertext1 = pbeCipher.doFinal(l); 

//it throws Exception  Missing parameter type: IV expected

pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec );

byte[] pbeDecipher = pbeCipher.doFinal(ciphertext1);

System.out.println(new String(pbeDecipher));

请问怎么做?

【问题讨论】:

  • 连同答案请注意(非常重要)答案是将加密中的数据作为字节数组处理(不要直接转换为字符串),如果你想要将二进制数据(密文)表示为字符串,使用某种编码(base64 是最常见的)-

标签: java file encryption


【解决方案1】:

您的代码使用随机盐来获取密码,但盐永远不会存储,因此当以后解密(在第二次运行中)时,您不再有盐。

第二 - 用于 AES 加密的初始化向量存在类似问题。您没有在加密方面定义一个,所以 Java 是(内部) 生成一个并进行加密。现在您必须从密码中获取此 iv 并将其保存以供以后解密。由于您不提供您运行的 iv 进入异常“缺少参数类型:IV 预期”。

由于我懒得检查您在代码下方找到的代码(由 @Topaco 提供,所有功劳归他所有!链接:https://stackoverflow.com/a/63719246/8166854) 完整的文件加密/解密,甚至适用于较大的文件,因为它使用缓冲的 CipherInput-/OutputStreams。

安全警告:代码没有异常处理,仅用于教育目的!

代码:

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.SecureRandom;

public class MainFileEncryption {
    public static void main(String[] args) throws Exception {
        System.out.println("File encryption with PBEWithHmacSHA256AndAES_256");

        String uncryptedFilename = "plaintext.txt";
        String encryptedFilename = "plaintext.enc";
        String decryptedFilename = "decrypted.txt";
        String password = "mySecretPassword";
        byte[] iv = new byte[16];
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextBytes(iv);
        encrypt(password, iv, uncryptedFilename, encryptedFilename);
        decrypt(password, encryptedFilename, decryptedFilename);
    }

    // by Topaco https://stackoverflow.com/a/63719246/8166854
    private static void encrypt(String key, byte[] initVector, String inputFile, String outputFile) throws Exception {
        // Key
        PBEKeySpec pbeKeySpec = new PBEKeySpec(key.toCharArray());
        SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_256");
        SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
        // IV
        IvParameterSpec iv = new IvParameterSpec(initVector);
        // Salt
        SecureRandom rand = new SecureRandom();
        byte[] salt = new byte[16];
        rand.nextBytes(salt);
        // ParameterSpec
        int count = 10000;
        PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count, iv);
        // Cipher
        Cipher cipher = Cipher.getInstance("PBEWithHmacSHA256AndAES_256");
        cipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
        try (FileInputStream fin = new FileInputStream(inputFile);
             FileOutputStream fout = new FileOutputStream(outputFile);
             CipherOutputStream cipherOut = new CipherOutputStream(fout, cipher)) {
            // Write IV, Salt
            fout.write(initVector);
            fout.write(salt);
            // Encrypt
            final byte[] bytes = new byte[1024];
            for (int length = fin.read(bytes); length != -1; length = fin.read(bytes)) {
                cipherOut.write(bytes, 0, length);
            }
        }
    }

    private static void decrypt(String key, String inputFile, String outputFile) throws Exception {
        try (FileInputStream encryptedData = new FileInputStream(inputFile);
             FileOutputStream decryptedOut = new FileOutputStream(outputFile)) {
            // Key
            PBEKeySpec pbeKeySpec = new PBEKeySpec(key.toCharArray());
            SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_256");
            SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
            // Read IV
            byte[] initVect = new byte[16];
            encryptedData.read(initVect);
            IvParameterSpec iv = new IvParameterSpec(initVect);
            // Read salt
            byte[] salt = new byte[16];
            encryptedData.read(salt);
            // ParameterSpec
            int count = 10000;
            PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count, iv);
            // Cipher
            Cipher cipher = Cipher.getInstance("PBEWithHmacSHA256AndAES_256");
            cipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);
            try (CipherInputStream decryptStream = new CipherInputStream(encryptedData, cipher)) {
                // Decrypt
                final byte[] bytes = new byte[1024];
                for (int length = decryptStream.read(bytes); length != -1; length = decryptStream.read(bytes)) {
                    decryptedOut.write(bytes, 0, length);
                }
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-02
    • 1970-01-01
    • 2016-03-11
    • 2017-02-11
    • 2020-07-17
    相关资源
    最近更新 更多