ヴィジュネル暗号をC++で実装する方法|暗号化・復号化プログラムの解説
ヴィジュネル暗号(Vigenère Cipher)は、アルファベットのテキストを暗号化するための多表式換字暗号の一種です。鍵の各文字に応じて異なる換字表が切り替わる仕組みのため、単純なシーザー暗号などと比べて、頻度分析による解読への耐性が高いという特徴があります。
この方式の暗号化と復号化には「ヴィジュネル暗号表」を使用します。これは、AからZまでのアルファベットを1行ずつ順にずらしながら26行に並べた、26×26の表です。

暗号化の流れ
鍵:WELCOME
平文:Thisistutorialspoint
まず、与えられた鍵を平文と同じ長さに達するまで繰り返し、処理用の鍵列を作成します。
続いて、平文の先頭の文字「T」と鍵の先頭の文字「W」を取り上げます。ヴィジュネル暗号表において「T」の行と「W」の列が交差する位置にあるアルファベット「P」が、暗号文の最初の文字となります。
この操作を、平文の残りのすべての文字についても同様に繰り返します。
最終的に得られる暗号文は以下の通りです。
暗号文:PLTUWEXQXZTWMPOTZKBF
暗号文は、次の数式によって生成できます。
Ei = (Pi + Ki) mod 26
ここで、Pは平文、Kは鍵を表します。
復号化の流れ
鍵:WELCOME
暗号文:PLTUWEXQXZTWMPOTZKBF
作成済みの鍵と暗号文の先頭の文字、すなわち「P」と「W」を取り上げます。ヴィジュネル暗号表の「W」の列から「P」を探し、その位置に対応する行の先頭にあるアルファベット「T」が、元の平文の最初の文字となります。
この手順を、暗号文のすべての文字に対して繰り返します。
復号された平文:Thisistutorialspoint
復号化は、次の代数式で表すことができます。
Pi = (Ei − Ki + 26) mod 26
以下は、ヴィジュネル暗号をC++で実装したプログラムです。
アルゴリズム
Begin Function encryption(string t) for i = 0, j = 0 to t.length() - 1 char c = t[i] if (c >= 'a' and c <= 'z') c = c + 'A' - 'a' else if (c < 'A' or c > 'Z') continue output = output + (c + k[j] ) % 26 + 'A' j = (j + 1) % k.length() return output End Begin Function decryption(string t) for i = 0, j = 0 to t.length() - 1 char c = t[i] if (c >= 'a' and c <= 'z') c = c + 'A' - 'a' else if (c < 'A' or c > 'Z') continue output = output + (c - k[j] + 26) % 26 + 'A' j = (j + 1) % k.length() return output End
サンプルコード
#include <iostream>
#include <string>
using namespace std;
class Vig {
public:
string k;
Vig(string k) {
for (int i = 0; i < k.size(); ++i) {
if (k[i] >= 'A' && k[i] <= 'Z')
this->k += k[i];
else if (k[i] >= 'a' && k[i] <= 'z')
this->k += k[i] + 'A' - 'a';
}
}
string encryption(string t) {
string output;
for (int i = 0, j = 0; i < t.length(); ++i) {
char c = t[i];
if (c >= 'a' && c <= 'z')
c += 'A' - 'a';
else if (c < 'A' || c > 'Z')
continue;
output += (c + k[j] - 2 * 'A') % 26 + 'A'; //added 'A' to bring it in range of ASCII alphabet [ 65-90 | A-Z ]
j = (j + 1) % k.length();
}
return output;
}
string decryption(string t) {
string output;
for (int i = 0, j = 0; i < t.length(); ++i) {
char c = t[i];
if (c >= 'a' && c <= 'z')
c += 'A' - 'a';
else if (c < 'A' || c > 'Z')
continue;
output += (c - k[j] + 26) % 26 + 'A';//added 'A' to bring it in range of ASCII alphabet [ 65-90 | A-Z ]
j = (j + 1) % k.length();
}
return output;
}
};
int main() {
Vig v("WELCOME");
string ori ="Thisistutorialspoint";
string encrypt = v.encryption(ori);
string decrypt = v.decryption(encrypt);
cout << "Original Message: "<<ori<< endl;
cout << "Encrypted Message: " << encrypt << endl;
cout << "Decrypted Message: " << decrypt << endl;
}
実行結果
Original Message: Thisistutorialspoint Encrypted Message: PLTUWEXQXZTWMPOTZKBF Decrypted Message: THISISTUTORIALSPOINT
実装のポイント
- 小文字は処理の前にすべて大文字へ変換されます。
- アルファベット以外の文字(空白や記号など)はスキップされ、その間は鍵のインデックスも進みません。
- 演算結果に「A」の文字コードを加算することで、計算結果がASCIIコードのA〜Z(65〜90)の範囲に収まるように調整しています。
- 復号時は負の値にならないよう、26を足してからmod 26を取る点がポイントです。
-
C++でAVL木(AVLツリー)を実装する方法:回転操作とサンプルコードを徹底解説
AVL木とは AVL木(AVL Tree)は、自己平衡型二分探索木(Self-balancing Binary Search Tree)の一種です。すべてのノードにおいて、左部分木と右部分木の高さの差が「1以下」に保たれるという性質を持っています。この平衡条件により、木が片側に偏って成長することを防ぎ、検索・挿入・削除といった操作を常に効率的(O(log n))に行うことができます。 木の回転(Tree Rotation)とは 木の回転とは、要素の順序(ソート順)を崩すことなく木の構造を変更する操作のことです。あるノードを一段上へ移動させ、別のノードを一段下へ移動させることで実現されます。 回
-
【C++】STLのset_symmetric_differenceで集合の対称差を実装するプログラム
本記事では、C++の標準テンプレートライブラリ(STL)に含まれる set_symmetric_difference 関数を使って、2つの集合の「対称差」を求めるプログラムを紹介します。 対称差とは、2つの集合のうち「どちらか一方にだけ存在し、両方には存在しない」要素から構成される集合のことです。 主な集合演算の種類 和集合(Union):どちらか一方に含まれるすべての要素 積集合(Intersection):両方に共通して含まれる要素 対称差(Symmetric Difference / 排他的論理和 XOR):片方にのみ含まれる要素 差集合(Difference / 減算):一方から他方