Объясняя функции шифра Vigenère - PullRequest
0 голосов
/ 24 февраля 2019

Я нашел следующий код в http://rosettacode.org для шифра Vigenère, и я хотел бы понять его лучше.

Может кто-нибудь объяснить мне, что такое отдельные строки кода в function ordA(a) и вfunction(a) до?

function ordA(a) {
  return a.charCodeAt(0) - 65;
}

// vigenere
function vigenere2(text, key, decode) {
  var i = 0, b;
  key = key.toUpperCase().replace(/[^A-Z]/g, '');
  return text.toUpperCase().replace(/[^A-Z]/g, '').replace(/[A-Z]/g, function(a) {
    b = key[i++ % key.length];
    return String.fromCharCode(((ordA(a) + (decode ? 26 - ordA(b) : ordA(b))) % 26 + 65));
  });
}

1 Ответ

0 голосов
/ 25 февраля 2019

Я не уверен, должен ли это быть пример кода, но в основном это показывает, как не программировать.Разумные решения принимаются , но очевидно, что разложение проблемы, именование переменных и документация оставляют желать лучшего.Повторный код, извилистые строки, необъяснимые фрагменты кода, этот список можно продолжить.Декодирование является логическим значением, но противоположностью шифрования является расшифровка , а не декодирование.Этот код был сделан, чтобы не понимал, что происходит;то, что он делает на сайте Rosetta, ошеломляет в этом отношении.


возвращает индекс в английском алфавите или ABC, принимая заглавные буквы, от 0 до 25 вместо 1 до 26 (потому что вы можетевыполнять модульные вычисления с нулевым индексированием, а не с одним индексированием на основе)

return a.charCodeAt(0) - 65;

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

function vigenere2(text, key, decode) 

индекс в виде открытого текста и переменную b, которая будет содержать символ ключа для индекса

var i = 0, b;

преобразует ключв верхний регистр и удалил все символы, не входящие в верхний регистр алфавита

key = key.toUpperCase().replace(/[^A-Z]/g, '');

эта строка, очевидно, слишком длинная;он преобразует текст в верхний регистр и снова удаляет не алфавитные символы

, затем заменяет символы в строке, используя функцию, определенную во втором аргументе replace

return text.toUpperCase().replace(/[^A-Z]/g, '').replace(/[A-Z]/g, function(a) {

взять следующий символ ключа в циклическом режиме, используя оператор модуля, затем обновлять индекс

b = key[i++ % key.length];

слишком много здесь происходит, очень плохая декомпозиция программы;в порядке выполнения:

  • (decode ? 26 - ordA(b) : ordA(b)): вычислить число в диапазоне, чтобы обновить индекс открытого текста;используйте противоположное значение для дешифрования (здесь его называют «декодированием»)
  • (ordA(a) + (decode ? 26 - ordA(b) : ordA(b))) % 26 выполните сложение с вычисленным числом, уменьшите до 0 до 25 (т. е. при достижении Z продолжайте с A и наоборот)
  • ((ordA(a) + (decode ? 26 - ordA(b) : ordA(b))) % 26 + 65) добавьте 65, чтобы индекс был преобразован обратно в индекс ASCII заглавных символов, используя две полностью ложные скобки
  • наконец, возвращает строку из одного результата кода символа, в противном случае + будет добавлениевместо конкатенации
return String.fromCharCode(((ordA(a) + (decode ? 26 - ordA(b) : ordA(b))) % 26 + 65));

ну, нужно было закончить

  });
}

Давайте покажем другой способ программирования этого, используя переменные с именами, функциидля повторно используемого кода и регулярных выражений, которым крайне необходимо имя, чтобы объяснить, что они делают.

var ALPHABET_SIZE = 'Z'.charCodeAt(0) - 'A'.charCodeAt(0) + 1;

var encrypted = vigenere(false, "B", "Zaphod Breeblebox");
document.body.append('<div>' + encrypted + '</div>');
var decrypted = vigenere(true, "B", encrypted);
document.body.append('<div>' + decrypted + '</div>');

function vigenere(decrypt, key, text) {
    key = toJustUppercase(key);
    text = toJustUppercase(text);
  
    var textOffset = 0;
    // iterate over all characters, performing the function on each of them
    return text.replace(/[A-Z]/g, function(textChar) {
        var keyChar = key[textOffset++ % key.length];
        var cryptedChar = substituteCharacter(decrypt, keyChar, textChar);
        return cryptedChar;
    });
}

function substituteCharacter(decrypt, keyChar, textChar) {
    var keyIndex = charToABCIndex(keyChar);
    if (decrypt) {
        // create the opposite of the encryption key index
        keyIndex = ALPHABET_SIZE - keyIndex;
    }
    
    var textIndex = charToABCIndex(textChar);

    // the actual Vigenere substitution, the rest is just indexing and conversion
    var substitutedIndex = (textIndex + keyIndex) % ALPHABET_SIZE;
      
    var substitutedChar = abcIndexToChar(substitutedIndex);
    return substitutedChar;
}

function toJustUppercase(text) {
    return text.toUpperCase().replace(/[^A-Z]/g, '')
}

function charToABCIndex(charValue) {
    return charValue.charCodeAt(0) - 'A'.charCodeAt(0);
}

function abcIndexToChar(index) {
    return String.fromCharCode(index + 'A'.charCodeAt(0));
}

Слишком много функций, вы говорите?Не совсем, я не реализовал ord и chr или vigenereEncrypt и viginereDecrypt, чтобы сделать его еще проще для чтения.

...