Я хотел разоблачить шестнадцатеричную строку, используя следующий алгоритм в C j = i MOD 4 преобразованный октет-i = исходный октет-i XOR маскирующий-ключ-октет-j
#include<stdlib.h>
#include<string.h>
int main()
{
char masked[] = "951bfdcdc113ebca921fe9dc";
char masking_key[] = "e17e8eb9";
char *unmasked;
int length=strlen(masked);
unmasked=malloc(sizeof(char)*(length+1));
int i=0;
for(i=0;i<length;i++)
{
unmasked[i]=masked[i]^masking_key[i%4];
}
printf("%s\n",unmasked);
return 0;
}
Вывод, который я получаю, равен \UT вместо 74657374206d657373616765. Было бы очень полезно, если бы кто-нибудь помог мне исправить ошибку здесь.
Вы выполняете xoring ascii-коды шестнадцатеричного вместо xoring фактических чисел.
В стороне: вы выделили один дополнительный, но не написали терминатор строки.
То, что вы здесь делаете, - это не xoring шестнадцатеричных байтов, а xor символов, представляющих их.
В то время как идеальным процессом был бы (0x95 ^ 0xe1) + (0xbf ^ 7e) + ...
, то, что вы делаете, — это xor значения ascii каждого символа, что означает ('9' ^ 'b') + ('5' ^ '1') + ...
.
Что вам нужно сделать, так это сначала преобразовать шестнадцатеричную строку в сами байты (bytes.fromhex("951bfdcdc113ebca921fe9dc")
в питоне), и только потом их XOR. Я бы сделал это с помощью sscanf("%2x", ...)
.
Например:
#include <stdio.h>
int main()
{
unsigned char a = 0;
scanf("%2hhx", &a);
}
Вам нужно преобразовать из строкового формата в необработанные целые числа, прежде чем выполнять XOR, а затем преобразовать обратно, прежде чем печатать его в виде строки. В противном случае вы будете использовать XOR для значений символов, а не для необработанных значений.
Вы можете преобразовать всю строку за один раз с помощью strtol(data, 0, 16)
. Но одна из общих деталей, которая отличает программистов от кодовых обезьян, — это возможность кодировать тривиальные преобразования строки в целое число без помощи библиотечных функций. Итак, вот упрощенный код, делающий именно это — имейте в виду полное отсутствие обработки ошибок, так как это просто быстрый и грязный код:
#include <stdio.h>
#include <stdlib.h>
char hexlify (char nibble)
{
return "0123456789abcdef"[nibble];
}
char unhexlify (char ch)
{
if (ch>='0' && ch<='9')
return ch - '0';
if (ch>='a' && ch<='f')
return ch - 'a' + 0xA;
return 0;
}
int main (void)
{
char masked[] = "951bfdcdc113ebca921fe9dc";
char masking_key[] = "e17e8eb9";
char *unmasked;
size_t length = sizeof masked - 1;
unmasked = malloc(length + 1);
for(size_t i=0;i<length;i++)
{
char op1 = unhexlify(masked[i]);
char op2 = unhexlify(masking_key[i%4]);
unmasked[i]= hexlify(op1 ^ op2);
}
unmasked[length]='\0';
printf("%s\n",unmasked);
free(unmasked);
return 0;
}
Выход:
74651cb3206d0ab4736108a2
(Поскольку вы используете xor по кусочкам, вы должны использовать masking_key[i%8]
, чтобы получить ожидаемый результат, указанный в вопросе; читается как парные шестнадцатеричные байты, это сообщение в ASCII. Не уверен, откуда берется e
в конце.)
@MOehm Да, это просто исправление исходного кода OP. Дополнительный вывод был связан с отсутствующей ошибкой нулевого терминатора, которую я исправил, но забыл обновить вывод в посте :)
Большое спасибо за помощь. Было очень глупо с моей стороны обращаться со строками в C так же, как я обращаюсь с ними в python :).
Я думаю, что ваши строки действительно должны состоять из шестнадцатеричных кодов символов, а не из шестнадцатеричных чисел. Так что
"e17e8eb9"
должно быть"\xe1\x7e\x8e\xb9"
.