我正在尝试对通过不安全通道发送或存储在不安全位置的文件实现安全加密。我用bouncy castle框架,我的代码写在 scala 。我决定使用aes -256(更具体地说 - Rinjael 具有 256 位 block 大小, here is why )。看起来我可以将 Rinjael 与任何 (128|160|192|256) block 长度一起使用。
我无法正确理解整个过程的概述。 Here是很好的答案之一,in this question有一些特定于充气城堡的有用代码。但两者都给我留下了一些未解答的问题(问题如下)。
这就是我对工作流程的理解:
为了创建分组密码实例,我必须获取带有一些输出反馈的填充分组密码实例:
// 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())
现在我必须在密码引擎上运行
init()
2.1。首先生成一个 key ,为此建议最好的解决方案here是使用
Scrypt
从密码中获取 secret ,而不是使用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))
问题:
- 盐的大小应该是多少?为什么大多数respondents在这里use
8
字节,而不是更多? - IV 的大小应该是多少?它的大小应该与密码 block 大小相同,这是否正确?是否首选从密码中获取 like here :
cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
还是像我一样随机? - 我需要两者盐和静脉注入(inject),或者我可以只使用其中之一,这是正确的吗?例如使用随机 IV 作为盐。
- 主要问题:我必须将盐和 IV 传递给另一方,否则将无法解密消息。我需要以某种方式将两者通过未加密的 channel 传递。在加密消息之前添加两者(作为 header )是否安全?
提前致谢!
最佳答案
关于security - 带有充气城堡的 scala 中的 AES-256 加密工作流程 : salt and IV usage and transfer/storage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19301244/