1

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

我的想法是将字符串中的每两个字符转换为其数值的一个字符(同时将第一个乘以 16),因为 |hex| = 4,|字符|=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]);
    }
}
4

2 回答 2

1

您在十六进制字符串中读取的方式看起来应该可以工作。您没有显示charToBinaryand transformToChar,但是根据函数调用旁边的注释,您最终应该得到一个字符串将代表的字节数组,因此该方法(假设它已正确实现)很好。

至于创建 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 额外。

于 2018-04-06T17:44:17.110 回答
0

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

所以你想取这 24 位:

12345678 12345678 12345678

并将它们变成这四个块:

123456 781234 567812 345678

x & 0xfc您可以使用和之类的表达式“屏蔽”某些位 x & 0x03<<您可以使用和左右移动位>>。您可以使用 将两个不重叠的位序列放在一起|

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

char base64_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

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

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

于 2018-04-06T17:41:37.720 回答