cryptography - libgcrypt 如何为 CTR 模式增加计数器?
问题描述
我有一个使用 libgcrypt 的 CTR 模式实现使用 AES-256 加密的文件。我希望能够部分解密文件(例如,在不解密整个文件的情况下解密 20 个块中的第 5-10 个块)。
我知道通过使用 CTR 模式,我应该可以做到。我只需要知道正确的计数器。问题在于我所拥有的只是块 0 的初始计数器。例如,如果我想解密块 5,我需要另一个计数器,它是通过对从 0 开始的每个块的初始计数器执行一些操作来实现的到 5。
我似乎找不到 libgcrypt 公开的 API,以便在给定初始计数器的情况下计算后续块的计数器。
给定块#0的计数器,我如何计算后面块(例如块#5)的计数器?
解决方案
如有疑问,请前往源头。这是 gcrypt 的通用 CTR 模式实现 ( _gcry_cipher_ctr_encrypt()
in cipher-ctr.c
) 中的代码,它增加了计数器:
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
数组(对于 AES,等于 16 个字节)。上面的代码将其最后一个字节加一,并检查结果是否环绕为零。如果没有,它会停止;如果它确实回绕,则代码然后移动到倒数第二个字节,增加它,检查它是否被包裹,并继续循环,直到它找到一个在增加时不回绕的字节,或者它已经增加所有字节。blocksize
blocksize
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}
,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3}
,等等)。
当然,这实际上只是在算术上递增一个 ( ×8) 位整数,以大端字节序blocksize
存储在内存中。
推荐阅读
- javascript - Uncaught SyntaxError: Unexpected token { in JSON at position 96
- php - PHP 关联数组的意外行为——为什么?
- python - 通过消除三个 for 循环来提高时间效率
- php - 编辑WordPress“wp_posts”数据库表上“comment_count”列数据的功能
- javascript - 避免在 Javascript 中使用科学记数法
- angular - 动态改变 Ionic App 的原色
- npm - 语义版本控制:在我的模块的所有版本中发现错误在哪里修复和更新版本?
- c# - MVC 转义剃刀输出
- python-3.x - 玩刽子手的布尔型迷你 Python 程序
- html - 网页取消配置 https 访问