简体   繁体   English

javascript中的凯撒密码:密码被破坏

[英]Caesar Cipher in javascript: cipher broken

I'm building a Caesar Cipher in javascript.我正在用 javascript 构建一个凯撒密码。 It uses a randomly set variable called currentkey as the cipher's key.它使用一个随机设置的变量currentkey作为密码的密钥。 it can be a number from -25 to +25, skipping 0.它可以是从 -25 到 +25 的数字,跳过 0。

I can't figure out why the function returns undefined in the beginning of the string, or why it translates the same letter for as long as the string goes, or even why that letter doesn't get translated at all.我不明白为什么函数在字符串的开头返回 undefined,或者为什么只要字符串存在,它就会翻译同一个字母,甚至为什么那个字母根本没有被翻译。

var currentkey = 5  //for example
function convertKey(str) {
    var o_text = str;
    var o_letters = o_text.split("");
    var alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','x','y','w','z']
    var c_text, _x = "";
    for (x in o_letters) {
        if (currentkey > 0) {
            _x = alphabet[alphabet.indexOf(x) + currentkey]
        } else {
            _x = alphabet[alphabet.indexOf(x) + (26 - currentkey)]
        }
        c_text = c_text + _x;
    }
    return c_text;
}

For example, running convertKey("example") returns undefinedeeeeeee (undefined + 7 times the first letter in "example").例如,运行convertKey("example")返回undefinedeeeeeee (未定义 + "example" 中第一个字母的 7 倍)。

Implementation the Caesar Cipher algorithm in JavaScript is very interesting due to the fact that JavaScripts lacks true modulo operator.由于 JavaScript 缺少真正的模运算符,因此在 JavaScript 中实现 Caesar Cipher 算法非常有趣。 The % is just the reminder of division. % 只是除法的提醒。 Read this article for more explanations.阅读这篇文章以获得更多解释。

However, you can easily define the modulo as a custom function and then proceed to the implementation of the Caesar Cipher - which is a very simple form of encryption, in which each letter in the original message is shifted to the left or right by a certain number of positions.但是,您可以轻松地将模定义为自定义函数,然后继续实现凯撒密码——这是一种非常简单的加密形式,其中原始消息中的每个字母向左或向右移动某个职位数。

To decrypt the message we simply shift back the letters the same number of positions.要解密消息,我们只需将字母移回相同数量的位置。

Example:例子:

  • JAVASCRIPT becomes MDYDVFULSW if we shift all letters by 3 positions如果我们将所有字母移动 3 个位置,JAVASCRIPT 将变成 MDYDVFULSW
  • MDYDVFULSW turns back to JAVASCRIPT if we shift back all letters by 3 positions.如果我们将所有字母向后移动 3 个位置,MDYDVFULSW 将返回 JAVASCRIPT。

If after shifting a letter goes outside the range of letters, then the letter is wrapped around in alphabet.如果移位后一个字母超出了字母范围,则该字母将在字母表中环绕。 Example: Letter Z becomes C if is shifted by 3 positions.示例:如果字母 Z 移动 3 个位置,则变为 C。

This “wrap-around” effect means use of modulo.这种“环绕”效果意味着使用模数。 In mathematical terms, the above can be expressed as this:用数学术语来说,上面的可以表示为:

En(x) = (x + n) mod 26 En(x) = (x + n) mod 26

Dn(x) = (x – n) mod 26 Dn(x) = (x – n) mod 26

Trying to implement this algorithm in JavaScript without the use of a proper modulo operator will produce either incorrect results or a very cryptic and difficult to understand code.在不使用适当的模运算符的情况下尝试在 JavaScript 中实现此算法将产生不正确的结果或非常神秘且难以理解的代码。

By using a custom modulo function, the code expresses the mathematical equation identically:通过使用自定义模函数,代码以相同的方式表达数学方程:

// Function will implement Caesar Cipher to
// encrypt / decrypt the msg by shifting the letters
// of the message acording to the key
function encrypt(msg, key)
{
    var encMsg = "";

    for(var i = 0; i < msg.length; i++)
    {
        var code = msg.charCodeAt(i);

        // Encrypt only letters in 'A' ... 'Z' interval
        if (code >= 65 && code <= 65 + 26 - 1)
        {
            code -= 65;
            code = mod(code + key, 26);
            code += 65;
        }

        encMsg += String.fromCharCode(code);
    }

    return encMsg;
}

// Implement modulo by replacing the negative operand 
// with an equivalent positive operand that has the same wrap-around effect
function mod(n, p)
{
    if ( n < 0 )
        n = p - Math.abs(n) % p;

    return n % p;
}

Have fun!玩得开心!

Encrypt a few messages to try out the code.加密一些消息以试用代码。 Remember: If you encrypt with a positive key, use the complementary negative key to decrypt it.请记住:如果您使用正密钥进行加密,请使用互补的负密钥对其进行解密。 You can also use this code to decode those ROT13 messages that appears everywhere on the web and newsgroups.您还可以使用此代码来解码出现在网络和新闻组中随处可见的 ROT13 消息。

If you want to find out other ways of implementing modulo in JavaScript, please consult the article mentioned at the beginning of this post.如果您想了解在 JavaScript 中实现取模的其他方法,请参阅本文开头提到的文章。

