当前位置: 首页 > 知识库问答 >
问题:

使用替换密码进行加密不会生成有效的ASCII输出

虞航
2023-03-14

我不明白为什么它说“输出无效的ASCII文本”!

为了让你理解问题的背景,我发布了描述要做的事情。从这里开始!

在替换密码中,我们通过用另一个字母替换每个字母来“加密”(即以可逆的方式隐藏)消息。为此,我们使用一个密钥:在本例中,是字母表中每个字母到加密时对应的字母的映射。为了“解密”消息,消息的接收者需要知道密钥,这样他们就可以逆转这个过程:将加密文本(通常称为密文)转换回原始消息(通常称为明文)。

例如,键可以是字符串nqxpomaftrhlzgecyjiuwskdvb。这个26个字符的键意味着A(字母表的第一个字母)应该转换为N(键的第一个字符),B(字母表的第二个字母)应该转换为Q(键的第二个字符),以此类推。

然后,像hello这样的消息将被加密为folle,根据密钥确定的映射替换每个字母。

让我们编写一个名为substitution的程序,它使您能够使用substitution密码对消息进行加密。在用户执行程序时,他们应该通过提供命令行参数来决定在运行时提供的秘密消息中应该有什么密钥。

下面是一些程序如何工作的例子。例如,如果用户输入ytnshkvefxrbauqzclwdmipgjo键和hello:

$ ./substitution YTNSHKVEFXRBAUQZCLWDMIPGJO
plaintext:  HELLO
ciphertext: EHBBQ

如果用户提供vchprzgjntlskfbdqwaxeuymoi键和hello,world明文,程序的工作方式如下:

$ ./substitution VCHPRZGJNTLSKFBDQWAXEUYMOI
plaintext:  hello, world
ciphertext: jrssb, ybwsp

请注意,逗号和空格都没有被密码替换。只能代替字母顺序的字符!请注意,原始消息的大小写已经被保留了。小写字母保持小写,大写字母保持大写。

键本身中的字符是大写还是小写并不重要。vchprzgjntlskfbdqwaxeuymoi的键在功能上与vchprzgjntlskfbdqwaxeuymoi的键相同(就此而言,vchprzgjntlskfbdqwaxeuymoi)。

#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(int argc, string argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./substitution KEY");
        return 1;               
    }
    else if (argc == 2)
    {
        string text = argv[1];
        string storing = text;
        int counter = 0;
        int i = 0;
        bool number = true;
        bool flag = true;
        while (flag == true && i < 26)
        {
            if ((int)text[i] >= 48 && (int)text[i] <= 57)
            {
                 number = false;
            }
            if (((int)text[i] >= 65 && (int)text[i] <= 90) || ((int)text[i] >= 97 && (int)text[i] <= 122))
            {
                counter++;
                for ( int j = 0; j < counter - 1; j++)
                {
                    if ((int)storing[j] == (int)text[i] || (int)storing[j] + 32 == (int)text[i])
                    {
                        flag = false;
                    }
                }
            }
            i++;
        }
        if (number == false)
        {
            printf("Key must only contain alphabetic characters.");
            return 1;
        }
        if (flag == false)
        {
            printf("Key must not contain repeated characters.");
            return 1;
        }
        if (counter < 26)
        {
            printf("Key must contain 26 characters.");
            return 1;
        }
    }
    string plaintext = get_string("plaintext:");
    string key = argv[1];
    int counter;
    bool not_letter;
    bool capital1;
    bool capital;
    int crypto[strlen(plaintext)];
    for (int i = 0; i < strlen(plaintext); i++)
    {
        capital1 = false;
        capital = false;
        not_letter = false;
        if ((int)plaintext[i] >=65 && (int)plaintext[i] <= 90)
        {           
            counter =  (int)plaintext[i] - 65;            
            capital = true;
        }
        else if ((int)plaintext[i] >=97 && (int)plaintext[i] <= 122)
        {
            counter =  (int)plaintext[i] - 97;                          
            capital1 = true;
        }
        else
        {
            not_letter = true;
        }
        if (not_letter == true)
        {
            crypto[i] = (int)plaintext[i];
        }
        else if (capital == true)
        {
            if ((int)key[i] >=65 && (int)key[i] <= 90)
            {
                crypto[i] = (int)key[counter];
            }
            else if ((int)key[i] >=97 && (int)key[i] <= 122)
            {
                crypto[i] = (int)key[counter] - 32;
            }
        }
        else if (capital1 == true)
        {
            if ((int)key[i] >=65 && (int)key[i] <= 90)
            {
                crypto[i] = (int)key[counter] + 32;
            }
            else if ((int)key[i] >=97 && (int)key[i] <= 122)
            {
                crypto[i] = (int)key[counter];
            }  
        }
    }
    printf("ciphertext: ");
    for (int i = 0; i < strlen(plaintext); i++)
    {
        printf("%c", (char)crypto[i]);
    }
    printf("\n");
    return 0;
}

