【问题标题】:How does libgcrypt increment the counter for CTR mode?libgcrypt 如何为 CTR 模式增加计数器?
【发布时间】:2018-12-27 14:34:18
【问题描述】:

我有一个使用 libgcrypt 的 CTR 模式实现使用 AES-256 加密的文件。 我希望能够部分解密文件(例如,在不解密整个文件的情况下解密 20 个块中的第 5-10 个块)。

我知道通过使用 CTR 模式,我应该可以做到。我只需要知道正确的计数器。 问题在于我所拥有的只是块 0 的初始计数器。例如,如果我想解密块 5,我需要另一个计数器,它是通过对从 0 开始的每个块的初始计数器执行一些操作来实现的到 5。

我似乎找不到 libgcrypt 公开的 API,以便在给定初始计数器的情况下计算后续块的计数器。

在给定块 #0 的计数器的情况下,我如何计算后续块(例如块 #5)的计数器?

【问题讨论】:

    标签: cryptography block-cipher libgcrypt ctr-mode


    【解决方案1】:

    如有疑问,请转至the source。下面是 gcrypt 的通用 CTR 模式实现(cipher-ctr.c 中的_gcry_cipher_ctr_encrypt())中的代码,它增加了计数器:

    for (i = blocksize; i > 0; i--)
      {
        c->u_ctr.ctr[i-1]++;
        if (c->u_ctr.ctr[i-1] != 0)
          break;
      }
    

    在 libgcrypt 源代码的其他地方还可以找到其他更优化的计数器递增实现,例如在各种特定于密码的快速批量 CTR 加密实现中,但这个通用的加密实现很好且可读。 (当然,所有这些替代实现无论如何都需要生成相同的计数器值序列,以便 gcrypt 保持与自身兼容。)

    好的,那么它实际上是做什么的?

    好吧,看看上下文(或者,更具体地说,cipher-internal.h),很明显c->u_ctr.ctr 是一个blocksize 无符号字节数组(其中blocksize 等于 AES 的 16 个字节)。上面的代码将其最后一个字节加一,并检查结果是否环绕为零。如果没有,它会停止;如果它确实回绕,则代码然后移动到倒数第二个字节,增加它,检查它是否被包裹,并继续循环,直到它找到一个在增加时不回绕的字节,或者它已经增加所有blocksize 字节。

    因此,例如,如果您的原始计数器值为{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},那么在递增之后它将变为{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}。如果再次递增,它将变为{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},然后是{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3},依此类推直到{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255},之后下一个计数器值将是{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}(之后是{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1}{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2}、@987654340 @ 等)。

    当然,这实际上只是对单个 (blocksize × 8) 位整数进行算术递增,以big-endian 字节顺序存储在内存中。

    【讨论】:

    • 您好,伊尔马里·卡罗宁。非常感谢您非常详细的回答。它对我帮助很大,而且我已经完全实现了我想要做的事情!顺便说一句,我还不能投票,但我确实按下了投票按钮:)
    • @E1adi 如您所见,我已要求迁移到 SO(我是 SO 的新 mod,仍在学习中)。由于您现在在这里拥有 > 15 分,您应该可以投票。但除了投票之外,如果某个答案解决了您的问题,那么您应该通过点击消息左侧的 V 按钮来接受它。
    • @Maarten,感谢您提供的信息。我已经检查了 Ilmari 的答案作为解决我问题的答案。谢谢各位
    猜你喜欢
    • 1970-01-01
    • 2012-07-24
    • 1970-01-01
    • 1970-01-01
    • 2021-05-16
    • 2015-06-08
    • 2018-04-15
    • 1970-01-01
    • 2017-09-17
    相关资源
    最近更新 更多