Vigenere 密码解码无法正常工作

Posted

技术标签:

【中文标题】Vigenere 密码解码无法正常工作【英文标题】:Vigenere cipher decoding not working properly 【发布时间】:2018-11-08 21:29:55 【问题描述】:

我正在编写一个 vigenere 密码,用作可加载内核模块的一部分。因此,我不能使用字符串库。这就是为什么我包含单独的循环来获取密钥和输入长度。 include 语句和 main 仅用于测试。

每当我使用不是全部大写的键时,程序都会由于地址清理程序错误而崩溃。这只发生在我包含应该将键输入转换为大写的代码时。我不确定这是不正确的,因为我转换为大写的方法与我过去在堆栈溢出中看到的相同。如果没有这些行,它将运行良好并且不会崩溃。

此外,解码阶段没有按预期工作,它给出了不正确的解码消息。我能想象的唯一可能的问题是我允许输入包含空格,但我认为这不是问题,因为我只是在字符串中添加一个空格。我真的很感激一些关于我在这段代码中出错的地方的意见。 尝试转换为大写时的完整错误是:

==25694==ERROR: AddressSanitizer: BUS on unknown address 0x00010c98ae80 (pc 0x00010c989ac2 bp 0x7ffee3277610 sp 0x7ffee3277440 T0)
    #0 0x10c989ac1 in encrypt (vig:x86_64+0x100001ac1)
    #1 0x10c98aca1 in main (vig:x86_64+0x100002ca1)
    #2 0x7fff5c419ef8 in start (libdyld.dylib:x86_64+0x16ef8)

==25694==Register values:
rax = 0x000000010c98ae80  rbx = 0x00007ffee3277440  rcx = 0x000000010c98ae4b  rdx = 0x0000000000000004  
rdi = 0x000000010c98ae80  rsi = 0x000000010c98ae4b  rbp = 0x00007ffee3277610  rsp = 0x00007ffee3277440  
 r8 = 0x00001000219315d0   r9 = 0x0000000000000004  r10 = 0x0000000000000000  r11 = 0x0000000000000000  
r12 = 0x0000000000000000  r13 = 0x0000000000000000  r14 = 0x0000000000000000  r15 = 0x0000000000000000  
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: BUS (vig:x86_64+0x100001ac1) in encrypt
==25694==ABORTING
Abort trap: 6

这是我的代码:

#include<stdio.h>
#include<stdlib.h>
char* encrypt(char* input, char* key)

    int keyLength = 0;
    int inputLength = 0;
    int i;
    int j;
    for(i = 0; key[i] != '\0'; i++) //Get the length of the key
    
        keyLength++;
    
    for(i = 0; input[i] != '\0'; i++) //Get the length of the input
    
        inputLength++;
    
    for (i = 0; i < keyLength; i++)
    
        if(key[i] >= 'a' && key[i] <= 'z')
        
             key[i] = key[i] - 'a' + 'A';
        
    

    char* encryptedMessage = (char *)malloc((inputLength+1)*sizeof(char)); //Malloc for the encrypted message
    char fixedKey[inputLength + 1];
    if(inputLength < keyLength)
    
        for(i =0; i < inputLength; i++)
        
            fixedKey[i] = key[i];
        
    
    for(i = 0, j = 0; i < inputLength; ++i, ++j) //If the key length is shorter than message length, loop the key to correct length
    
        printf("Entered Loop\n");
        if(j == keyLength)
            j = 0;
        fixedKey[i] = key[j];
    
    fixedKey[i] = '\0';
    for(i = 0; i < inputLength; ++i) //Encryption
    
        if(input[i] == ' ')
        
            encryptedMessage[i] = ' ';
            continue;
        
        encryptedMessage[i] = ((input[i] + fixedKey[i]) % 26) + 'A';
    
    encryptedMessage[i] = '\0';
    return encryptedMessage;