当我用CS50的check50 CS50/problems/2020/x/substitution测试程序时,它说:

:) substitution.c exists
:) substitution.c compiles
:) encrypts "A" as "Z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
:) encrypts "a" as "z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
:) encrypts "ABC" as "NJQ" using NJQSUYBRXMOPFTHZVAWCGILKED as key
:) encrypts "XyZ" as "KeD" using NJQSUYBRXMOPFTHZVAWCGILKED as key
:) encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZTEOGXHCIPJSQD as key
:) encrypts "This is CS50" as "Cbah ah KH50" using yukfrnlbavmwzteogxhcipjsqd as key
! :( encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZteogxhcipjsqd as key
    output not valid ASCII text
! :( encrypts all alphabetic characters using DWUSXNPQKEGCZFJBTLYROHIAVM as key
    output not valid ASCII text
:) handles lack of key
:) handles invalid key length
:) handles invalid characters in key
:) handles duplicate characters in key
:) handles multiple duplicate characters in key

共有1个答案

夹谷辰沛
2023-03-14

假设您已经将密钥转换为大写字母。

然后让我们简化一下循环中的问题:

int keyIndex;
bool lowercase;
for (int i = 0; i < strlen(plaintext); i++) {
    if (plaintext[i] >= 'A' && plaintext[i] <= 'Z') {
        keyIndex = plaintext[i] - 'A';
        lowercase = false;
    } else if (plaintext[i] >= 'a' && plaintext[i] <= 'z') {
        keyIndex = plaintext[i] - 'a';
        lowercase = true;
    } else {
        // do not encrypt that character
        ciphertext[i] = plaintext[i];
        // and skip the rest of the loop
        continue;
    }

    ciphertext[i] = key[keyIndex];

    // revert back to lowercase, if necessary
    if (lowercase) {
        ciphertext[i] += 'a' - 'A';
    }
}

你遇到的问题是你没有把你的大问题分解成小问题。因此,如果您预先创建了一个全大写字母键,那么您不需要在以后考虑它。

当然,将键转换为所有小写字母,然后在必要时将字符转换回大写字母同样有效。

永远不要使用变量名,如counteruppercase1。它使您的代码很难阅读;变量名应尽可能清晰。

ciphertext数组只是上面代码中的字符串/字符数组。如果您使用的是C而不是C++,那么我想您通常会使用char*char[]

 类似资料:
  • 我正在尽我最大的努力创建一个程序,它将生成一个私有/公共RSA密钥集,并使用它发送消息,从端到端是安全的。我正在使用RSA私钥/公钥对来安全地传输AES密钥,该密钥将用于发送消息。 当我使用1024位密钥对时,加密的会话密钥是128字节。但在试图用RSA私钥解密时,它抱怨说只能解密117字节或更少的字节。 当我使用2048位的密钥对时,加密的会话密钥是256字节(但必须是245或更少),等等。 结

  • 问题内容: 我正在使用Java应用程序,该应用程序要求我使用从不同字符串生成的两个密钥进行加密和解密。一个字符串来自用户,另一个是主密钥。我上网查看了有关它的一些参考资料。我真的很想知道如何实现此目标。我将展示我现在拥有的。 因此,从代码中可以看到,我使用了其他stackoverflow帖子中的一些代码,并对其进行了一些修改。我只是不知道如何从2个字符串生成2个密钥,以及从哪里可以获取用于解密的S

  • 我正在开发一个Java应用程序,它要求我使用从不同字符串生成的两个密钥进行加密和解密。一个字符串来自用户,另一个是主密钥。我在网上查了一下,找到了一些关于它的参考资料。我真的很想得到一些帮助,了解如何实现这一点。我将展示我现在所拥有的。 正如您从代码中看到的,我使用了其他stackoverflow帖子中的一些代码,并对其进行了一些修改。我只是不知道如何从2个字符串生成2个密钥,以及从哪里可以获得用

  • 我想得到的是 使用libnail加密密码salt 我有一个列表的盐,我想用它来加密/解密我的密码。当我加密密码时,我得到一个哈希返回,这样一个似乎可以工作,但在解密时,我总是得到假返回值。 我是否使用了错误的方法对libnaude进行加密/解密,还是完全朝着错误的方向行驶? 我的加密/解密源: 我感谢任何帮助! 多姆

  • 问题内容: 我之所以写这个问题+答案,是因为我挣扎了很多(也许是因为缺乏经验),并迷失了使用node或python进行加密/解密的许多不同方式。 我以为我的案子将来可以帮助人们。 我需要做的是: 从表单获取数据,使用Crypto(node-js)对其进行加密 在Python中传递加密的数据,然后使用PyCrypto将其解密。 我选择使用AES加密。 这是我的开始方式(我不会尝试的所有事情): 我遵

  • <?php $pw='simplewind'; $afpw=sp_password($pw);//加密字符串 echo $afpw;//输出加密后的字符串 ?>