【问题标题】:How to reverse XOR-shift operations如何反转 XOR 移位操作
【发布时间】:2020-10-06 03:02:48
【问题描述】:

我有以下异或移位编码器

char a[] = "text";
int b = strlen(a);
for (int c = 0; c < b; c++) {
    if (c > 0) a[c] ^= a[c-1];
    a[c] ^= a[c] >> 3;
    a[c] ^= a[c] >> 2;
    a[c] ^= a[c] >> 1;
    printf("%02x", (unsigned int)(a[c]));
}

我想将十六进制输出恢复为原始字符串。

考虑到在某些情况下移位会消除右侧无法再检索的位,这是否可能?如果可能,如何恢复操作?

【问题讨论】:

  • 高达 256 个可能的值。建立一个查找表。
  • @n.'pronouns'm。我之前回答过类似的想法,但看起来每个元素都取决于前一个元素
  • @EugeneSh。 这种依赖很容易可逆。
  • @n.'pronouns'm。确实。所以证明/证明a[1] 的可逆性(通过表格)就足够了

标签: c xor shift


【解决方案1】:

是的,这并不难。只需将 xor-shit 结果映射回其原始值即可。考虑这个函数:

char f(char c) {
    c ^= c >> 3;
    c ^= c >> 2;
    c ^= c >> 1;
    return c;
}

您应该能够让自己满意,对于每个可能的输入值(从 0 到 127),都有一个对应的唯一输出。 (当然,如果你把char改成unsigned char,那么这个函数就可以在任何8位输入上工作。)

使用此函数,您可以轻松创建一个数组来执行此函数的逆操作:

char g(char c) {
    static char *map = NULL;
    if (!map) {
        map = malloc(128);
        for (int i=0; i<128; i++) map[f(i)] = i;
    }
    return map[c];
}

然后只需编写一个函数依次读取字符串的每个字符,应用这个反向函数,然后将结果与之前的值进行异或:

char *decode(char *s, int len) {
    char *start = s, last = 0;
    while (len--) {
        char tmp = *s;
        *s = last ^ g(*s);
        last = tmp;
        s++;
    }
    return start;
}

【讨论】:

    【解决方案2】:

    在这种情况下,查找表只能使用 8 位值,但也可以在没有 8 位值的情况下进行这种反转。

    要反转x ^= x &gt;&gt; a 做:

    x ^= x >> a;
    x ^= x >> (2*a);
    x ^= x >> (4*a);
    x ^= x >> (8*a);
    // ...
    

    直到移位量a超过类型的位宽。考虑到这一点,您可以拥有如下编码和解码功能:

    void encode(unsigned char* str, size_t len) {
        for (int c = 0; c < len; c++) {
            if (c > 0) str[c] ^= str[c-1];
            str[c] ^= str[c] >> 3;
            str[c] ^= str[c] >> 2;
            str[c] ^= str[c] >> 1;
        }
    }
    
    void decode(unsigned char* str, size_t len) {
        for (int c = len - 1; c >= 0; c--) {
            str[c] ^= str[c] >> 1;
            str[c] ^= str[c] >> 2;
            str[c] ^= str[c] >> 4;
            
            str[c] ^= str[c] >> 2;
            str[c] ^= str[c] >> 4;
            
            str[c] ^= str[c] >> 3;
            str[c] ^= str[c] >> 6;
            if (c > 0) str[c] ^= str[c-1];
        }
    }
    

    【讨论】:

      【解决方案3】:

      考虑到这种移位在某些情况下会消除 右侧

      实际上这是微不足道的,特别是因为比特被消除了!

      让我们反转您示例中的最后一步,您应该能够从那里向后工作。让我们将 8 位数字的数字视为名为 a 到 h 的布尔变量以及生成的布尔变量 i 到 p:

      abcdefgh ^
      0abcdefg =
      ijklmnop
      

      我们看到的只是 i 到 p,但我们想找到 a 到 h。注意 a^0=i,但任何与 0 异或的东西都只是它本身,所以我们知道 a。我们也知道:b^a=j 如果我们用“a”异或两边,我们得到 b^a^a=j^a。 Xor 的特殊之处在于,对具有相同值的事物进行两次异或会抵消它,因此等式简化为 b=j^a。现在我们有 b。我相信您知道如何继续此操作并获得其余数字并最终获得种子。

      【讨论】:

        猜你喜欢
        • 2014-06-15
        • 2015-02-11
        • 1970-01-01
        • 1970-01-01
        • 2020-09-02
        • 2014-12-16
        • 1970-01-01
        • 2019-08-16
        • 2023-03-02
        相关资源
        最近更新 更多