2

我正在尝试对要通过不安全通道发送或存储在不安全位置的文件进行安全加密。我使用充气城堡框架,我的代码是用编写的。我决定使用 -256(更具体地说 - 具有 256 位块大小的 Rinjael,这就是原因)。似乎我可以使用任何 (128|160|192|256) 块长度的 Rinjael。

我无法正确理解整个过程概述。是一个很好的答案,在这个问题中有一些特定于充气城堡的有用代码。但两者都给我留下了一些未回答的问题(下面的问题)。

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

  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。首先生成一个密钥,要做到这一点,这里建议的最佳解决方案是使用Scrypt从密码中派生一个秘密,而不是使用PBKDF2-HMAC-xxx. 在关于 Scrypt 的俄罗斯维基百科文章中,据说 Scrypt的推荐参数如下:N = 16384, r = 8, p = 1 所以我编写了这段代码来生成密码:

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

    2.2. 这导致我需要盐。Salt应该是一个随机字节数组。这里的大多数答案使用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))
    

问题:

  1. 盐的大小应该是多少?为什么这里的大多数受访者使用 8字节,而不是更多?
  2. IV的大小应该是多少?它应该与密码块大小相同是否正确?是喜欢从这里的密码中获取:cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();还是像我一样随机?
  3. 我需要盐和 IV 是否正确,或者我可以只使用其中一种?例如,使用随机 IV 作为盐。
  4. 主要问题:我必须将盐和 IV 传递给另一方,否则无法解密消息。我需要以某种方式通过未加密的通道。在加密消息(作为标头)之前添加两者是否安全?

提前致谢!

4

2 回答 2

2
  1. 我会按照建议选择 16 字节的盐长度
  2. IV 应该是密码块大小的大小,并且应该是随机的
  3. 是的,您需要 salt 和 IV,因为 salt 用于从密码生成密钥,IV 用于初始化分组密码
  4. Salt 和 IV 旨在公开。您可以发送或存储未加密的文件,但您不使用任何身份验证机制,因此任何人都可以在传输过程中更改 IV 或 Salt,您将无法检测到它,解密将为您带来不同的东西。为防止您应该使用一些AEAD模式并在身份验证中包含 IV 和 salt。
于 2013-10-11T13:12:12.887 回答
0

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

于 2013-10-10T16:35:59.407 回答