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

带bouncy Castle的scala中的AES-256加密工作流:salt和IV的使用和传输/存储

闾丘成礼
2023-03-14

我正在尝试实现文件的安全加密,以发送在不安全的渠道或存储在不安全的地方。我使用bouncy castle框架,我的代码是用Scala写的。我决定使用aes-256(更具体地说--256位块大小的Rinjael,这是为什么)。看起来我可以使用任何(128160192256)块长度的Rinjael。

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

>

  • 为了创建一个分组密码实例,我必须获得一个带有一些输出反馈的填充分组密码实例:

    // 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.首先生成一个密钥,为此,这里建议的最佳解决方案是使用scrypt从密码中导出一个秘密,而不是使用pbkdf2-hmac-xxx。在俄文维基百科关于Scrypt的一篇文章中说,Scrypt的推荐参数如下:n=16384,r=8,p=1所以我们使用这个代码来生成密码:

    SCrypt.generate(password.getBytes(encoding), salt, 16384, 8, 1, bitLength / 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().getParametersSpec(IVParameterSpec.class).getIV();还是像我那样随机提取?
    3. 我既需要盐又需要静脉注射,或者我可以只使用其中一种,这是正确的吗?例如,使用random IV作为盐。
    4. 和主要问题:我必须把salt和IV传送到另一边,否则就不可能解密消息。我需要以某种方式通过未加密的通道。仅在加密消息(作为报头)之前添加两者是否安全?
  • 共有1个答案

    郝君博
    2023-03-14
    1. 我将按照建议使用16字节的盐长度
    2. iv应该是密码的块大小,并且应该是随机的
    3. 是的,您需要salt和IV,因为salt用于从密码生成密钥,IV用于初始化分组密码
    4. 盐和IV的设计是公开的。您可以不加密地发送或存储它们,但您不使用任何身份验证机制,因此任何人都可以在传输过程中更改IV或Salt,而您将无法检测到它,解密将得到不同的结果。以防止使用某种AEAD模式,并在身份验证中包括IV和salt。
     类似资料:
    • 我从Python得到一个加密的base64字符串。 格式是AES 256 CBC,但当我尝试使用Android解密时,它将解密字符串返回为nil。 这里我使用https://github.com/fukata/aes-256-cbc-example

    • 所以,我用AES算法加密文档列表。我使用PBKDF2从用户密码中确定密钥。我有几个关于存储数据和IV/salt问题: 如何存储文档: null null null

    • bouncyCastle新手,欢迎提供帮助。我正在尝试使用bounncycastle java API在我的系统上解密一个由第三方加密的文件。它似乎可以很好地解密文件,除了解密文件开头的一团垃圾数据。代码如下 解密的数据块看起来很好,除了开头的“?”??? 用于解密文件的openssl命令在下面的命令中运行良好。事实上,我在解密时使用的是openssl打印的密钥和iv。 加密文件中的openssl

    • 问题内容: 我正在尝试使用PyCrypto构建两个接受两个参数的函数:消息和密钥,然后对消息进行加密/解密。 我在网络上找到了几个链接可以帮助我,但是每个链接都有缺陷: 在codekoala上的此代码使用了os.urandom,PyCrypto不建议这样做。 此外,我不能保证给函数的键具有预期的确切长度。我该怎么做才能做到这一点? 另外,有几种模式,推荐哪种?我不知道该怎么用:/ 最后,IV到底是

    • 我试图使用PyCrypto构建两个函数,它们接受两个参数:消息和密钥,然后加密/解密消息。 我在网上找到了几个帮助我的链接,但每一个都有缺陷: 编辑:删除了代码部分,因为它不安全。

    • 问题内容: 我试图弄清楚如何使用crypto模块对nodejs中的密码进行加盐和哈希处理。我可以这样做来创建哈希密码: 但是我对以后如何验证密码感到困惑。 问题答案: 在您使用的任何持久性机制(数据库)中,您都将在哈希值和迭代次数之间存储结果哈希,这两者都是纯文本。如果每个密码使用不同的盐(您应该这样做),则还必须保存该信息。 然后,您将比较新的纯文本密码,使用相同的盐(和迭代次数)对其进行哈希处