C 中的 XOR 两个十六进制字符串(取消屏蔽)

XOR two hexadecimal strings(unmasking) in C

我想在 C 语言中使用以下算法来揭露十六进制字符串 j = i MOD 4 transformed-octet-i = original-octet-i XOR masking-key-octet-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。如果有人能帮我修复这里的错误,那将非常有帮助。

你在这里做的不是对十六进制字节进行异或,而是对代表它们的字符进行异或。

虽然理想的过程是 (0x95 ^ 0xe1) + (0xbf ^ 7e) + ...,但您正在做的是对每个字符的 ascii 值进行异或,即 ('9' ^ 'b') + ('5' ^ '1') + ...

您需要做的是首先将十六进制字符串转换为字节本身(bytes.fromhex("951bfdcdc113ebca921fe9dc") in python),然后才对它们进行异或运算。我会这样做的方式是 sscanf("%2x", ...).

例如:

#include <stdio.h>

int main()
{
    unsigned char a = 0;
    scanf("%2hhx", &a);
}

您需要在执行 XOR 之前从字符串格式转换为原始整数,然后在将其打印为字符串之前转换回来。否则你将异或符号值,而不是原始值。

您可以使用 strtol(data, 0, 16) 一次性转换整个字符串。但是,使程序员不同于代码猴子的一个常见细节是能够在不借助库函数的情况下编写琐碎的 string-integer 转换代码。所以这里有一个简化的代码就是这样做的 - 请注意完全没有错误处理,因为这只是快速和肮脏的代码:

#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]='[=10=]';

  printf("%s\n",unmasked);
  free(unmasked);
  return 0;
}

输出:

74651cb3206d0ab4736108a2