Цель

Наша цель здесь — написать очень простой инструмент командной строки на Javascript для шифрования и дешифрования сообщений с использованием (секретного) ключа. Мы называем наш инструмент "секретным", поскольку мы имеем дело с информацией, которую намерены скрывать и раскрывать.

Если мы хотим зашифровать сообщение «все коты серые» с помощью секретного ключа «слон», мы просто набираем:

секрет --encrypt --"все коты серые" --слон

который должен вернуть следующее зашифрованное сообщение (зашифрованный текст):

ewp ioe ptxd egl gexc

Это зашифрованное сообщение можно расшифровать с помощью того же ключевого слова через:

secret --decrypt -“ewp ioe ptxd egl gexc” -elephant

который должен вернуть наше расшифрованное сообщение (открытый текст):

все коты серые

Итак, приступим!

Шифр

Метод (или алгоритм), используемый для шифрования и дешифрования сообщения, называется шифром. Одна из классических категорий шифров называется подстановочные шифры и в основном описывает метод замены каждой буквы сообщения другой. Простейшей заменой было бы просто изменить алфавит, используемый для открытого текста, на другой для зашифрованного текста.

/* (plaintext alphabet)
/* +-----------------------------------------------------+ */
/* | A B C D E F G H I J K L M N O P Q R S T U V W X Y Z | */
/* +-----------------------------------------------------+ */
/* | L G H T Z Y K V C M O F N B P J R X D Q A U W I S E | */
/* +-----------------------------------------------------+ */
/*                                   (ciphertext alphabet) */          

Использование этого алфавита зашифрованного текста превратит наш открытый текст "все кошки серые" в зашифрованный текст "lff qvz hlqd lxz kxzs".

Шифр

Вместо использования метода алфавита зашифрованного текста мы используем метод ключевых слов (называемый шифром Виженера), который работает следующим образом.

Шифрование

Под нашим сообщением мы продолжаем повторять наше ключевое слово «слон», пока оно не будет соответствовать длине открытого текста:

/* (plaintext)
/* +-------------------------------------------+ */
/* | a l l   t h e   c a t s   a r e   g r e y | */
/* +-------------------------------------------+ */
/* | e l e   p h a   n t e l   e p h   a n t e | */
/* +-------------------------------------------+ */
/*                                    (key word) */

На следующем шаге мы ищем индекс каждой буквы в алфавите (a равно 0, z равно 25) как обычного текста, так и ключевого слова.

/* (plaintext)
/* +---------------------------------------------------+ */
/* | a  l  l   t h e   c  a  t  s   a  r e   g  r e  y | */
/* +---------------------------------------------------+ */
/* | 0 11 11  19 7 4   2  0 19 18   0 17 4   6 17 4 24 | */
/* +---------------------------------------------------+ */
                                      (alphabetic index) */
/* (keyword)                                 
/* +---------------------------------------------------+ */
/* | e  l  e   p h a   n  t  e  l   e  p h   a  n  t e | */
/* +---------------------------------------------------+ */
/* | 4 11  4  15 7 0  13 19  4 11   4 15 7   0 13 19 4 | */
/* +---------------------------------------------------+ */
/*                                    (alphabetic index) */

Затем мы добавляем оба индекса:

/* (plaintext)
/* +------------------------------------------------------+ */
/* | 0 11 11  19  7 4   2  0 19 18   0 17  4   6 17  4 24 | */
/* +------------------------------------------------------+ */                  
     +  +  +   +  + +   +  +  +  +   +  +  +   +  +  +  + 
/* +------------------------------------------------------+ */
/* | 4 11  4  15  7 0  13 19  4 11   4 15  7   0 13 19  4 | */
/* +------------------------------------------------------+ */
/*                                                (keyword) */
     =  =  =   =  = =   =  =  =  =   =  =  =   =  =  =  =
/* +------------------------------------------------------+ */
/* | 4 22 15  34 14 4  15 19 24 29   4 32 11   6 30 23 28 | */
/* +------------------------------------------------------+ */
/*                                          (added indices) */

Наконец, мы сопоставляем буквы алфавита с рассчитанными индексами.
Если индекс больше длины алфавита, мы просто берем разность (34-26=8), начинаем с начала и заканчиваем на i (8-я буква алфавита).

/* +------------------------------------------------------+ */
/* | 4 22 15   8 14 4  15 19 24 29   4  6 11   6  4 23  2 | */
/* +------------------------------------------------------+ *
/* +------------------------------------------------------+ */
/* | e  w  p   i  o e   p  t  x  d   e  g  l   g  e  x  c | */
/* +------------------------------------------------------+ */

Итак, наш окончательный зашифрованный текст: ewp ioe ptxd egl gexc.

Поместите в код, это выглядит так:

Расшифровка

Чтобы расшифровать наш зашифрованный текст, мы должны выполнить обратный процесс. Мы повторяем наше ключевое слово под зашифрованным текстом:

/* +------------------------------------------------------+ */
/* | e  w  p   i  o e   p  t  x  d   e  g  l   g  e  x  c | */
/* +------------------------------------------------------+ */
/* | e  l  e   p  h a   n  t  e  l   e  p  h   a  n  t  e | */
/* +------------------------------------------------------+ */

Мы просматриваем индекс каждого символа:

/* (ciphertext)
/* +-----------------------------------------------------+ */
/* | e  w  p   i  o e   p  t  x  d   e  g  l   g  e  x c | */
/* +-----------------------------------------------------+ */
/* | 4 22 15   8 14 4  15 19 24 29   4  6 11   6  4 23 2 | */
/* +-----------------------------------------------------+ */
                                      (alphabetic index) */