char* decrypt(char* input, char* key)

    int keyLength = 0;
    int inputLength = 0;
    int i;
    int j;
    for(i = 0; key[i] != '\0'; i++) //Get the length of the key
    
        keyLength++;
    
    for(i = 0; input[i] != '\0'; i++) //Get the length of the input
    
        inputLength++;
    
    for (i = 0; i <keyLength; i++)
    
        if(key[i] >= 'a' && key[i] <= 'z')
        
            key[i] = key[i] - 'a' + 'A';
        
    
    char* decryptedMessage = (char *)malloc((inputLength+1)*sizeof(char));
    char fixedKey[inputLength + 1];
    if(inputLength < keyLength)
    
        for(i =0; i < inputLength; i++)
        
            fixedKey[i] = key[i];
        
    
    for(i = 0, j = 0; i < inputLength; ++i, ++j) //Fix the key length if needed
    
        if(j == keyLength)
            j = 0;
        fixedKey[i] = key[j];
    
    fixedKey[i] = '\0';
    for(i = 0; i < inputLength; ++i) //Decryption
    
        if(input[i] == ' ')
        
            decryptedMessage[i] = ' ';
            continue;
        
        decryptedMessage[i] = (((input[i] - fixedKey[i]) + 26) % 26) + 'A';
    
    decryptedMessage[i] = '\0';
    return decryptedMessage;

int main()

    char* encrypted = encrypt("The quick brown fox jumps over lazy dogs","key");
    char* decrypted = decrypt(encrypted,"key");
    printf("Encrypted string is: %s\nDecrypted String is: %s\n",encrypted,decrypted);
    return 0;

【问题讨论】:

错误不是告诉你源文件和行号吗?发布完整的错误。 @stark 我更新了帖子以包含完整的错误 我认为你不能在内核模块中使用malloc 您正在尝试将只读字符串转换为大写。 解密错误是因为输入字符串的大小写没有用同样的方法转换。如果您的输入全部为大写,则解密有效。在我看来,您的代码有太多特殊情况。例如,您不必区分键比输入短的情况;这是自动捕获的。当您转换不是字母或空格的字符时,也不清楚会发生什么。 【参考方案1】:

您正在尝试修改字符串文字。

您将encrypted 称为:

encrypt("The quick brown fox jumps over lazy dogs","key");

然后在encrypt中,修改第二个参数:

key[i] = key[i] - 'a' + 'A';

字符串文字是只读的,尝试修改它们会调用undefined behavior。

制作key 的本地副本,并在执行大写/小写转换时对其进行修改。

【讨论】:

我假设做 char* keyCopy = key;行不通,因为这只会创建一个指向键的指针,它仍然是一个字符串文字? @ColinNull 正确。您需要复制key,或者在创建fixedKey时进行大小写转换。 char* 本身不能修改吗?例如,我是否可以创建另一个 char* keyCopy,然后从 key 逐个字符复制,然后修改 keyCopy?我解决了密钥大小写的问题,但现在我遇到了与输入大小写相同的问题(它需要全部大写或全部小写),并且我想避免修改加密和解密的返回类型如果可能的话。 @ColinNull 取决于它指向什么。如果它指向一个字符串文字,那么你不能修改它指向的内容。如果它指向 char 数组的元素或 malloc 的内存,那么你可以。 那么,下面的内容就无效了? char* inputCpy = NULL; for(i = 0; inputA[i] != '\0'; i++) inputCpy[i] = input[i]; if(inputCpy[i] &gt;= 'a' &amp;&amp; inputCpy[i] &lt;= 'z') inputCpy[i] = inputCpy[i] - 'a' + 'A'; inputCpy[i] = '\0';

以上是关于Vigenere 密码解码无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

维热内密码解密

NOIP 2012 题解

Python:解码使用仿射密码编码的 Vigenere 密码

Go 语言入门很简单:实现 Vigenere 加密算法

C++ 链表凯撒密码 Vigenere Cipher

python中的Vigenere密码[关闭]