需要帮助调试我的c ++编程(文本ascii manupulation)

时间:2015-08-02 14:52:12

标签: c++ debugging encryption ascii

我最近制作了一个基于vigenere密码技术加密文本的C ++程序。

我认为加密部分工作正常,但在某些情况下,解密功能似乎没有输出正确的答案。我希望有人能看看代码并告诉我它有什么问题。

CMD对话框:

输入加密密钥: 的魔法

输入消息1: 我喜欢C编程

邮件已加密: u rwxq i rdomzcymovi

解密: 我喜欢编程

在这种情况下它以某种方式输出“X”而不是“r”.............

以下是代码:

Secret.h:

#ifndef CPP_TUTORIALS_SECRET_H
#define CPP_TUTORIALS_SECRET_H
#include <iostream>
using namespace std;

class Secret {

private:
    string message;
    string key;
    bool toEncrypt;
    bool toDecrypt;

public:
    bool isToDecrypt() const {
        return toDecrypt;
    }

    Secret(const string &message = "", const string &key = "", bool toEncrypt = false);

    ~Secret();

    void setToDecrypt(bool toDecrypt);

    void encrypt();

    void decrypt();

    void display();

};

#endif //CPP_TUTORIALS_SECRET_H

Secret.cpp

#include "Secret.h"

Secret::Secret(const string &message, const string &key, bool toEncrypt) {
    Secret::message = message;
    Secret::key = key;
    Secret::toEncrypt = toEncrypt;
}

Secret::~Secret(){

}

void Secret::setToDecrypt(bool toDecrypt) {
    Secret::toDecrypt = toDecrypt;
}

void Secret::display() {
    cout << message << endl;
}

void Secret::encrypt() {
    if(toEncrypt) {
        int keyAscii[key.length()];
        int count = 0;

        for(unsigned int i = 0; i < key.length(); i++) {
            keyAscii[i] = key.at(i);
        }

        for(unsigned int i = 0; i < message.length(); i++) {
            if (message.at(i) > 64 && message.at(i) < 91) {
                message.at(i) = (char)((message.at(i) - 65 + (keyAscii[count] - 97)) % 26 + 97);
            }
            else if (message.at(i) > 96 && message.at(i) < 123) {
                message.at(i) = (char)((message.at(i) - 97 + (keyAscii[count] - 97)) % 26 + 97);
            }
            else{
                message.at(i) = message.at(i);
            }
            count++;
            if(count == key.length()) {
                count = 0;
            }
        }
    }
}

void Secret::decrypt() {
    if(toDecrypt) {
        int keyAscii[key.length()];
        int count = 0;

        for(unsigned int i = 0; i < key.length(); i++) {
            keyAscii[i] = key.at(i);
        }

        for(unsigned int i = 0; i < message.length(); i++) {
            if (message.at(i) > 96 && message.at(i) < 123) {
                message.at(i) = (char)((message.at(i) - 97) % 26 - (keyAscii[count] - 97) + 97);
            }
            else {
                message.at(i) = message.at(i);
            }
            count++;
            if (count == key.length()) {
                count = 0;
            }
        }
    }
}

的main.cpp

#include <limits>
#include "Secret.h"

void calcMsgAmount(int &pArraySize);
void inputKey(string &key);
void encryptMsg(Secret &secret, string &msg, const string &key, bool toEncrypt, int index);

int main() {
    int arraySize;
    string key;
    string msg;

    calcMsgAmount(arraySize);
    inputKey(key);

    Secret secrets[arraySize];

    for(int i = 0; i < arraySize; i++){
        encryptMsg(secrets[i], msg, key, true, i);
    }

    cout << endl << "Message encrypted: " << endl;
    for(Secret i: secrets){
        i.display();
        i.setToDecrypt(true);
        if(i.isToDecrypt()){
            i.decrypt();
            cout << endl << "Decrypted: " << endl;
            i.display();
        }
        cout << endl << endl;
    }

    return 0;
}

void calcMsgAmount(int &pArraySize) {
    cout << "Enter the amount of messages you want to input: " << endl;
    while(!(cin >> pArraySize)){
        cout << endl << "There's something really wrong with your input, please enter again." << endl;
        cout << "Enter the amount of messages you want to input: " << endl;
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }
}

void inputKey(string &key){
    cout << "Enter the key for encrytion: " << endl;
    cin.ignore();
    getline(cin, key);
}

void encryptMsg(Secret &secret, string &msg, const string &key, bool toEncrypt, int index){
    cout << "Enter message No. " << index + 1 << ": " << endl;
    getline(cin, msg);
    secret = Secret(msg, key, toEncrypt);
    secret.encrypt();
}

非常感谢

2 个答案:

答案 0 :(得分:2)

wikipedia加入Vigenere Cipher的解密程序

(C - K) mod 26

您在Secret::decrypt()中撰写的内容是

message.at(i) = (char)((message.at(i) - 97) % 26 - (keyAscii[count] - 97) + 97);

C % 26 - K

我将行改为

message.at(i) = (char)((26 + (message.at(i) - 97) - (keyAscii[count] - 97)) % 26 + 97);

似乎是正确的。我还没有真正理解为什么前26个是必要的,但如果没有它,代码就不起作用(带有%和负数的东西)

P.S。至于调试部分,您可能已经注意到whong字母显示为具有较小ascii代码的错误大写字母,因此您解密例程中包含负数。之后你会根据维基百科检查你的代码:)

答案 1 :(得分:0)

问题在于解决两个问题:

  • 第一个是计算应该与加密对称,即消息的模26,密钥(如effenok已经指出的那样)
  • 第二个是在解密时你可以在char级别,message-key可以是负数,这可能不会给你模26的预期结果(例如-2%26是-2以便你&#39; ll超出您期望的字母范围)。简单的技巧是在进行模数之前添加26,这样可以确保它在正数上完成。

这里的功能稍微紧凑一些,区别在于大写和小写:

void Secret::encrypt() {
    if(toEncrypt) {
        for(unsigned int i = 0; i < message.length(); i++) {
            if(isalpha(message[i])){
                char start = isupper(message[i]) ? 'A' : 'a';
                message[i] = (message[i] - start + (tolower(key[i%key.length()]) - 'a') + 26) % 26 + start;
            }
        }
    }
}
void Secret::decrypt() {
    if(toDecrypt) {
        for(unsigned int i = 0; i < message.length(); i++) {
            if (isalpha(message[i]) ){
                char start = isupper(message[i]) ? 'A':'a'; 
                message[i] = (message[i] - start - (tolower(key[i%key.length()]) - 'a') + 26) % 26 + start;
            }
        }
    }
}