我试图将一个十六进制字符串转换为一个长的位序列。这是Cryptopals挑战中挑战1的一部分(将hex转换为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]);
}
}
答案 0 :(得分:1)
您在十六进制字符串中读取的方式看起来应该可行。您没有显示charToBinary
和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个额外的。{/ p>
答案 1 :(得分:0)
如您所知,Base-64编码表示3个字节(24位),4个字符(每个代表6位)。
所以你想要这些24位:
12345678 12345678 12345678
并将它们变成这四个块:
123456 781234 567812 345678
你可以&#34;掩盖&#34;使用x & 0xfc
和x & 0x03
等表达式的某些位。您可以使用<<
和>>
左右移位位。您可以使用|
将两个非重叠位序列放在一起。
一旦你获得了6位块,将它们映射到Base-64字母表字符的常用方法是将它们用作数组的索引:
char base64_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
您还需要做一些额外的工作来处理输入长度不是3个字节的精确倍数的情况。
我不想破坏挑战的乐趣,所以我会把剩下的留给你。