用AES腌制

我是一个加密新手,但需要在存储到数据库之前加密敏感的个人数据。 我打算在CBC上使用AES,但也想用盐。 然而,我无法找到一种方法来做到这一点(除了BouncyCastle,我的主机不准备出于某种原因)所以我决定通过在要加密的文本末尾添加一个随机字符串来添加一个:

SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; IvParameterSpec ivspec = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec); String plainText = "This is my plain text"; System.out.println("**plainText: " + plainText); String saltedPlainText = plainText + UUID.randomUUID().toString().substring(0, 8); byte[] encrypted = cipher.doFinal(saltedPlainText.getBytes()); String encryptedText = new String(new Hex().encode(encrypted)); System.out.println("**encryptedText: " + encryptedText); cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivspec); byte[] decrypted = cipher.doFinal(new Hex().decode(encryptedText.getBytes())); saltedPlainText = new String(decrypted); plainText = saltedPlainText.substring(0, saltedPlainText.length()-8); System.out.println("**plainText: " + plainText); 

我想我有3个问题:

  1. 有没有更好的方法在加密中加入盐?
  2. 在与此类似的示例中,似乎始终在开始时生成随机密钥,并且在加密之后立即进行解密。 这是一个不太可能的场景 – 所以我的工作基础是我每次都应该使用相同的密钥(看起来很简单,但我见过的所有例子似乎都是随机的)。 看不出它会怎么样,但有人可以确认:)
  3. 使用固定密钥,我注意到如果我继续加密相同的字符串,我会得到不同的结果,但只有加密结果的末尾部分会发生变化。 似乎不对。 怎么会?

非常感谢,尼尔

Salting通常是在对密码进行散列时完成的,而不是在加密明文时; 例如,使用PBEKeySpec从密码生成密钥时,您将使用salt。 AES的“盐”是它的初始化向量。

在加密相同的明文时,您获得了相同的密文,因为每次使用相同的初始化向量 – 您需要随机化IV(使用例如SecureRandom ),否则您需要从计数器生成IV。 IV不是秘密的(可以用明文传输),并且解密器需要使用与加密器相同的IV。

为什么要在文本中添加盐? 它什么都不做。

Salt通常用于哈希密码,以打败彩虹表。 工作原理如下:假设用户输入密码“qwerty”。 生成一个16字节长的随机字符串(rs),将其添加到密码中,并对生成的字符串进行散列,然后获取散列,将rs添加到其中 – 并将生成的字符串存储在数据库中。