将零填充添加到数组

时间:2013-11-27 16:32:42

标签: c cryptography aes-gcm

我正在为AES-GCM实施做一个GHASH。

GHASH

我需要实现这个

eqn

其中v是A的最后一个块的位长,u是C的最后一个块的位长,并且||表示位串的串联。

如何进行A块的串联以填充从0到128位的零填充,因为我不知道整个块的长度。 所以我只需要A块并将其与一个128位的数组进行异或运算

void GHASH(uint8_t H[16], uint8_t len_A, uint8_t A_i[len_A], uint8_t len_C,
    uint8_t C_i[len_C], uint8_t X_i[16]) {

uint8_t m;
uint8_t n;
uint8_t i;
uint8_t j;
uint8_t zeros[16] = {0};

 if (i == m + n) {
        for(j=16; j>=0; j--){
        C_i[j] = C_i[j] ^ zeros[j]; //XOR with zero array to fill in 0 of length 128-u
        tmp[j] = X_i[j] ^ C_i[j]; // X[m+n+1] XOR C[i] left shift by (128bit-u) and store into tmp
        gmul(tmp, H, X_i); //Do Multiplication of tmp to H and store into X
        }
    }

我很确定我不对。但我不知道该怎么做。

2 个答案:

答案 0 :(得分:4)

如果你不关心每一点效率(我假设这是为了实验,而不是实际使用?)只需重新分配和填充(实际上,你可以在第一次声明这些时将其向上舍入并调用calloc) :

size_t round16(size_t n) {
    // if n isn't a multiple of 16, round up to next multiple
    if (n % 16) return 16 * (1 + n / 16);
    return n;
}

size_t realloc16(uint8_t **data, size_t len) {
    // if len isn't a multiple of 16, extend with 0s to next multiple
    size_t n = round16(len);
    *data = realloc(*data, n);
    for (size_t i = len; i < n; ++i) (*data)[i] = 0;
    return n;
}

void xor16(uint8_t *result, uint8_t *a, uint8_t *b) {
    // 16 byte xor
    for (size_t i = 0; i < 16; ++i) result[i] = a[i] ^ b[i];
}

void xorandmult(uint8_t *x, uint8_t *data, size_t n, unint8_t *h) {
    // run along the length of the (extended) data, xoring and mutliplying
    uint8_t tmp[16];
    for (size_t i = 0; i < n / 16; ++i) {
        xor16(tmp, x, data+i*16);
        multgcm(x, h, tmp);
    }
}

void ghash(uint8_t *x, uint8_t **a, size_t len_a, uint8_t **c, size_t len_c, uint8_t *h) {
    size_t m = realloc16(a, len_a);
    xorandmult(x, *a, m, h);
    size_t n = realloc16(c, len_c);
    xorandmult(x, *c, n, h);

    // then handle lengths
}

uint8_t x[16] = {0};
ghash(x, &a, len_a, &c, len_c, h);
免责声明 - 没有专家,只是浏览了规范。代码未编译,未经检查,并非用于“真实”使用。此外,规范支持任意(位)长度,但我假设您正在以字节为单位。

另外,我仍然不确定我是否回答了正确的问题。

答案 1 :(得分:4)

在我看来,你在这里遇到了几个问题,并且将它们混为一谈是问题的重要组成部分。分开它们会更容易。

  • 首先:传入uint8_t len_A, uint8_t A_i[len_A]形式的参数是不正确的语法,不会给你你想要的。你实际上得到uint8_t len_A, uint8_t * A_i,A_i的长度取决于你在上面的级别上的声明方式,而不是你尝试传递它的方式。(注意uint8_t * A和{{1}在这里功能相同;差异主要是程序员的语法糖。)

  • 在上面的层面上,因为我不知道它是由malloc()还是在堆栈上声明的,所以我不会对内存管理问题感到满意。我将根据我的建议使用本地存储。

  • 单位清晰度:这里有一个不好的案例:位与字节对块长度。在不知道核心算法的情况下,在我看来,未申报的m&amp; n是A&amp;的块长度。 C;即,A是m个块长,并且C是n个块长,并且在两种情况下,最后一个块不需要是全长的。你正在传递len_A&amp; len_C没有告诉我们(或在代码中使用它们,所以我们可以看到)它们是位长度u / v,A_i / C_i的字节长度,还是A / C的总长度,以位或字节或块为单位。基于(不正确的)声明,我假设它们是A_i / C_i的长度,以字节为单位,但它并不明显......也不是明显的通过。通过这个名字,我猜它是比特的A / C长度。提示:如果你的单位在名称中,当你尝试将bitLenA添加到byteLenB时就很明显了。

  • 迭代控制:你似乎在第i次迭代时传入16字节的块,但是没有传入i。要么通过我,要么通过完整的A&amp; C代替A_i&amp; C_I。你也在使用m&amp; n没有设置或传递它们;同样的问题适用。我会假装他们在使用的那一刻都是正确的,让你解决这个问题。

  • 最后,我不理解i = m + n + 1情况的求和符号,特别是len(A)和&amp; len(C)被处理,但你不是在问这个案子所以我会忽略它。

考虑到这一切,让我们来看看你的功能:

uint8_t A[]

我们只复制A或C的最后一个块中的内存,并使用本地内存进行复制。大多数块都使用单个指针复制进行处理,以指向输入存储器的正确位。