Шифр Гронсфельда — полиалфавитный подстановочный шифр создан графом Гронсвельдом (руководителем первой дешифровальной службы Германии) в 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' ), "- дешифрование строчных - без алфавита" );