Шифр Гронсфельда
Шифр Гронсфельда — полиалфавитный подстановочный шифр создан графом Гронсвельдом (руководителем первой дешифровальной службы Германии) в XVII веке. Шифр можно считать усовершенствованием шифра Цезаря (надежность) и Виженера / Бофора (скорость).
Описание
[править | править код]Ключ
[править | править код]Длина ключа (K) должна быть равной длине исходного текста. Для этого циклически записывают ключ до тех пор, пока его длина не будет соответствовать длине исходного текста.
Шифрование
[править | править код]Каждый символ Mi открытого текста M нужно на Ki (соответствующий символ ключа K) шагов сдвинуть вправо.
Или пользуясь таблицей Гронсфельда (Tx y, где x — номер строки, а y — номер столбца и отсчет ведется с нуля):
каждый символ Ci шифротекста C находится на пересечении столбца y, первый (заголовочный) символ которого равен соответствующему символу открытого текста Mi, и Ki-й (соответствующей цифры ключа) строки — (TKi y)
Дешифрование
[править | править код]Каждый символ (Ci) зашифрованного текста C нужно на Ki (соответствующий символ ключа K) шагов сдвинуть влево.
Или пользуясь таблицей Гронсфельда (Tx y, где x — номер строки, а y — номер столбца и отсчет ведется с нуля):
нужно в Ki (i-ая цифра ключа K) строке найти символ, который равен соответствующему символу шифротекста (TKi y = Ci), и первый (заголовочный) элемент столбца будет i-ый символ открытого текста.
Пример
[править | править код]Пусть дан исходный текст: M = «GRONSFELD»
и ключ: K = «2015»
Ключ
[править | править код]Длина слова — 9 символов, значит и длина ключа также должна равнятся 9 символам.
K = «201520152»
Шифрование
[править | править код]- M1 = «G».
- y = 6 (y — номер столбца)
- K1 = 2
- С1 = T2 6 = «I»
C += «I» (C = «I»)
- M2 = «R».
- y = 17
- K2 = 0
- С2 = T0 17 = «R»
C += «R» (C = «IR»)
. . . . . . . . .
- M9 = «D»
- y = 3
- K9 = 2
- С9 = T2 3 = «F»
C += «F» (C = «IRPSUFFQF»)
Шифротекст (C) — «IRPSUFFQF»
Дешифрование
[править | править код]- C1 = «I».
- x = K1 = 2
- y = 6 (y — индекс встречи Cn на x строке)
- M += «G» (M = «G»)
- C2 = «R»
- x = K2 = 0
- y = 17
- M += «R» (M = «GR»)
. . . . . . . . .
- C9 = «F»
- x = K9 = 2
- y = 3
- M += «D» (M = «GRONSFELD»)
Дешифрованный текст (M) — «GRONSFELD»
Реализация
[править | править код]Python
[править | править код]A = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' * 2 # алфавит
def f(text, k, op):
k *= len(text) // len(k) + 1
text = text.upper()
return ''.join([A[A.index(j) + int(k[i]) * op] for i, j in enumerate(text)])
def encrypt(message, key):
return f(message, key, 1)
def decrypt(ciphertext, key):
return f(ciphertext, key, -1)
print(encrypt('GRONSFELD', '2015')) # шифрование
print(decrypt('IRPSUFFQF', '2015')) # расшифровывание
C#
[править | править код]string key = "2015", text = "gronsfeld";
string abc = "abcdefghijklmnopqrstuvwxyz", newKey = key, result = "";
bool encode = true;
int op = encode ? +1 : -1, offset, indexOf = 0;
while (newKey.Length < text.Length)
{
newKey += key;
}
if (newKey.Length > text.Length)
{
newKey = newKey.Substring(0, newKey.Length - (newKey.Length - text.Length));
}
for (int i = 0; i < text.Length; i++)
{
indexOf = abc.IndexOf(text[i]);
if (indexOf != -1)
{
offset = abc.IndexOf(text[i]) + (Convert.ToInt32(newKey[i]) - 48) * op;
if (offset >= abc.Length)
offset = offset - abc.Length;
else if (offset < 0)
offset = abc.Length + offset;
result += abc[offset];
} else
result += text[i];
}
JavaScript
[править | править код]//Этот код работает в консоли браузера, если его скопировать и вставить туда.
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; //Строка алфавита
//Одна функция из двух отсюда: https://codepen.io/the405/pen/ZOxwrr
function Gronsfeld(m, key, mode, a) {
//Шифр Гронсфельда - шифрование/дешифрование
// m - сообщение или шифртекст;
// key - ключ,
// a - строка с алфавитом
// mode - режим. "encrypt" (по умолчанию), "decrypt" - для дешифрования.
var result = ""; //пустая строка результата, для заполнения.
for (var i = 0; i < m.length; ++i) {//для каждой буквы сообщения/шифротекста
if(typeof a !== 'undefined'){ //если указан алфавит - шифруем/дешифруем этим коротким кодом
var ki = parseInt(key[( (i>=key.length) ? i % key.length : i)]); //подгоняем ключ
ki = (mode === 'decrypt') ? -ki : ki; //-k[i] при дешифровании
//шифрование: ( m[i] + k[i] ), дешифрование: ( m[i] - k[i] ) = ( m[i] + (-k[i]) )
result += a[ ( ( a.indexOf( m[i] ) + ki ) ) ];
}else{ //если алфавит не указан, попробуем шифрование/дешифрование - по коду символов
var c = m[i].charCodeAt(0); //код i-того символа текста/шифртекста
var counter = ( (i>=key.length) ? i% key.length : i );
if((typeof mode === 'undefined') || mode==='encrypt'){
if (c >= 97 && (parseInt(c) + parseInt(key[counter])) > 122) { // строчные
result += String.fromCharCode(
parseInt(96) + parseInt((parseInt(c) + parseInt(key[counter]) - parseInt(122)))
);
} else if (c <= 90 && (parseInt(c) + parseInt(key[counter])) > 90) { // прописные
result += String.fromCharCode(
parseInt(64) + parseInt((parseInt(c) + parseInt(key[counter]) - parseInt(90)))
);
} else { //иначе - сдвиг символа
result += String.fromCharCode(parseInt(c) + parseInt(key[counter]));
}
}else if( mode === 'decrypt' ){
if (c >= 65 && c <= 90) { // прописные
if ((parseInt(c) - parseInt(key[counter])) < 65) {
result += String.fromCharCode(
parseInt(91) - parseInt((parseInt(65) - (parseInt(c) - parseInt(key[counter]))))
);
}
else {
result += String.fromCharCode(parseInt(c) - parseInt(key[counter]));
}
} else if (c >= 97 && c <= 122) { // строчные
if ((parseInt(c) - parseInt(key[counter])) < 97) {
result += String.fromCharCode(
parseInt(123) - parseInt((parseInt(97) - (parseInt(c) - parseInt(key[counter]))))
);
}
else {
result += String.fromCharCode(parseInt(c) - parseInt(key[counter]));
}
}else { //иначе - просто символ
result += String.fromCharCode(c);
}
}
}
}
return result; //возврат строки шифротекста/текста.
}
//Тест
// # шифрование - c указанным алфавитом
console.log( Gronsfeld( 'GRONSFELD', '2015', 'encrypt', alphabet ), "- шифрование с алфавитом" );
// # расшифровывание - с указанным алфавитом
console.log( Gronsfeld( 'IRPSUFFQF', '2015', 'decrypt', alphabet ), "- дешифрование с алфавитом" );
// # шифрование - по умолчанию, без алфавита и без указания 'encrypt'
console.log( Gronsfeld( 'GRONSFELD', '2015' ), "- шифрование без алфавита и указания 'encrypt'" );
// # успешное расшифровывание - без алфавита
console.log( Gronsfeld( 'IRPSUFFQF', '2015', 'decrypt' ), "- дешифрование без алфавита" );
// # шифрование - без алфавита, с маленькими буквами
console.log( Gronsfeld( 'gronsfeld', '2015', 'encrypt' ), "- шифрование строчных - без алфавита" );
// # расшифровывание - без алфавита, с маленькими буквами.
console.log( Gronsfeld( 'irpsuffqf', '2015', 'decrypt' ), "- дешифрование строчных - без алфавита" );