【问题标题】:Explaining functions of Vigenère cipher解释 Vigenère 密码的功能
【发布时间】:2019-07-18 04:56:15
【问题描述】:

我在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));
  });
}

【问题讨论】:

  • 65 是字母 A
  • ordA 采用大写字符并返回从“A”偏移。 'A' 为 0,'B' 为 1,...,'Z' 为 25。

标签: javascript encryption cryptography vigenere


【解决方案1】:

我不确定这是否应该是示例代码,但它主要展示了如何不编程。正在做出明智的决定,但显然问题分解、变量命名和文档还有很多不足之处。重复的代码、错综复杂的行、无法解释的代码片段,不胜枚举。解码是一个布尔值,但加密的反面是解密而不是解码。编写此代码是为了了解发生了什么;在这方面,它在 Rosetta 网站上所做的事情令人难以置信。


返回英文字母或 ABC 中的索引,假设为大写字符,0 到 25 而不是 1 到 26(因为您可以使用零索引进行模块化计算,而不是使用基于 1 的索引)

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));
}

你说的功能太多了?不是真的,我没有实现ordchr,或vigenereEncryptviginereDecrypt 以使其更易于阅读。

【讨论】:

  • 如果有人能向我解释为什么我的常量定义不能移到下面,我会很高兴。
  • 我主要是编写上面的sn-p来了解sn-p工具箱的东西,但我认为我没有完全正确。非常感谢编辑。
  • 感谢您的帮助!您的解释和编写的代码将对我有很大帮助。
  • 没问题,很高兴这对您有所帮助。最后一点:显然首先转换为全部大写,然后只转换全部大写,这也有点虚假。
猜你喜欢
  • 2012-11-04
  • 2017-04-26
  • 1970-01-01
  • 2016-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 1970-01-01
相关资源
最近更新 更多