带有充气城堡的scala中的AES-256加密工作流程:盐和IV的使用和转移/存储

时间:2013-10-10 16:26:29

标签: security encryption aes bouncycastle password-encryption

我正在尝试对通过不安全通道发送或存储在不安全位置的文件实施安全加密。我使用bouncy castle框架,我的代码是用编写的。我决定使用 - 256(更具体地说 - 具有256位块大小的Rinjael,here is why)。似乎我可以使用任何(128 | 160 | 192 | 256)块长度的Rinjael。

我无法正确理解整个过程概述。 Here是一个很好的答案,in this question有一些特定于充气城堡的有用代码。但是两个都没有给我留下一些问题(下面的问题)。

这就是我理解工作流程的方式:

  1. 为了创建一个块密码实例,我必须得到一个填充块密码的实例,并带有一些输出反馈:

    // create an instance of the engine
    val engine = new RijndaelEngine(bitLength)
    // wrap engine with some feedback-blocking cipher mode engine
    val ofb = new OFBBlockCipher(engine , bitLength)
    // wrap this with some padded-blocking cipher mode
    val cipher = new PaddedBufferedBlockCipher(ofb, new PKCS7Padding())
    
  2. 现在我必须在密码引擎上运行init()

    2.1。首先生成一个密钥,为此,建议here建议的最佳解决方案是使用Scrypt从密码中导出秘密,而不是使用PBKDF2-HMAC-xxx。在russian wikipedia article on Scrypt中,据说Scrypt的推荐参数如下:N = 16384, r = 8, p = 1 所以我用这个代码来生成密码:

    SCrypt.generate(password.getBytes(encoding), salt, 16384, 8, 1, bitLength / 8)
    

    2.2。这导致我需要盐。盐should be an array of random bytes。大多数answers此处use 8个字节。所以我做了

    // helper method to get a bunch of random bytes
    def getRandomBytes(size: Int) = {
      val bytes = Array.ofDim[Byte](size)
      val rnd = new SecureRandom()
      rnd.nextBytes(bytes)
      bytes
    }
    // generate salt
    val salt = getRandomBytes(8)
    

    2.3。为了使密码初始化,我们需要一个初始化向量(请看下面我的问题(2))。

    val iv = getRandomBytes(bitLength / 8)
    

    2.4。现在我们准备初始化密码了。

    cipher.init(mode, params(password, salt, iv, bitLength))
    
  3. 问题:

    1. 盐的大小应该是多少?为什么大多数respondents此处use 8字节,而不是更多?
    2. IV的大小应该是多少?它应该与密码块大小相同是正确的吗?它是首选从密码like here获取:cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();还是像我一样随意?
    3. 我需要两者盐和IV是否正确或者我只能使用其中一种?例如,使用随机IV作为盐。
    4. 主要问题:我必须将salt和IV传递给另一方,否则将无法解密该消息。我需要以某种方式将传递给未加密的频道安全只是在加密邮件(作为标题)之前添加两者吗?
    5. 提前致谢!

2 个答案:

答案 0 :(得分:2)

  1. 我会将{16}字节的盐长度设为suggested
  2. IV应该是密码块大小的大小,应该是随机的
  3. 是的,您需要salt和IV,因为salt用于从密码生成密钥,而IV用于初始化分组密码
  4. Salt and IV旨在公开。您可以发送它们或以未加密的方式存储,但是您不使用任何身份验证机制,因此任何人都可以在传输过程中更改IV或Salt,而您将无法检测到它,解密将为您带来不同的信息。为了防止这种情况,您应该使用某种AEAD模式,并在身份验证中包含IV和salt。

答案 1 :(得分:0)

安全吗?当然,他们仍然需要猜测密码。它安全吗?不,因为您向攻击者提供了简化解密过程所需的信息。如果你可以通过一个未加密的通道获得盐/密码的唯一方法是通过一个未加密的通道,那么我想的东西总比没有好,但为什么你不能用PKI / SSL交换这些信息呢?