如何在 C 中表示长位序列?

How to represent long sequence of bits in C?

我正在尝试将一串十六进制转换为一长串位。这是 Cryptopals 挑战中挑战 1 的一部分(将十六进制转换为 base64)。

我的想法是将字符串中的每两个字符转换为其数值的一个字符(同时将第一个字符乘以 16),因为 |hex| = 4, |char|=8.

然后,每次屏蔽前6位,转成base64

问题是在前 6 位之后我需要将所有数组左移 6 次 - 显然 - 我不知道该怎么做。

那么,首先,他们是否有更好的方法将十六进制字符串表示为位序列?

而且 - 我怎样才能将所有数组左移?我在这里看到了处理移动每个元素并复制它们的解决方案 - 这是最简单的方法吗?

这是我到目前为止所做的 - 我添加了一些额外的步骤来澄清:

int main(int argc, char * argv[]) {
    int elm = strlen(argv[1]) / 2;
    char *hashBits = malloc(sizeof(char) * elm);
    char a,b,c;
    for (int i = 0; i < elm; ++i) {
        a = charToBinary(argv[1][i*2]);   // Convert the char to its numeric value
        b = charToBinary(argv[1][i*2+1]);
        c = transformToChar(a,b);         // multiply the first with 16 and adds the second one
        hashBits[i] = c;
    }

    char base64Bits = 63 << 2;

    int elm64 = elm * 2 * 4 / 6;
    char *hashIn64Base = malloc(sizeof(char) * elm64);

    for (int j = 0; j < elm64; ++j) {
        hashIn64Base[j] = toBaseSixtyFour((hashBits[0] & base64Bits) >> 2); 
        hashBits = hashBits << 6;        //***This is obviously wrong but - how to do it?***//
    }

    for (int k = 0; k < elm64; ++k) {
        printf("%s", &hashIn64Base[k]);
    }
}

如你所知,Base-64编码表示4个字符(每个代表6位)中的3个字节(24位)。

所以你想取这24位:

12345678 12345678 12345678

并将它们变成这四个块:

123456 781234 567812 345678

您可以使用 x & 0xfcx & 0x03 等表达式 "mask off" 某些位。您可以使用 <<>> 左右移动位。您可以使用 |.

将两个不重叠的位序列放在一起

获得 6 位块后,将它们映射到 Base-64 字母表字符的常用方法是将它们用作数组的索引:

char base64_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

您还需要做一些额外的工作来处理输入长度不是 3 字节的精确倍数的情况。

我不想破坏挑战的乐趣,剩下的就交给你了。

您阅读十六进制字符串的方式看起来应该可行。您没有显示 charToBinarytransformToChar,但是根据函数调用旁边的注释,您应该以字符串将代表的字节数组结束,因此该方法(假设它已正确实现) 没问题。

至于创建 base64 字符串,为每个 base64 字符将整个数组移动 6 位是错误的方法。

利用8 * 3 == 6 * 4的优势,一次取3个字节,转换成4个base64字符。您可以通过循环获取当前元素以及接下来的两个元素来进行转换,并在每次迭代中将索引递增 3 来完成此操作。

您需要检查字节数是否是 3 的倍数。如果不是,则最后一次循环迭代将需要处理只有 1 或 2 个字节的情况。

发生这种情况时,任何与任何源字节无关的额外 base64 字符都将设置为 =,并且字符中任何编码内容的额外位都将用 0 填充。

例如,给定以下两个字节:

00000000 11111111

你把它分成6个位组如下:

000000 001111 111100

请注意,最后一组的末尾有额外的 0。所以你最终会得到 3 个 base64 字符加上一个 =.

给定一个字节:

11111111

分组为:

111111 110000

所以你将有 2 个 base64 字符加上 2 个 =.

解码时,末尾有1个=表示多出2个,有2个=表示多出1个