Vigenère cipher (tsz. Vigenère ciphers)
A Vigenère-rejtjel egy klasszikus, polialfabetikus titkosítási eljárás, amelyet a 16. században fejlesztettek ki. Az egyszerű Caesar-kódhoz képest fejlettebb és biztonságosabb, mivel nem egyetlen eltolást alkalmaz az üzenet minden betűjére, hanem egy kulcsszó segítségével különböző eltolásokat használ az egyes karakterek kódolására. Ez a módszer évszázadokon át „feltörhetetlennek” számított, mígnem a 19. században sikeresen visszafejtették.
A titkosítás a következő lépéseken alapul:
A Vigenère-rejtjel a 26 betűs latin ábécét használja. Az eltolásokat egy speciális Vigenère-táblázat segítségével határozzuk meg. Ez egy 26 sorból és 26 oszlopból álló táblázat, amely minden sorban egy újabb eltolással tartalmazza az ábécét.
Az üzenet titkosításához egy kulcsszóra van szükség. Ezt a kulcsszót folyamatosan ismételjük az üzenet hosszának megfelelően.
Tegyük fel, hogy a titkosítandó szöveg: „TITKOSUZENET”, és a kulcsszó: „KULCS”.
Ismételjük meg a kulcsszót:
TITKOSUZENET KULCSKULCSKU
Titkosítás a Vigenère-tábla szerint:
Az így kapott titkosított szöveg: „DCEMG…”.
A Vigenère-rejtjelet gyakran Blaise de Vigenère francia diplomata nevéhez kötik, azonban valójában Giovan Battista Bellaso olasz kriptográfus találta fel 1553-ban. Vigenère egy fejlettebb változatot dolgozott ki később, amely egy még összetettebb módszert alkalmazott.
A módszer évszázadokon át „feltörhetetlen” titkosításként volt ismert, mígnem a 19. század közepén Friedrich Kasiszki német katonatiszt felfedezte, hogy ha a kulcs elég rövid és ismétlődő, akkor az üzenet statisztikai módszerekkel visszafejthető. A módszert később William F. Friedman tovább tökéletesítette, megteremtve a modern kriptoanalízis alapjait.
A rejtjel feltörésére két fő módszert dolgoztak ki:
Ha a kulcs rövid és ismétlődik, akkor az azonos titkosított betűkombinációk statisztikai módszerekkel kimutathatók.
Ha a kulcs ismert vagy elég rövid, akkor az egyes betűk gyakoriságának vizsgálatával visszafejthető a kódolt szöveg.
Bár a Vigenère-rejtjel ma már nem tekinthető biztonságosnak, történelmi jelentősége nagy. Az elvét a modern szimmetrikus kulcsú titkosításokban továbbfejlesztették, és a számítógépes kriptográfia fejlődésében is szerepet játszott.
A Vigenère-elv tovább él például az OTP (One-Time Pad) titkosításban, amely elméletileg feltörhetetlen, ha a kulcs teljesen véletlenszerű és egyszer használatos.
A Vigenère-rejtjel egy fontos történelmi titkosítási módszer, amely a Caesar-kódhoz képest jelentős fejlesztés volt. Bár a 19. században feltörték, és ma már nem számít biztonságosnak, a modern kriptográfia egyik előfutárának tekinthető.
BEGIN // Load the Vigenère Table FUNCTION LoadVigenereTable(filename) OPEN FILE filename FOR READING FOR i FROM 0 TO 25 DO FOR j FROM 0 TO 25 DO READ FILE INTO VigenereTable END FOR READ NEW LINE END FOR CLOSE FILE END FUNCTION // Normalize the text (remove accents, convert to uppercase, filter only letters) FUNCTION NormalizeText(text) DECLARE result AS STRING DECLARE accent_map AS DICTIONARY accent_map = {'Á':'A', 'É':'E', 'Í':'I', 'Ó':'O', 'Ö':'O', 'Ő':'O', 'Ú':'U', 'Ü':'U', 'Ű':'U', 'á':'a', 'é':'e', 'í':'i', 'ó':'o', 'ö':'o', 'ő':'o', 'ú':'u', 'ü':'u', 'ű':'u'} FOR EACH CHARACTER c IN text DO IF c IN accent_map THEN c = accent_map END IF IF c IS ALPHABETIC THEN result = result + TO_UPPERCASE(c) END IF END FOR RETURN result END FUNCTION // Extend the key to match the length of the text FUNCTION ExtendKey(key, length) DECLARE extended_key AS STRING FOR i FROM 0 TO length-1 DO extended_key = extended_key + key END FOR RETURN extended_key END FUNCTION // Encrypt text using the Vigenère cipher FUNCTION Encrypt(plaintext, key) DECLARE ciphertext AS STRING DECLARE processedText AS STRING processedText = NormalizeText(plaintext) DECLARE extendedKey AS STRING extendedKey = ExtendKey(key, LENGTH(processedText)) FOR i FROM 0 TO LENGTH(processedText)-1 DO DECLARE row AS INTEGER DECLARE col AS INTEGER row = ASCII_VALUE(processedText) - ASCII_VALUE('A') col = ASCII_VALUE(extendedKey) - ASCII_VALUE('A') ciphertext = ciphertext + VigenereTable END FOR RETURN ciphertext END FUNCTION // Write encrypted text to file FUNCTION WriteToFile(filename, content) OPEN FILE filename FOR WRITING WRITE content TO FILE CLOSE FILE END FUNCTION // Main program execution PROCEDURE MAIN CALL LoadVigenereTable("Vtabla.dat") PRINT "Enter text to encode: " READ plaintext PRINT "Enter a key (max 5 characters): " READ key key = NormalizeText(key) DECLARE encryptedText AS STRING encryptedText = Encrypt(plaintext, key) PRINT "Encoded text: " + encryptedText CALL WriteToFile("kodolt.dat", encryptedText) END PROCEDURE END
#include <iostream>
#include <fstream>
#include <vector>
#include <cwctype> // For towupper() in wide characters
#include <string>
#include <unordered_map>
using namespace std;
const int ALPHA_SIZE = 26;
vector<vector<wchar_t>> VigenereTable(ALPHA_SIZE, vector<wchar_t>(ALPHA_SIZE));
// Function to load Vigenère table from a file
void LoadVigenereTable(const string &filename) {
wifstream file(filename);
file.imbue(locale("")); // Enable wide character support
if (!file) {
wcerr << L"Error: Could not open " << filename.c_str() << endl;
exit(1);
}
for (int i = 0; i < ALPHA_SIZE; ++i) {
for (int j = 0; j < ALPHA_SIZE; ++j) {
file >> VigenereTable;
}
}
file.close();
}
// Function to normalize text: remove accents and convert to uppercase
wstring NormalizeText(const wstring &text) {
wstring result;
unordered_map<wchar_t, wchar_t> accents = {
{L'Á', L'A'}, {L'É', L'E'}, {L'Í', L'I'}, {L'Ó', L'O'}, {L'Ö', L'O'}, {L'Ő', L'O'},
{L'Ú', L'U'}, {L'Ü', L'U'}, {L'Ű', L'U'}, {L'á', L'a'}, {L'é', L'e'}, {L'í', L'i'},
{L'ó', L'o'}, {L'ö', L'o'}, {L'ő', L'o'}, {L'ú', L'u'}, {L'ü', L'u'}, {L'ű', L'u'}
};
for (wchar_t c : text) {
if (accents.find(c) != accents.end()) {
c = accents; // Replace accented character
}
if (iswalpha(c)) { // Ensure valid characters
result += towupper(c); // Use towupper for wide characters
}
}
return result;
}
// Function to extend the key to match the text length
wstring ExtendKey(const wstring &key, int length) {
if (key.empty()) {
wcerr << L"Error: Key cannot be empty!" << endl;
exit(1);
}
wstring extendedKey;
for (int i = 0; i < length; ++i) {
extendedKey += key;
}
return extendedKey;
}
// Function to encrypt text using the Vigenère cipher
wstring Encrypt(const wstring &text, const wstring &key) {
wstring ciphertext;
wstring processedText = NormalizeText(text);
wstring extendedKey = ExtendKey(key, processedText.size());
for (size_t i = 0; i < processedText.size(); ++i) {
wchar_t row = processedText;
wchar_t col = extendedKey;
if (row < L'A' || row > L'Z' || col < L'A' || col > L'Z') { // Ensure valid table lookups
wcerr << L"Error: Invalid character found in text or key." << endl;
exit(1);
}
ciphertext += VigenereTable;
}
return ciphertext;
}
// Function to write encrypted text to file
void WriteToFile(const string &filename, const wstring &content) {
wofstream file(filename);
if (!file) {
wcerr << L"Error: Could not open " << filename.c_str() << L" for writing." << endl;
exit(1);
}
file << content;
file.close();
}
// Main function
int main() {
setlocale(LC_ALL, ""); // Enable Unicode support
LoadVigenereTable("Vtabla.dat");
wstring plaintext, key;
wcout << L"Enter text to encode: ";
getline(wcin, plaintext);
wcout << L"Enter a key (max 5 characters): ";
wcin >> key;
key = NormalizeText(key);
if (key.empty() || key.length() > 5) {
wcerr << L"Error: Key must be between 1 and 5 characters!" << endl;
exit(1);
}
wstring encryptedText = Encrypt(plaintext, key);
wcout << L"Encoded text: " << encryptedText << endl;
WriteToFile("kodolt.dat", encryptedText);
return 0;
}
kodolt.dat
ABCDEFGHIJKLMNOPQRSTUVWXYZ BCDEFGHIJKLMNOPQRSTUVWXYZA CDEFGHIJKLMNOPQRSTUVWXYZAB DEFGHIJKLMNOPQRSTUVWXYZABC EFGHIJKLMNOPQRSTUVWXYZABCD FGHIJKLMNOPQRSTUVWXYZABCDE GHIJKLMNOPQRSTUVWXYZABCDEF HIJKLMNOPQRSTUVWXYZABCDEFG IJKLMNOPQRSTUVWXYZABCDEFGH JKLMNOPQRSTUVWXYZABCDEFGHI KLMNOPQRSTUVWXYZABCDEFGHIJ LMNOPQRSTUVWXYZABCDEFGHIJK MNOPQRSTUVWXYZABCDEFGHIJKL NOPQRSTUVWXYZABCDEFGHIJKLM OPQRSTUVWXYZABCDEFGHIJKLMN PQRSTUVWXYZABCDEFGHIJKLMNO QRSTUVWXYZABCDEFGHIJKLMNOP RSTUVWXYZABCDEFGHIJKLMNOPQ STUVWXYZABCDEFGHIJKLMNOPQR TUVWXYZABCDEFGHIJKLMNOPQRS UVWXYZABCDEFGHIJKLMNOPQRST VWXYZABCDEFGHIJKLMNOPQRSTU WXYZABCDEFGHIJKLMNOPQRSTUV XYZABCDEFGHIJKLMNOPQRSTUVW YZABCDEFGHIJKLMNOPQRSTUVWX ZABCDEFGHIJKLMNOPQRSTUVWXY