使用AES加密/解密,并将信息存储在文本文件中



我一直在做我自己的小项目,在那里我试图制作一个简单的密码管理器。我目前遇到的问题是,让它以某种方式工作,这样当运行时,它会将加密的密码保存到一个文件中,然后当下次运行时,你可以调用它,它会被解密,并向你显示你调用的用户名的密码。

对于稍后我想添加到程序中的内容,我确实需要将加密/解密方法分开。

当前错误为:

线程"main"javax.crypto.IllegalBlockSizeException异常:使用填充密码解密时,输入长度必须是16的倍数

非常感谢您的帮助。

代码如下:

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.util.Scanner;
import javax.crypto.spec.SecretKeySpec;
public class PasswordManager3
{
    static String key = "SimplePasswordMg";
    static String password1 = "";
    static String password2 = "";
    static String username = "";

    public static void main(String[] args) 
             throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, 
             BadPaddingException, IOException 
    {
        Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        System.out.println("Enter New to input a new password, or Retrieve to retrieve an old password:");
        Scanner scanner1 = new Scanner(System.in);
        String answer = scanner1.nextLine();
        if(answer.equalsIgnoreCase("New")) {
            System.out.println("Please enter a username: ");
            Scanner scanner2 = new Scanner(System.in);
            username = scanner2.nextLine();
            System.out.println("Please enter a password: ");
            Scanner scanner3 = new Scanner(System.in);
            password1 = scanner3.nextLine();
            System.out.println("Please enter your password again: ");
            Scanner scanner4 = new Scanner(System.in);
            password2 = scanner4.nextLine();
            if (password1.equalsIgnoreCase(password2)) {
                Files.write(Paths.get(username + ".txt"), encrypt(password1, cipher, aesKey));
                System.out.println("Your password has been stored.");
            }
            else {
                System.out.println("The passwords you entered did not match. Exiting password manager.");
            }
        }
        else if(answer.equalsIgnoreCase("Retrieve")) {
            System.out.println("Please enter the username you would like to retrieve the password for: ");
            Scanner scanner5 = new Scanner(System.in);
            username = scanner5.nextLine();
            BufferedReader in = new BufferedReader(new FileReader(username + ".txt"));
            String encryptedpass = in.readLine();
            byte[] encryptedpass2 = encryptedpass.getBytes("UTF-8");
            System.out.println(decrypt(encryptedpass2, cipher, aesKey));
        }
        else {
            System.out.println("You entered an incorrect option, program exited.");
        }
    }
     public static byte[] encrypt(String str, Cipher cipher, Key aesKey) 
             throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException 
     {
          cipher.init(Cipher.ENCRYPT_MODE, aesKey);
          byte[] encrypted = cipher.doFinal(key.getBytes("UTF-8"));
          return encrypted;
     }
    public static String decrypt(byte[] byte1, Cipher cipher, Key aesKey) 
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException 
    {
        cipher.init(Cipher.DECRYPT_MODE, aesKey);
        String decrypted = new String(cipher.doFinal(byte1));
        return decrypted;
    }
}

您不是在编写文本文件加密数据实际上是随机位,mainencrypt的返回直接传递给Files.write(Path,byte[]),后者将其写入二进制。

当你用FileReader读回它时,它会使用你的平台的默认编码,而你没有识别它,有时还会使用你的用户环境,它可能会也可能不会损坏一些字节;使用readLine()可能会丢弃部分数据,而当它从来都不是有效字符时,使用getBytes("UTF-8")对其进行编码,大约99.6%的可能性会破坏剩下的数据。因此,您传递给decrypt的值完全错误,无法解密。

简单的对称修复方法是使用File.readAllBytes(Path)以二进制形式读取(整个)文件,并解密返回的byte[]值。

或者,如果出于某种原因(我看不到)你真的想要文本文件,你需要首先将加密的值编码成文本形式并写入,可能添加了一个行终止符,然后读回(如果你选择的话,作为一行)并在解密前对其进行解码。Base64和十六进制(缩写为hex)是对二进制数据进行文本编码的两种最常见的方法。

此外:使用一个完全可打印的ASCII密钥,甚至包含英语单词的一部分,这大大削弱了您的加密能力,从标称的128位到20-30位,任何能力不强的攻击者都可以轻易破解。使用任何硬编码的钥匙也是一种危险,尽管这是一个更难的问题,而且没有单一、简单、好的解决方案。

默认情况下,您在ECB模式下使用AES。使用ECB密码(以及几乎所有其他密码)是个坏主意;了解谷歌"ECB企鹅"one_answers"Adobe密码漏洞"的原因和/或查看
https://crypto.stackexchange.com/questions/11451/can-ecb-mode-really-leak-some-characters
https://crypto.stackexchange.com/questions/11456/what-does-it-mean-if-second-half-of-8-char-string-encrypted-in-3des-is-always-id

最新更新