使用按位运算符解密隐藏消息

时间:2017-09-22 04:51:37

标签: c encryption bitwise-operators bitwise-xor

我遇到了这个练习,它要求你在下面的图片中解密加密代码中的隐藏信息。

Link To Picture

本练习与按位运算符有关,因此我假设我们需要使用“XOR”运算符来解密代码,使用2位数字键,范围从00到99.

这是我的代码。

char input[9] = "dEsxDI^I" , decrypt[9];      // Variable Declarations and Initializations.
int key;

printf("\n\n\nDecrpytion for the Encrypted code \"dEsxDI^I\"  :\n\n\n");

for(key = 0 ; key <= 99 ; key++) // 00 to 99 Key Testing.
    {
        for (int i = 0; i < 8; i++) // Decryption Process.
            {
                decrypt[i] = input[i] ^ key;
                printf("%c", decrypt[i]);
            }
        printf("    =    Key No (%d)\n\n\n", key); // Displays Key No for each decryption.
    }

printf("\n\n");
return 0;

我解密的消息是“Hi_There”,加密密钥为“44”。 只是想知道它是否是正确的信息?因为那是我解密的所有邮件中最合乎逻辑的信息。

这项练习没有提供解决方案,所以我很好奇。 那么,你的输出人员是什么?

3 个答案:

答案 0 :(得分:0)

我对您的解密信息进行了XOR,~XOR,AND,NAND,OR,NOR,左移,右移操作。

当然,我们任何人都会认为答案的关键是 44

我没有从该字符串中获得任何其他可读消息。

虽然你考虑所有可能性:

