当前位置: 首页 > 知识库问答 >
问题:

使用基于密码的加密的AES-128 CBC示例回顾

茹正祥
2023-03-14

我需要一些帮助来验证下面的代码片段的Java AES加密与CBC、PKCS5Padding和IV。

我测试了代码,能够加密和解密。我有几个问题如下所述。

  1. 密码应该存储在哪里?
  2. 向密码文本附加/检索salt和IV字节的方式是否正确?
  3. 高度赞赏任何其他评论,谢谢!
public class Encryption {

    private static int iterations = 65536;
    private static int keySize = 128;
    private static char[] password = "password".toCharArray();
    private static String algorithm= "PBKDF2WithHmacSHA1";


    private static final String SEPARATOR = "~";


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

         String filePath = "test.xml";

         String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));

         String encrMesg = encrypt(fileContent);

         System.out.println("Encrypted: " + encrypt(encrMesg)); 

         System.out.println("Decrypted: " + decrypt(encrMesg)); 
     }


    public static String encrypt(String plaintext) throws Exception {


        byte[] saltBytes = getSalt().getBytes();

        SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
        PBEKeySpec spec = new PBEKeySpec(password, saltBytes, iterations, keySize);
        SecretKey secretKey = skf.generateSecret(spec);
        SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretSpec);
        AlgorithmParameters params = cipher.getParameters();

        byte[] ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
        byte[] cipherText = cipher.doFinal(String.valueOf(plaintext).getBytes("UTF-8"));

        return DatatypeConverter.printBase64Binary(ivBytes)+SEPARATOR+DatatypeConverter.printBase64Binary(saltBytes)
        +SEPARATOR+DatatypeConverter.printBase64Binary(cipherText);
    }

    public static String decrypt(String encryptedText) throws Exception {

        System.out.println(encryptedText);

        String[] encryptedArr = encryptedText.split(SEPARATOR);

        byte[] ivBytes = DatatypeConverter.parseBase64Binary(new String(encryptedArr[0]));

        byte[] salt = DatatypeConverter.parseBase64Binary(new String(encryptedArr[1]));

        byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(new String(encryptedArr[2]));

        SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
        PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, keySize);
        SecretKey secretKey = skf.generateSecret(spec);
        SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretSpec, new IvParameterSpec(ivBytes));

        byte[] decryptedTextBytes = null;

        try {
            decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }

        return new String(decryptedTextBytes);

    }

    public static String getSalt() throws Exception {

        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        byte[] salt = new byte[20];
        sr.nextBytes(salt);
        return new String(salt);
    }

}

共有1个答案

赵开诚
2023-03-14

查询

密码应该存储在哪里作为一个好的约定?

对称钥匙最好是放进保险库。否则,它们应该放在密钥存储库上,但这样就会出现保护密钥存储库密码的问题。

SecureRandom random = SecureRandom.getInstanceStrong();

否则,您将使用较弱的熵池(即linux中的/dev/urandom)来生成安全号码,这将导致较弱的密钥,从而更容易被破解。

任何其他评论都非常感谢,谢谢!

在处理字符串转换时,您应该始终如一地使用相同的编码,例如.getBytes(“UTF-8”),以避免出现问题。例如,在转换盐时,你不用它。

 类似资料:
  • 问题内容: 我需要实现256位AES加密,但是我在网上找到的所有示例都使用“ KeyGenerator”来生成256位密钥,但是我想使用自己的密码。如何创建自己的密钥?我尝试将其填充到256位,但是随后出现错误消息,提示密钥太长。我确实安装了无限管辖权补丁,所以那不是问题:) 就是 KeyGenerator看起来像这样… 从这里获取的代码 编辑 我实际上是将密码填充到256个字节而不是位,这太长了

  • 问题内容: 我找到了用Java实施AES加密/解密的指南,并试图理解每一行并将其放入自己的解决方案中。但是,我没有完全理解它,因此出现了问题。最终目标是拥有基于密码的加密/解密。我已经阅读了有关此的其他文章/ stackoverflow帖子,但是大多数文章没有提供足够的解释(我对Java加密非常陌生) 我现在的主要问题是,即使设置了 I,最后还是会得到不同的Base64结果(每次都是随机的,但是我

  • null 我正在尝试使用Jasypt的StandardPBEStringEncryptor类 当我这样做时,我会得到以下异常: java.security.NosuchAlgorithmException:AES/CBC/PKCS5Padding SecretKeyFactory不可用 谢谢

  • 问题内容: 如何基于Java 256位AES密码的加密? 问题答案: 与带外接收者共享和salt 所选择的 - 8个字节,这是个好习惯,不需要保密)。然后从此信息中得出一个好的密钥: 幻数(可以在某处定义为常数)65536和256分别是密钥派生迭代计数和密钥大小。 迭代密钥派生功能需要大量的计算工作,并且可以防止攻击者快速尝试许多不同的密码。可以根据可用的计算资源来更改迭代次数。 密钥大小可以减少

  • 这是我的密码 抱歉,如果我的代码一团糟。

  • 本文向大家介绍java基于AES对称加密算法实现的加密与解密功能示例,包括了java基于AES对称加密算法实现的加密与解密功能示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了java基于AES对称加密算法实现的加密与解密功能。分享给大家供大家参考,具体如下: 注:SecureRandom是生成安全随机数序列,password.getBytes()是种子,只要种子相同,序列就一样,所以解