(1) You are not iterating through your array o_letters properly. (1) 您没有正确地遍历数组o_letters

(2) You are going out-of-bounds for your array. (2) 你的数组越界了。

for (var i = 0; i < o_letters.length; i++) {
    _x = alphabet[(alphabet.indexOf(o_letters[i]) + currentkey + 26) % 26]
    c_text = c_text + _x;
}

Also, in your code, you don't need .split("") at all.此外,在您的代码中,您根本不需要.split("")

I would just do this:我只会这样做:

var currentkey = 5  //for example
function convertKey(str) {
    var ret = '';
    for (var i = 0; i < str.length; i++) {
        ret += String.fromCharCode((str.charCodeAt(i) + currentKey + 26) % 26);
    }
    return ret;          
}

Or more succinctly (but less efficiently):或者更简洁(但效率较低):

function convertKey(str) {
    return str.split('').map(function(c) {
       return String.fromCharCode((c.charCodeAt(0) + currentKey + 26) % 26);
    }).join('');       
}

The undefined is a result of not initializing c_text before you try concatenate it with _x . undefined是在尝试将c_text_x连接之前未初始化的结果。

The code only works on one letter because alphabet.indexOf(x) returns -1 (not found).该代码仅适用于一个字母,因为alphabet.indexOf(x)返回-1 (未找到)。 When using o_text = "abc" , x equals 0, 1, and 2. Thus, the index of 0, 1, or 2 in alphabet is nonexistent (indicated by the -1 result).使用o_text = "abc"x等于 0、1 和 2。因此, alphabet的 0、1 或 2 索引不存在(由-1结果指示)。 You need to relate those numbers back to o_text by changing indexOf(x) to indexOf(o_text[x]) .您需要通过将indexOf(x)更改为indexOf(o_text[x])将这些数字关联回o_text Also, to prevent going outside the bounds of your array, you need a modulus operation to wrap values greater than 26 (I've used alphabet.length to allow this code to work with other alphabets) back around into a valid region.此外,为了防止超出数组的范围,您需要一个模数运算来将大于 26 的值(我使用了alphabet.length长度以允许此代码与其他字母表一起使用)回绕到有效区域。 Thus, the correct code would be as follows (note: I've moved 'w' in your array into its proper location alphabetically, as I assumed its location in your example was an error and not intentional):因此,正确的代码如下(注意:我已将数组中的 'w' 按字母顺序移动到其正确位置,因为我假设它在您的示例中的位置是错误而不是故意的):

var currentkey = 5  //for example
function convertKey(str) {
    var o_text = str;
    var o_letters = o_text.split("");
    var 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']
    var c_text="", _x = "";
    for (x in o_letters) {
        if (currentkey > 0) {
            _x = alphabet[(alphabet.indexOf(o_letters[x]) + currentkey) % alphabet.length]
        } else {
            _x = alphabet[(alphabet.indexOf(o_letters[x]) + (26 - currentkey)) % alphabet.length]
        }
        c_text = c_text + _x;
    }
    return c_text;
}

alert(convertKey('abcdefghijklmnopqrstuvwxyz'));

This alert's fghijklmnopqrstuvwxyzabcde此警报的fghijklmnopqrstuvwxyzabcde

// working at https://www.freecodecamp.org/challenges/caesars-cipher // 在https://www.freecodecamp.org/challenges/caesars-cipher工作

function rot13(str){    

var res = [];

var currentPosition;

var shiftedPosition;

for (var i = 0; i<str.length; i++){
    currentPosition = str.charCodeAt(i);

    if (currentPosition<65 || currentPosition>90){
    res.push(String.fromCharCode(currentPosition));
    }

    shiftedPosition = str.charCodeAt(i) - 13;

    if (currentPosition>=65 && shiftedPosition <65){
    res.push(String.fromCharCode(91-(13-(currentPosition-65))));
    }

    if (currentPosition>=78 && currentPosition<=90){
    res.push(String.fromCharCode(shiftedPosition));
    }
  }
return res.join('');`enter code here`
}

// Change the inputs below to test

rot13("GUR DHVPX OEBJA QBT WHZCRQ BIRE GUR YNML SBK.");

Here's a more simple answer:这是一个更简单的答案:

 var rot = { 'A': 'N', 'B': 'O', 'C': 'P', 'D': 'Q', 'E': 'R', 'F': 'S', 'G': 'T', 'H': 'U', 'I': 'V', 'J': 'W', 'K': 'X', "L": 'Y', 'M': 'Z', 'N': 'A', 'O': 'B', 'P': 'C', 'Q': 'D', 'R': 'E', 'S': 'F', 'T': 'G', 'U': 'H', 'V': 'I', 'W': 'J', 'X': 'K', 'Y': 'L', 'Z': 'M', ' ': ' ', '.': '.', '!': '!', '?': '?' }; // Change the inputs below to test rot13("SERR CVMMN!"); // FREE CODE CAMP function rot13(str) { var index = []; for (var key in str) { for (var property in rot) { if (str[key] === property) { index.push(rot[property]); } } } return index.join(''); }

function rot13(str) {
const alphabet1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY';
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
return str
  .split('')
  .map(function(char) {  
    const pos = alphabet.indexOf(char);
    return pos >=0? alphabet1[pos+13] : char;     
  })
  .join('');
}
rot13("SERR PBQR PNZC");

  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM