凱薩密碼(Caesar Cipher)是歷史上最早的密碼之一,它簡單的將字母按照固定的位移量進行替換來達到加密的目的。雖然凱薩密碼在古代用途廣泛,但由於其易受到頻率分析攻擊的弱點,現代密碼學中較少使用。
Vigenere Cipher和Affine Cipher是兩種進階的古典密碼學算法,它們在歷史上代表了對凱薩密碼的改進和擴展。這份報告將深入探討這兩種算法的功能實現、應用以及未來的發展方向。
Vigenere Cipher是在16世紀由布拉德沃德提出的,它使用一個稱為「密鑰字」的短句來進行加密。密文的每個字母都是由明文中的相應字母和密鑰字中的字母組成的。這使得Vigenere Cipher相對於凱薩密碼更難被破解,因為它引入了密鑰的概念,增加了加密的隨機性。 自本次報告中,使用了以下程式碼實現Vigenere Cipher:
class VigenereCipher : public Cipher {
private:
std::string key;
public:
VigenereCipher(const std::string& k) : key(k) {}
std::string process(const std::string& text, int operation) const override {
if (operation == 0) { // Encrypt
return encrypt(text);
} else { // Decrypt
return decrypt(text);
}
}
private:
std::string encrypt(const std::string& plaintext) const {
std::string ciphertext = "";
for (size_t i = 0; i < plaintext.length(); ++i) {
if (isalpha(plaintext[i])) {
char base = isupper(plaintext[i]) ? 'A' : 'a';
char offset = key[i % key.length()] - 'A';
ciphertext += static_cast<char>((plaintext[i] + offset - base) % 26 + base);
} else {
ciphertext += plaintext[i];
}
}
return ciphertext;
}
std::string decrypt(const std::string& ciphertext) const {
std::string decryptedText = "";
for (size_t i = 0; i < ciphertext.length(); ++i) {
if (isalpha(ciphertext[i])) {
char base = isupper(ciphertext[i]) ? 'A' : 'a';
char offset = key[i % key.length()] - 'A';
decryptedText += static_cast<char>((ciphertext[i] - offset - base + 26) % 26 + base);
} else {
decryptedText += ciphertext[i];
}
}
return decryptedText;
}
};
Affine Cipher是一種更加複雜的古典密碼,它在每個字母上應用了一個仿射函數。這個函數具有兩個參數a和b,其中a和26互質。Affine Cipher的強大之處在於其線性轉換特性,使其能夠抵抗基本的頻率分析攻擊。 自本次報告中,使用了以下程式碼實現Vigenere Cipher:
class AffineCipher : public Cipher {
private:
int keyA;
int keyB;
public:
AffineCipher(int a, int b) : keyA(a), keyB(b) {}
std::string process(const std::string& text, int operation) const override {
if (operation == 0) { // Encrypt
return encrypt(text);
} else { // Decrypt
return decrypt(text);
}
}
private:
std::string encrypt(const std::string& plaintext) const {
std::string ciphertext = "";
for (char ch : plaintext) {
if (isalpha(ch)) {
char base = isupper(ch) ? 'A' : 'a';
ch = static_cast<char>((keyA * (ch - base) + keyB) % 26 + base);
}
ciphertext += ch;
}
return ciphertext;
}
std::string decrypt(const std::string& ciphertext) const {
int modInverseA = modInverse(keyA, 26);
std::string plaintext = "";
for (char ch : ciphertext) {
if (isalpha(ch)) {
char base = isupper(ch) ? 'A' : 'a';
ch = static_cast<char>(modInverseA * (ch - base - keyB + 26) % 26 + base);
}
plaintext += ch;
}
return plaintext;
}
int modInverse(int a, int m) const {
a = a % m;
for (int x = 1; x < m; x++)
if ((a * x) % m == 1)
return x;
return 1;
}
};
Vigenere Cipher和Affine Cipher相較於凱薩密碼都提供了更高的安全性。Vigenere Cipher通過引入密鑰字,增加了對抗頻率分析攻擊的能力。而Affine Cipher則透過線性轉換的特性,增加了密文的隨機性。兩者雖然都是古典密碼學中的重要算法,但在現代密碼學中過於容易遭到破解。至今主要用作教學和歷史研究的對象。
特性 | Vigenere Cipher | Affine Cipher |
---|---|---|
加密方式 | 多表雜湊加密,使用密鑰字進行加密 | 單一雜湊加密,使用仿射函數進行加密 |
密鑰管理 | 密鑰長度與明文相同 | 使用兩個整數a和b作為密鑰 |
抗頻率分析 | 較強,密鑰字增加了加密的隨機性 | 較弱,容易受到頻率分析攻擊的影響 |
運算方式 | 字母和密鑰字的相加,使用模運算 | 仿射函數的線性轉換,涉及乘法和加法 |
安全性 | 普通,對抗基本攻擊,但仍可被破解 | 較強,對抗頻率分析有一定的抵抗力 |
應用場景 | 簡短文本,需要較高的加密強度 | 對抗基本攻擊,需求較複雜的加密 |
以下長度偏長,可以先來看結果長怎樣:)
專案連結(Github) (release裡面也可以找到編譯完的檔案)
如果要自己編譯,請使用qt creator並確保版本於5.9.8或以上
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QComboBox>
#include <QFont>
#include <QString>
#include <QDesktopServices>
#include <QUrl>
#include <QMediaPlayer>
#include <iostream>
#include <string>
// Abstract base class for different cipher implementations
class Cipher {
public:
virtual std::string process(const std::string& text, int operation) const = 0;
};
// Implementation of the Affine Cipher, a type of substitution cipher
class AffineCipher : public Cipher {
private:
int keyA;
int keyB;
public:
AffineCipher(int a, int b) : keyA(a), keyB(b) {}
std::string process(const std::string& text, int operation) const override {
if (operation == 0) { // Encrypt
return encrypt(text);
} else { // Decrypt
return decrypt(text);
}
}
private:
std::string encrypt(const std::string& plaintext) const {
std::string ciphertext = "";
for (char ch : plaintext) {
if (isalpha(ch)) {
char base = isupper(ch) ? 'A' : 'a';
ch = static_cast<char>((keyA * (ch - base) + keyB) % 26 + base);
}
ciphertext += ch;
}
return ciphertext;
}
std::string decrypt(const std::string& ciphertext) const {
int modInverseA = modInverse(keyA, 26);
std::string plaintext = "";
for (char ch : ciphertext) {
if (isalpha(ch)) {
char base = isupper(ch) ? 'A' : 'a';
ch = static_cast<char>(modInverseA * (ch - base - keyB + 26) % 26 + base);
}
plaintext += ch;
}
return plaintext;
}
int modInverse(int a, int m) const {
a = a % m;
for (int x = 1; x < m; x++)
if ((a * x) % m == 1)
return x;
return 1;
}
};
// Implementation of the Vigenere Cipher, another type of substitution cipher
class VigenereCipher : public Cipher {
private:
std::string key;
public:
VigenereCipher(const std::string& k) : key(k) {}
std::string process(const std::string& text, int operation) const override {
if (operation == 0) { // Encrypt
return encrypt(text);
} else { // Decrypt
return decrypt(text);
}
}
private:
std::string encrypt(const std::string& plaintext) const {
std::string ciphertext = "";
for (size_t i = 0; i < plaintext.length(); ++i) {
if (isalpha(plaintext[i])) {
char base = isupper(plaintext[i]) ? 'A' : 'a';
char offset = key[i % key.length()] - 'A';
ciphertext += static_cast<char>((plaintext[i] + offset - base) % 26 + base);
} else {
ciphertext += plaintext[i];
}
}
return ciphertext;
}
std::string decrypt(const std::string& ciphertext) const {
std::string decryptedText = "";
for (size_t i = 0; i < ciphertext.length(); ++i) {
if (isalpha(ciphertext[i])) {
char base = isupper(ciphertext[i]) ? 'A' : 'a';
char offset = key[i % key.length()] - 'A';
decryptedText += static_cast<char>((ciphertext[i] - offset - base + 26) % 26 + base);
} else {
decryptedText += ciphertext[i];
}
}
return decryptedText;
}
};
// Widget for the graphical user interface
class CipherWidget : public QWidget {
Q_OBJECT
public:
CipherWidget(QWidget* parent = nullptr) : QWidget(parent) {
setupUI();
connectSignals();
}
private slots:
// Slot for the process button click
void onProcessClicked() {
QString inputText = inputLineEdit->text();
QString outputText;
// Determine the selected cipher type and perform the corresponding operation
if (cipherTypeComboBox->currentIndex() == 0) { // Affine Cipher
outputText = QString::fromStdString(affineCipher.process(inputText.toStdString(), operationComboBox->currentIndex()));
} else { // Vigenere Cipher
outputText = QString::fromStdString(vigenereCipher.process(inputText.toStdString(), operationComboBox->currentIndex()));
}
outputLineEdit->setText(outputText);
}
// Slot for the Kanna button click, opens my wife's Twitter link
void onKannaButtonClicked() {
QDesktopServices::openUrl(QUrl("https://twitter.com/H_KANNA_0203"));
}
// Slot for the Kanna button click, opens my wife's Official Page link
void onKannaBookButtonClicked() {
QDesktopServices::openUrl(QUrl("https://fc.hashimotokanna.jp/"));
}
private:
QVBoxLayout* mainLayout;
QLabel* titleLabel;
QMediaPlayer* player;
QComboBox* cipherTypeComboBox;
QComboBox* operationComboBox;
QLineEdit* inputLineEdit;
QLineEdit* outputLineEdit;
QPushButton* processButton;
QPushButton* KannaButton;
QPushButton* KannaBookButton;
QLabel* imageLabel;
AffineCipher affineCipher{5, 8}; // Example key for Affine Cipher, you can change key here ny yourself
VigenereCipher vigenereCipher{"KEY"}; // Example key for Vigenere Cipher, You can change key here ny yourself
// Set up the user interface components
void setupUI() {
mainLayout = new QVBoxLayout(this);
// Set up and scale the image label
imageLabel = new QLabel(this);
QPixmap image(":/ck/chiken.png");
qreal scaleRatio = 0.5;
QPixmap scaledImage = image.scaled(image.size() * scaleRatio, Qt::KeepAspectRatio);
imageLabel->setPixmap(scaledImage);
// Set up the media player for background music
player = new QMediaPlayer;
player->setMedia(QUrl("qrc:/ck/music.wav"));
player->setVolume(10);
player->play();
// Set up the title label
titleLabel = new QLabel("段考爆破神器", this);
titleLabel->setAlignment(Qt::AlignCenter);
// Set up combo boxes for selecting cipher type and operation
cipherTypeComboBox = new QComboBox(this);
cipherTypeComboBox->addItem("Affine cipher");
cipherTypeComboBox->addItem("Vigenère cipher");
operationComboBox = new QComboBox(this);
operationComboBox->addItem("搞他!");
operationComboBox->addItem("解他!");
// Set up input and output text fields
inputLineEdit = new QLineEdit(this);
inputLineEdit->setPlaceholderText("用滿滿的文字填滿這裡...");
outputLineEdit = new QLineEdit(this);
outputLineEdit->setReadOnly(true);
outputLineEdit->setPlaceholderText("結果是...");
// Set up buttons for encryption/decryption and external links
processButton = new QPushButton("簽下去", this);
KannaButton = new QPushButton("寶🥰", this);
KannaBookButton = new QPushButton("橋本純情內科🥰", this);
// Set up layout for cipher type and operation combo boxes
QHBoxLayout* comboLayout = new QHBoxLayout;
comboLayout->addWidget(cipherTypeComboBox);
comboLayout->addWidget(operationComboBox);
// Add all components to the main layout
mainLayout->addWidget(imageLabel);
mainLayout->addWidget(titleLabel);
mainLayout->addLayout(comboLayout);
mainLayout->addWidget(inputLineEdit);
mainLayout->addWidget(outputLineEdit);
mainLayout->addWidget(processButton);
mainLayout->addWidget(KannaButton);
mainLayout->addWidget(KannaBookButton);
setLayout(mainLayout);
}
// Connect signals (events) to corresponding slots (functions)
void connectSignals() {
connect(processButton, &QPushButton::clicked, this, &CipherWidget::onProcessClicked);
connect(KannaButton, &QPushButton::clicked, this, &CipherWidget::onKannaButtonClicked);
connect(KannaBookButton, &QPushButton::clicked, this, &CipherWidget::onKannaBookButtonClicked);
}
};
// Main function
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
QFont font("Microsoft YaHei", 12);
QApplication::setFont(font);
CipherWidget cipherWidget;
cipherWidget.setWindowTitle("哈哈哈段考爆了 - 21210 李品翰 (2006-2024)");
cipherWidget.show();
return app.exec();
}
#include "main.moc"
Vigenere Cipher和Affine Cipher都有其獨特的優勢,Vigenere Cipher適用於需要較高加密強度的應用,例如保護短語或簡訊。Affine Cipher則在對抗一些基本攻擊方面表現優越,可以應用於一些較為複雜的加密需求。
未來的改進方向可以包括對這些算法進行更多的分析,並嘗試應用於現代密碼學的某些方面。例如,可以考慮結合這些算法與現代加密技術,以提高整體安全性。
Qt project. (n.d.). Qt Documentation. Retrieved January 15, 2024, from https://doc.qt.io/
C++. (n.d.). C++ Documentation. Retrieved January 15, 2024, from https://devdocs.io/cpp/
Wikipedia contributors. (n.d.). Vigenère Cipher - Wikipedia. Retrieved January 15, 2024, from https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher
Wikipedia contributors. (n.d.). Affine Cipher - Wikipedia. Retrieved January 15, 2024, from https://en.wikipedia.org/wiki/Affine_cipher
史博勳. (2022, June 27). 二.內文 - HackMD. Retrieved January 15, 2024, from https://hackmd.io/@bEguM6t5RgyX3mvN42fwCA/S1eHzIaK5