libgcrypt如何增加CTR模式的计数器?

时间:2018-12-27 14:34:19

标签: cryptography block-cipher libgcrypt ctr-mode

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

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

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

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

1 个答案:

答案 0 :(得分:4)

如有疑问,请转到the source。以下是gcrypt通用CTR模式实现中的代码(_gcry_cipher_ctr_encrypt()中的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.ctrblocksize个无符号字节的数组(其中blocksize等于16 AES字节)。上面的代码将其最后一个字节加1,然后检查结果是否回零。如果没有,它将停止;如果确实进行了换行,则代码将移至倒数第二个字节,对其进行递增,然后检查其是否进行了换行,并一直循环执行,直到找到增量时未回绕的字节或它已递增所有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}(然后是{{ 1}},{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}等。

当然,这实际上是在算术上递增以big-endian字节顺序存储在内存中的单个({0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3}×8)位整数。