Единозначный парный шифр на js
В единозначном шифре каждому знаку ключа соответствует одна определенная буква. В связи с тем, что ключ должен быть легким для запоминания, чистая форма единозначного шифра совершенно не употребительна. Зато в большом ходу его упрощенная модуляция – парный единозначный шифр.
Представим себе фразу из 17 различных букв, т.е. половины азбуки. Оставшиеся 17 букв подпишем под этой фразой в алфавитном порядке.
Например, ключ:

Каждая верхняя буква с лежащей под ней нижней составляет пару, в которой одна буква взаимозамещает другую. Хочу попросить совета. Каким способом лучше осуществить данный шифр на JS? Использовать объекты (ключ - значение), двумерные массивы с парами букв или может есть иные советы по данному поводу? Буду благодарен любому ответу. Так же был бы рад некоему алгоритму решения.
Ответы (2 шт):
Для такого лучше использовать объекты:
const crypt = {
'a': 'b',
'Q': 'S'
....
}
Затем можно обращаться как к Object.values(), так и к Object.entries(), что упростит решение данной задачи.
Во всех вариантах используется возможность передать в метод replace вторым параметром функцию, управляющую этими заменами. Она может принимать четыре параметра. Здесь принимается один - m - match - совпадающий символ. Функция должна возвращать подстроку для замены совпадающего символа. Подстрока берется из объекта secret по key == m или по соответствию двух массивов через индекс.
Как вариант:
// Получаем полноценные массивы из строк, составляющих алфавит и ряда символов, соответствующих каждой букве этого алфавита
// Для простоты сместил секретные символы на один и все, но можно как угодно
let alphabet = [...'АБВГДЕЁЖЗИЙКЛМНОПРСУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя'];
let shifr = [...'БВГДЕЁЖЗИЙКЛМНОПРСУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюяA'];
let secret = {}; // Объявляем объект, где будем хранить соответствия
// Наполняем объект secret парами ключ: значение (можно и `reduce` использовать, но я с ним не дружу))))
alphabet.forEach((a,i) => {
secret[a] = shifr[i];
})
str = 'Железный шприц дома'; // Строка для обработки
// Функция для передачи в качестве второго параметра `String.prototype.replace()`
function howTo(m){
return secret[m]; // Возвращает значение ключа `m` в объекте `secret`
}
// Ищем все буквы русского алфавита и вызываем функцию `howTo` для каждого случая (флаг `g`)
str = str.replace(/[а-яёА-ЯЁ]/g, howTo);
console.log(str);
Сокращенный вариант(кроме подготовки secret):
let alphabet = [...'АБВГДЕЁЖЗИЙКЛМНОПРСУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя'];
let shifr = [...'БВГДЕЁЖЗИЙКЛМНОПРСУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюяA'];
let secret = {};
alphabet.forEach((a,i) => {
secret[a] = shifr[i];
})
str = 'Железный шприц дома'.replace(/[а-яёА-ЯЁ]/g, m => secret[m]);
console.log(str);
Можно и не формируя объект:
let alphabet = [...'АБВГДЕЁЖЗИЙКЛМНОПРСУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя'];
let shifr = [...'БВГДЕЁЖЗИЙКЛМНОПРСУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюяA'];
str = 'Железный шприц дома'.replace(/[а-яёА-ЯЁ]/g, m => shifr[alphabet.indexOf(m)]);
console.log(str);
Если вопрос с ключом вызывает сложности:
let kluch = 'желёзныйшпицъдома';
function encrypt(kluch, str){
let alphabet = [...'абвгдеёжзиiклмнопрстуфхцчшщъыьэюя'].filter(s => !kluch.includes(s));
let key = [...kluch, ...alphabet];
let anti = [...alphabet, ...kluch];
str = str.replace(/[а-яё]/gi, m => anti[key.indexOf(m.toLowerCase())]);
return str;
}
console.log(encrypt(kluch, 'Не знаю, получится разглядеть?'));
console.log(encrypt(kluch, encrypt(kluch, 'Не знаю, получится разглядеть?'))); // Может так?..
console.log(encrypt(kluch, 'Если: железный шпицъ дома'));