Transpoziční šifra a C#

Co je Transpoziční šifra?
Transpoziční šifra je klasická šifra, která nemění písmena textu, ale mění jejich pořadí. Na rozdíl od substitučních šifer, kde se písmena nahrazují jinými znaky, transpoziční šifra zachovává stejná písmena, jen je přeskupuje podle určitého pravidla. Tento typ šifry byl hojně používán v historii, například při vojenské komunikaci.
Princip Transpoziční šifry
- Výběr klíče – klíč určuje, jak budou písmena přeskupena. Nejčastěji se používá číslicový klíč, který určuje pořadí sloupců.
- Rozdělení textu – text se rozdělí do tabulky podle délky klíče. Například pro klíč 4 a text HELLO WORLD vznikne tabulka:
H E L L O W O R L D X
(přidáno X pro doplnění bloku, aby tabulka byla úplná)
- Přečtení podle klíče – písmena se čtou ve sloupcích podle pořadí klíče. Pokud je klíč např. 3-1-4-2, přečte se sloupec 3, pak 1, pak 4, pak 2.
- Výsledný šifrovaný text – skládá se z písmen přečtených podle pořadí sloupců.
Bezpečnost Transpoziční šifry
Transpoziční šifra byla historicky považována za poměrně silnou, pokud útočník neznal klíč. Její bezpečnost závisí na délce klíče a způsobu přeskupení písmen. Moderní metody kombinují transpoziční šifry se substitučními, aby vznikly složitější šifry. Samotná jednoduchá transpoziční šifra je dnes snadno prolomitelná pomocí analýzy písmen a délky slov.
Příklad šifrování slova HELLO
Použijeme klíč 3-1-4-2 a doplníme text X pro úplnost:
Text: HELLO → doplněno na HELLOXXX
Tabulka:
H E L L O X X X
Čtení podle klíče 3-1-4-2:
- Sloupec 3 → L X
- Sloupec 1 → H O
- Sloupec 4 → L X
- Sloupec 2 → E X
Výsledek: LXHOLXEX
Implementace Transpoziční šifry v C#
using System;
using System.Text;
namespace TranspositionCipher;
internal class Program
{
private static string Encrypt(string plaintext, int[] key)
{
plaintext = Normalize(plaintext);
var cols = key.Length;
var rows = (int)Math.Ceiling((double)plaintext.Length / cols);
var table = new char[rows, cols];
var index = 0;
for (var r = 0; r < rows; r++)
{
for (var c = 0; c < cols; c++)
{
table[r, c] = index < plaintext.Length ? plaintext[index++] : 'X';
}
}
var sb = new StringBuilder(rows * cols);
foreach (var k in key)
{
var col = k - 1;
for (var r = 0; r < rows; r++)
{
sb.Append(table[r, col]);
}
}
return sb.ToString();
}
private static string Decrypt(string ciphertext, int[] key)
{
ciphertext = Normalize(ciphertext);
var cols = key.Length;
var rows = ciphertext.Length / cols;
if (ciphertext.Length % cols != 0)
throw new ArgumentException("Ciphertext length invalid for given key.");
var table = new char[rows, cols];
var index = 0;
foreach (var k in key)
{
var col = k - 1;
for (var r = 0; r < rows; r++)
{
table[r, col] = ciphertext[index++];
}
}
var sb = new StringBuilder(rows * cols);
for (var r = 0; r < rows; r++)
{
for (var c = 0; c < cols; c++)
{
sb.Append(table[r, c]);
}
}
return TrimPadding(sb.ToString());
}
private static string Normalize(string text)
{
var sb = new StringBuilder(text.Length);
foreach (var ch in text.ToUpperInvariant())
{
if (ch >= 'A' && ch <= 'Z')
sb.Append(ch);
}
return sb.ToString();
}
private static string TrimPadding(string text)
{
var end = text.Length;
while (end > 0 && text[end - 1] == 'X')
end--;
return text.Substring(0, end);
}
private static bool IsValidKey(int[] key, out string reason)
{
reason = string.Empty;
if (key.Length == 0)
{
reason = "Key empty.";
return false;
}
var seen = new bool[key.Length];
foreach (var k in key)
{
if (k < 1 || k > key.Length)
{
reason = "Key values must be in range 1..N.";
return false;
}
if (seen[k - 1])
{
reason = "Duplicate values in key.";
return false;
}
seen[k - 1] = true;
}
return true;
}
private static void Main(string[] args)
{
var original = "HELLO";
int[] key = { 3, 1, 4, 2 };
if (!IsValidKey(key, out var reason))
{
Console.WriteLine($"Invalid key: {reason}");
return;
}
var encrypted = Encrypt(original, key);
var decrypted = Decrypt(encrypted, key);
Console.WriteLine($"Original: {original}");
Console.WriteLine($"Encrypted: {encrypted}");
Console.WriteLine($"Decrypted: {decrypted}");
}
}
Závěr
Transpoziční šifra ukazuje, že i pouhé přeskupení písmen může vytvořit čitelně nezrozumitelný text. Její jednoduchost ji činí snadno pochopitelnou a výbornou pro studium základů kryptografie. Přesto samotná není bezpečná pro moderní použití a často se kombinuje s dalšími šifrovacími technikami pro zvýšení odolnosti vůči kryptoanalýze.