Я углубляю свое понимание криптографии. Хотя мне, вероятно, следовало начать это 20 лет назад (или даже в 2014 году, когда Bit Coin начала шуметь), сейчас самое время продолжать учиться. Один из текстов, который я выбрал для начала, - Понимание криптографии. План состоит в том, чтобы запачкать руки и написать код вместе с текстом (чтобы доказать себе минимальную компетентность). Мое любимое оружие (в течение последних трех лет) - JavaScript - и хотя он отвечал задаче первого шифра, не обошлось без проблем.
Алгоритм берет алфавит, смещение и текст и заменяет каждый символ в тексте значением из алфавита, сдвинутым на количество символов в смещении. Если смещение проходит мимо конца алфавита, оно возвращается к началу. Чтобы зашифровать, мы берем символ и находим его числовое значение (назовем это x), добавляем к нему смещение (назовем это k) и модуль деления на количество символов в алфавите (назовем это m). Следовательно
encrypt(x) = (x + k) mod m
Расшифровка аналогична
decrypt(x) = (x - k) mod m
Тривиальность решения (которую я сначала подтвердил моделированием в Excel) разлетелась на части через 10 минут после начала упражнения, и оказалось, что есть некоторая двусмысленность по модулю в отношении отрицательных чисел. Есть две реализации, и если вы не используете правильную, ничего не пойдет. Как оказалось, оператор по модулю javascript не является правильной реализацией для этого варианта использования. Поскольку это был первый раз, когда я столкнулся с этой странностью по модулю, потребовалось некоторое исследование, чтобы решить (спасибо Википедии). Я определил свою собственную функцию по модулю:
const quotient = (dividend,divisor) => Math.floor(dividend/divisor) const floor_modulo = (dividend,divisor) => dividend - divisor * quotient(dividend,divisor)
с множеством других помощников (чтобы мой алгоритм легко читался) я получил следующее решение:
const {reduce, pipe, curry, find} = require('../helpers/functional-bits') const {maxOr, increment, appendToObj, appendToArray, join, length, floor_modulo, numberOfKeys, values} = require('../helpers/common-bits') const maxOrNegOne = maxOr(-1) const alphabet = 'abcdefghijklmnopqrstuvwxyz' // arrayToAlphabetMap :: [k] -> {k: Number} const arrayToAlphabetMap = reduce( (map, a) => appendToObj(map, a, getNextValue(map)), {} ) // getNextValue :: {character: Number} -> Number const getNextValue = pipe([ values, maxOrNegOne, increment ]) // enryptCharacter :: ({character: Number} -> Number -> Number -> // character -> character) -> {character: Number} -> Number -> // Number -> [character] -> [character] const applyWith = curry((algo, alphabetMap, k, m, xs) => reduce( (arr, x) => appendToArray( arr, algo(alphabetMap, k, m, x)) ,[] , xs ) ) // enryptCharacter :: {character: Number} -> Number -> Number -> // character -> character const encryptCharacter = curry((alphabetMap, k, m, x) => { const rawValue = alphabetMap[x] const shiftValue = floor_modulo((rawValue + k), m) const shiftCharacter = find(alphabetMap, shiftValue) return shiftCharacter }) // decryptCharacter :: {character: Number} -> Number -> Number -> // character -> character const decryptCharacter = curry((alphabetMap, k, m, x) => { const shiftValue = alphabetMap[x] const rawValue = floor_modulo((shiftValue - k), m) const rawCharacter = find(alphabetMap, rawValue) return rawCharacter }) // shiftCipher :: string, Number -> // { encrypt :: string -> string, decrypt :: string -> string } const shiftCipher = (alphabet, k) => { const alphabetArray = alphabet.split('') const alphabetMap = arrayToAlphabetMap(alphabetArray) const m = numberOfKeys(alphabetMap) return { encrypt: pipe([ applyWith(encryptCharacter, alphabetMap, k, m), join ]), decrypt: pipe([ applyWith(decryptCharacter, alphabetMap, k, m), join ]), } } const raw = 'attack' const cipher = shiftCipher(alphabet, 17) const secret = cipher.encrypt(raw) //=> rkkrtb const raw2 = cipher.decrypt(secret) //=> attack
Обратите внимание: сопротивляйтесь зуду - это небезопасный криптографический алгоритм. Но, пожалуйста, поиграйте с кодом (его можно найти здесь). Также есть код? Я хотел бы получить известие от вас - напишите мне!
Обо мне
Первоначально опубликовано на https://www.linkedin.com.