一种方法是使用指针initVec
。最初,它指向初始向量。然后每次迭代后,改变指针引用上一轮的密文。CBC本质上意味着每个块的密文用作下一个块的初始向量。第一个块没有前一个块,因此存在一个特殊块:初始向量。
事实上,看看一些代码,这正是我在 2001 年 AES 刚推出时所做的,我想自己做:
加密:
void
rijn_cbc_encrypt(rijn_keysched_t *sched, unsigned char *iv, unsigned char *out,
const unsigned char *in, size_t nblocks)
{
unsigned char *ivec = iv;
size_t blocksize = numrows_to_blocksize(sched->rijn_param.rijn_blockrows);
size_t i, nbytes = nblocks * blocksize;
for (i = 0; i < nbytes; i += blocksize) {
xor_mem(out + i, in + i, ivec, blocksize);
rijn_encrypt(sched, out + i, out + i);
ivec = out + i; /* <---- next block's ivec is this block's output! */
}
memcpy(iv, ivec, blocksize);
}
解密。在这里,我们在每次迭代的顶部创建一个ivec
点,以指向前一个输入(密文)块i > 0
。对于第一次迭代,i == 0
我们将其指向iv
。很简单!
请注意,解密在数据中向后行进!
void
rijn_cbc_decrypt(rijn_keysched_t *sched, unsigned char *iv, unsigned char *out,
const unsigned char *in, size_t nblocks)
{
rijn_block_t iv_save;
size_t blocksize = numrows_to_blocksize(sched->rijn_param.rijn_blockrows);
size_t i, nbytes = nblocks * blocksize;
if (nblocks > 0) {
memcpy(&iv_save, in + nbytes - blocksize, blocksize);
for (i = nbytes - blocksize; i < nbytes; i -= blocksize) {
const unsigned char *ivec = (i > 0) ? in + i - blocksize : iv;
rijn_decrypt(sched, out + i, in + i);
xor_mem(out + i, out + i, ivec, blocksize);
}
memcpy(iv, &iv_save, blocksize);
}
}