XOR:

  1. 键12:hItHERE
  2. key 44:Hi_There
  3. 键112:49.9____
  4. 用空格替换下划线(不是不可打印的字符,只是空格)

    OR:

    1. key 14:no~no~o
    2. 键46:no~no~o
    3. 是的,它们都是相同的,事实上OR会产生很多字符串,重复的字符像{{{{{{{{{#39;

      〜XOR:

      1. key 243:hItHERE
      2. key 211:Hi_There
      3. 现在,可读消息的定义取决于每个人。

        hItHERE可能是空袭的标志。

        no~no~o可能是寻求帮助或拒绝某事的呼吁。

        49.9可能是生物武器实验室中某些秘密成分的数量。

        0~99是一个非常有限的范围。

答案 1 :(得分:0)

  

我解密的消息是&#34; Hi_There&#34;使用加密密钥&#34;   44&#34;。只是想知道它是否是正确的信息?

对于8字符密码的解决方案是否必须是8个字符的解决方案,没有明确的指示,但这是一般情况。如果没有明确的指示(&#34; 您的解决方案可能包含或不包含密码中的所有字符。&#34;),我会寻找包含8个字符的解决方案。

虽然您没有提供代码的详细信息,但对所有可能的密钥进行简单的暴力循环与其他任何密钥一样好。由于您未获得解决方案,因此您无法进行任何比较。你可以做的最好的事情就是遍历所有键,将它应用到密码中的每个字符并输出结果 - 然后使用你&#34;好的眼球&#34;找出解决方案。 (如果您知道解决方案将是所有大写/小写字符 - 您可以在输出手动检查的每个结果之前强制执行该检查。)

不清楚是否有人告诉XOR每个字符key,或者你是否应该尝试所有合理的按位操作,而是一般{{1} }或OR是一个很好的起点。

XOR放在一起,你可以做类似的事情:

XOR

示例使用/输出

#include <stdio.h>

int main (void) {

    char *buf = "dEsxDI^I";

    for (int key = 0; key < 100; key++) {   /* loop over all keys */
        char *p = buf;                      /* output key (and char) */
        printf ("key: %2d ('%c')   ", key, key >= ' ' ? key : 0);
        while (*p)                          /* loop over all chars */
            putchar (*p++ ^ key);           /* output decrypted char */
        putchar ('\n');                     /* tidy up with '\n' */
    }

    return 0;
}

使用 XOR 来应用密钥并使用手动眼球扫描解决方案,$ ./bin/keyfind2 key: 0 ('') dEsxDI^I key: 1 ('') eDryEH_H key: 2 ('') fGqzFK\K key: 3 ('') gFp{GJ]J key: 4 ('') `Aw|@MZM key: 5 ('') a@v}AL[L <snip> key: 12 ('') hItHERE <snip> key: 43 ('+') OnXSobub key: 44 (',') Hi_There key: 45 ('-') Ih^Uidsd <snip> 看起来很有希望,但它只是一个7字符解决方案,继续{{1提供了一个8-char解决方案,并且在两个答案中会更好。

所以,&#34; &#34;,我认为您找到了正确的解决方案。

没有使用字符串索引的指针

由于使用指针key: 12 ('') hItHERE迭代key: 44 (',') Hi_There中的密码字符串似乎让你挠头(不用担心,它会随着时间的推移而全部浸泡) ,你可以轻松地使用字符串索引做同样的事情。 p循环与索引一样容易使用。消除指针并使用字符串索引,您可以执行以下操作:

buf

(输出完全相同)

关于在printf语句中使用三元运算符的问题对于不熟悉它的人来说是一个很好的问题。三元运算符是for语句的简写,其中表达式的结果基于给定的测试条件。基本上三元运算符是:

#include <stdio.h>

int main (void) {

    char *buf = "dEsxDI^I";

    for (int key = 0; key < 100; key++) {   /* loop over all keys */
        printf ("key: %2d ('%c')   ", key, key >= ' ' ? key : 0);
        for (int i = 0; buf[i]; i++)        /* loop over all chars */
            putchar (buf[i] ^ key);         /* output decrypted char */
        putchar ('\n');                     /* tidy up with '\n' */
    }

    return 0;
}

在我的if/else声明中,我只是这样做:

condition ? if_true_value : if_false_value

显然printf的整数值与printf ("key: %2d ('%c') ", key, key >= ' ' ? key : 0); 转换说明符一起使用,以确保所有key值都打印两个字符宽(这是{{{I}的目的1}} 字段宽度说明符。现在让我们看看我想通过%2d打印哪个字符。

key

这很容易。第一个可打印的ASCII值为2(十六进制)或%c十进制,对应于key >= ' ' ? key : 0 // huh? 空格)字符。请参见下面的ASCII表。那么我的测试条件是什么?如果0x20大于或等于 space 。如果是,只需打印32表示的字符。如果不是,则打印 nul-character (十进制' '或等效字符(key >= ' ') - 只需输入更多内容)。你可以做同样的事情:

key

(它只是打字0

ASCII表

'\0'

答案 2 :(得分:0)

目标应该是自动化检测机制。而不是从详尽的列表中找到解密的短语,而不是表单代码。

通过对OP代码的一些小修改,下面调用各种valid()来评估解密有效性。

建议OP进一步调整valid(),直到它提供1&#34;最佳&#34;解密。那么&#34;公式&#34;找到解密。

为了好玩:尝试查找此间谍和Google的电话号码以确定姓名。她的加密数据为"0>?%=;81"。相应地调整valid()

#include <stdio.h>

#if 1
int valid(const char *decrypt) {
  size_t end = strspn(decrypt, " ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz");
  return end == 8;
}

#else
int valid(const char *decrypt) {
  size_t end = strspn(decrypt, " ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz");
  if (end != 8) return 0;
  for (int i=1; i<8; i++) {
    if (isupper(decrypt[i-1]) && isupper(decrypt[i])) { //reject paired capital letters
      return 0;
    }
  }
  return 1;
}
#endif

int main(void) {
  const char input[9] = "dEsxDI^I";
  printf("Decryption for the Encrypted code \"dEsxDI^I\"  :\n\n");

  for (int key = 0; key <= 99; key++) {
    char decrypt[9] = ""; // Variable Declarations and Initializations.
    for (int i = 0; i < 8; i++) {
      decrypt[i] = (char) (input[i] ^ key);
    }
    if (valid(decrypt)) {
      printf("Key No %2d Decrypt:<%s>\n", key, decrypt);
    }
  }
  return 0;
}

输出 - 第一valid()

Decryption for the Encrypted code "dEsxDI^I"  :

Key No  1 Decrypt:<eDryEH_H>
Key No 10 Decrypt:<nOyrNCTC>
Key No 11 Decrypt:<oNxsOBUB>
Key No 16 Decrypt:<tUchTYNY>
Key No 17 Decrypt:<uTbiUXOX>
Key No 22 Decrypt:<rSenR_H_>
Key No 28 Decrypt:<xYodXUBU>
Key No 29 Decrypt:<yXneYTCT>
Key No 39 Decrypt:<CbT_cnyn>
Key No 42 Decrypt:<NoYRnctc>
Key No 43 Decrypt:<OnXSobub>
Key No 44 Decrypt:<Hi_There>
Key No 48 Decrypt:<TuCHtyny>
Key No 49 Decrypt:<UtBIuxox>
Key No 60 Decrypt:<XyODxubu>
Key No 61 Decrypt:<YxNEytct>

输出 - 第二valid()

Decryption for the Encrypted code "dEsxDI^I"  :

Key No 22 Decrypt:<rSenR_H_>
Key No 39 Decrypt:<CbT_cnyn>
Key No 44 Decrypt:<Hi_There>