/* (keyword)                                 
/* +---------------------------------------------------+ */
/* | e  l  e   p h a   n  t  e  l   e  p h   a  n  t e | */
/* +---------------------------------------------------+ */
/* | 4 11  4  15 7 0  13 19  4 11   4 15 7   0 13 19 4 | */
/* +---------------------------------------------------+ */
/*                                    (alphabetic index) */

Затем вычтите их:

/* (plaintext)
/* +------------------------------------------------------+ */
/* | 4 22 15   8 14 4  15 19 24 29   4  6 11   6  4 23 2  | */
/* +------------------------------------------------------+ */                  
     -  -  - + +   +  +  +  +   +  +  +   +  +  +  + 
/* +------------------------------------------------------+ */
/* | 4 11  4  15  7 0  13 19  4 11   4 15  7   0 13 19  4 | */
/* +------------------------------------------------------+ */
/*                                                (keyword) */
     =  =  =   =  = =   =  =  =  =   =  =  =   =  =  =  =
/* +------------------------------------------------------+ */
/* | 0 11 11  -5 14 4  15 19 24 29   4 32 11   6 30 23 28 | */
/* +------------------------------------------------------+ */
/*                                          (added indices) */

Теперь мы добавляем 26 к каждому индексу. Если оно больше 26, мы берем разницу.

/* (plaintext)
/* +------------------------------------------------------+ */
/* | 4 22 15   8 14 4  15 19 24 29   4  6 11   6  4 23 2  | */
/* +------------------------------------------------------+ */                  
     -  -  -   -  - -   -  -+   +  +  +   +  +  +  + 
/* +------------------------------------------------------+ */
/* | 4 11  4  15  7 0  13 19  4 11   4 15  7   0 13 19  4 | */
/* +------------------------------------------------------+ */
/*            -7                                (keyword) */
             +26
     =  =  =   =  = =   =  =  =  =   =  =  =   =  =  =  =
/* +------------------------------------------------------+ */
/* | 0 11 11  19  7 4  15 19 24 29   4 32 11   6 30 23 28 | */
/* +------------------------------------------------------+ */
/*                                          (added indices) */

Если вычисленный индекс отрицательный, это означает, что мы должны идти с конца алфавита, поэтому мы добавляем 26 (-7 + 26 = 19). Если мы теперь сопоставим эти индексы с алфавитом…

/* +------------------------------------------------------+ */
/* | 0 11 11   19 7 4  15 19 24 29   4  6 11   6  4 23  2 | */
/* +------------------------------------------------------+ *
/* +------------------------------------------------------+ */
/* | a  l  l    t h e   p  t  x  d   e  g  l   g  e  x  c | */
/* +------------------------------------------------------+ */

… мы получаем обратно наш открытый текст: все коты серые.

Поместите в код, это выглядит так:

Инструмент командной строки

Поскольку нашей целью было написать инструмент командной строки, нам нужно быстро научиться создавать CLI на Javascript с помощью Node.js, используя встроенный менеджер пакетов NPM.

Сначала мы инициируем пустой пакет NPM через:

npm init

Это создаст файл package.json, который выглядит примерно так:

{
  "name": "golden-secret",
  "version": "1.0.0",
  "description": "Basic Hide & Reveal",
  "main": "index.js",
  "bin": {
    "secret": "index.js"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Florian Maxim",
  "license": "ISC"
}

Добавляя значение bin с ключевым объектом { «secret»: «index.js» }, мы сообщаем NPM, что хотим, чтобы команда «secret» была связана с index.js. Поэтому каждый раз, когда мы запускаем «secret», он будет запускать все, что находится в этом файле.

После создания файла index.js мы должны предоставить ему права на выполнение:

chmod +x index.js

Затем мы связываем команду, которую мы определили в package.json:

npm link

Параметры

Поверх нашего файла index.js нам нужно поместить следующую строку, чтобы определить среду Node.js.

#!/usr/bin/env node

(Подробнее об этом читайте здесь: https://en.wikipedia.org/wiki/Shebang_(Unix))

Итак, какая информация нам нужна? Сначала нам нужно знать, должны ли мы шифровать или расшифровывать текст (это РЕЖИМ нашей программы). Во-вторых, нам нужен сам ТЕКСТ (либо открытый текст для шифрования, либо зашифрованный текст для расшифровки). Чтобы заставить наше шифрование или дешифрование работать, мы всегда должны передавать наш KEY в качестве третьего параметра.
В Node.js параметры хранятся в объекте process.argv. Поскольку первые два ключа всегда включают «узел» и имя файла, мы начинаем с третьего аргумента ([2]).

Все вместе

Наконец, мы включаем наши функции encrypt и decrypt, указанные выше, и вызываем их в соответствии с переданным аргументом MODE (сокращение «E» или «encrypt ” зашифровывает, “d” или расшифровывает наоборот.).

Если вы сейчас наберете:

secret -E -"all the cats are grey" -"elephant"

вы должны получить наш зашифрованный текст ранее:

ewp ioe ptxd egl gexc

И наоборот:

secret -D -"ewp ioe ptxd egl gexc" -"elephant"

напечатает наш исходный открытый текст:

все коты серые

Если вы считаете, что все кошки золотые, оставьте комментарий ниже, если вам понравился или не понравился этот текст каким-либо образом. Я всегда рад стать лучше и услышать ваши мысли!

Код:

Полный код можно найти здесь:

https://github.com/florianmaxim/gold-secret

В качестве альтернативы его можно установить с помощью NPM:

npm install golden-secret

Ресурсы:

https://www.youtube.com/watch?v=ez0AOYl-i4k

https://en.wikipedia.org/wiki/Cipher
https://en.wikipedia.org/wiki/Substitution_cipher
https://en.wikipedia.org/ wiki/Полиалфавитный_шифр