簡體   English   中英

解密 Javascript 中的 3 步密碼會導致字母表中 26 個字符中僅顯示一半,而一些字符最終會顯示為符號

[英]Decryption of a 3-step cipher in Javascript leads to only half of the 26 characters in the alphabet being show, while some end up as symbols

所以我有一個項目,我需要創建一個密碼,其中內置了 3 種不同類型的密碼。 就我而言,我有一個凱撒密碼、阿特巴什密碼和 ROT13。 但是,每當我嘗試解密消息時,有些字符不會顯示,而有些則顯示為符號。

下面是我在 Javascript 中的代碼

function decryptROT13() { 
    var dmsg = document.getElementById('message').value;
    var dnewMsg2 = '';
    for(var i = 0; i < dmsg.length; i++){
    var n = dmsg.charCodeAt(i)

    if(n == 32) {
        dnewMsg2 += String.fromCharCode(n);
    }

    else if(n - 13 > 90){
        dnewMsg2 += String.fromCharCode(n-13-26)
    }

    else{
        dnewMsg2 += String.fromCharCode(n - 13)
        }

    }
    decryptAtbash(dnewMsg2);
}

function decryptAtbash(dval) { 
    var dmsg = dval;
    var dnewMsg1 = '';
    var dtebahpla = 'ZYXWVUTSRQPONMLKJIHGFEDCBA ';
    var dalphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ';     

    for (i = 0; i < dmsg.length; i++) {
        var dcodedLetter = dmsg.charAt(i);
        var dletterIndex = dalphabet.indexOf(dcodedLetter);
        dnewMsg1 += dalphabet.charAt(dletterIndex); 
        }
        
     decryptCaesar(dnewMsg1); 

}


function decryptCaesar(dval) {  
    var dnewMsg = '';
    var dmsg = dval;
    var dmsg1 = dmsg.toUpperCase();
    for(var i = 0; i < dmsg1.length; i++){
        var n = dmsg1.charCodeAt(i)

    if(n == 32) {
        dnewMsg += String.fromCharCode(n);
    }

    else if(n - 3 > 90){
        dnewMsg += String.fromCharCode(n - 3 - 26)
    }

    else{
        dnewMsg += String.fromCharCode(n - 3)
        }
    }
    dnewMsg.toUpperCase()
    document.getElementById('decryptedMessage').innerHTML = dnewMsg;
}

這就是 output 的樣子:

這就是輸出的樣子

字符代碼

我們的簡單密碼將處理大寫字母 AZ 並對其 ASCII 字符代碼執行簡單的轉換。 我們可以 go 從一個字母到一個字符代碼 -

console.log("A".charCodeAt(0)) // 65
console.log("B".charCodeAt(0)) // 66
console.log("C".charCodeAt(0)) // 67
console.log("Z".charCodeAt(0)) // 90

或者從一個字符代碼到一個字母——

console.log(String.fromCharCode(65)) // "A"
console.log(String.fromCharCode(66)) // "B"
console.log(String.fromCharCode(67)) // "C"
console.log(String.fromCharCode(90)) // "Z"

我們將編寫可重用的函數toCodefromCode來簡化我們程序的 rest -

const toCode = s =>
  s.toUpperCase().charCodeAt(0)

const fromCode = n =>
  String.fromCharCode(n)

密碼

cipher是一種同構- 即,它是一對函數,其中一個 function 可以反轉另一個的效果。 我們編寫的每個密碼都有一個encodedecode function -

const cipher = (encode, decode) =>
  ({ encode, decode })

字符A從偏移量65開始, Z90結束,我們不想將密碼應用於超出此范圍的字符。 如果我們可以編寫適用於從 0-25 的簡單 AZ 字符集運行的密碼,而不是在每個密碼中處理此邏輯,那就太好了 -

(0,A) (1,B) (2,C) (3,D) (4,E)
(5,F) (6,G) (7,H) (8,I) (9,J)
(10,K) (11,L) (12,M) (13,N) (14,O)
(15,P) (16,Q) (17,R) (18,S) (19,T)
(20,U) (21,V) (22,W) (23,X) (24,Y)
(25,Z)

對於任何給定的alg和字符代碼n ,我們可以filter超出 65-90 范圍的字符,並自動將適當的偏移量應用於算法的響應 -

const filter = alg => n =>
  n < 65 || n > 90      // if n is out or range
    ? n                 // simply return n
    : 65 + alg(n - 65)  // apply offset to alg's response

阿特巴什

現在讓我們編寫我們的第一個密碼atbash -

atbash(n) 密碼
25 - 0 = 25 A → Z
25 - 1 = 24 B → Y
25 - 2 = 23 C → X
25 - 23 = 2 X → C
25 - 24 = 1 Y → B
25 - 25 = 0 Z → A

實現很簡單。 如上表所示,對 atbash 進行編碼的過程與解碼過程完全相同。 換句話說, atbash是一對相同的函數——

const atbash =
  cipher(n => 25 - n, n => 25 - n)

rot13

接下來我們看看我們的第二個密碼, rot13 -

rot13(n) 密碼
rot13(0) A → N
腐爛13(1) B→O
腐爛13(2) C → P
腐爛13(23) X → K
腐爛13(24) Y → L
腐爛13(25) Z → M

Rot1313 的凱撒位移,所以我們可以簡單地將其定義為

const rot13 =
  caesar(13)

凱撒

最后,Caesar 允許我們將字符代碼移動指定的量 -

凱撒(移位,n) 密碼
凱撒(-3,0) A → X
凱撒(-2,0) A → Y
凱撒(-1,0) A → Z
凱撒(0,0) 一→一
凱撒(1,0) 甲→乙
凱撒(2,0) A → C
凱撒(3,0) A → D
凱撒(-100,0) A → E
凱撒(100,0) A → W

我們可以通過使用shift量參數化cipher來實現caesar period用於執行基本的模運算並支持任何正或負移位量 -

const caesar = shift =>
  cipher
    ( n => period(26, n + shift) // plus shift for encode
    , n => period(26, n - shift) // minus shift for decode
    )

const period = (z, n) =>
  (z + n % z) % z

編碼和解碼

我們定義的密碼對字符代碼進行操作,但我們不希望用戶手動處理該轉換。 我們將提供一個簡單的encode function 來使用 -

encode(atbash, "A")  // "Z"
encode(atbash, "B")  // "Y"
encode(atbash, "C")  // "Z"

encode(caesar(1), "A") // "B"
encode(caesar(2), "A") // "C"
encode(caesar(3), "A") // "D"

以及反向decode function -

decode(atbash, "Z")  // "A"
decode(atbash, "Y")  // "B"
decode(atbash, "Z")  // "C"

decode(caesar(1), "B") // "A"
decode(caesar(2), "C") // "A"
decode(caesar(3), "D") // "A"

encodedecode接受密碼c和輸入字符串s -

const encode = (c, s) =>
  transform(c.encode, s)

const decode = (c, s) =>
  transform(c.decode, s)

無論您是編碼還是解碼, transform過程都是相同的。 唯一改變的是正在使用的alg -

const transform = (alg, s) =>
  Array
    .from(s, composeL(toCode, filter(alg), fromCode))
    .join("")

我的密碼

最后,我們編寫composeCipher ,它允許您從一系列密碼構建自己的復雜cipher 編碼器序列使用composeL 自然地,解碼器序列使用composeR從右到左反向運行 -

const composeCipher = (...ciphers) =>
  cipher
    ( composeL(...ciphers.map(c => c.encode)) // encode
    , composeR(...ciphers.map(c => c.decode)) // decode
    )

const myCipher =
  composeCipher(rot13, atbash, caesar(3))
console.log(encode(myCipher, "DON'T CAUSE PANIC!"))
// MBC'W NPVXL APCHN!
console.log(decode(myCipher, "MBC'W NPVXL APCHN!"))
// DON'T CAUSE PANIC!

可重用函數

上面我們使用composeL (左)和composeR (右),它們是通用的function 組合程序。 這些允許我們從一系列輸入函數中構建單個 function。 您無需了解它們的實現即可使用它們 -

// func.js

const composeL = (...fs) =>
  x => fs.reduce((r, f) => f(r), x)

const composeR = (...fs) =>
  x => fs.reduceRight((r, f) => f(r), x)

// ...

export { composeL, composeR, ... }

模塊

就像我們對上面的func模塊所做的那樣,你應該捆綁你自己的cipher模塊來保持你的代碼整潔。 這也允許我們選擇用戶應該可以訪問模塊的哪些部分 -

// cipher.js

import { composeL, composeR } from "./func.js"

const atbash = ...
const caesar = ...
const cipher = ...
const compose = ...
const decode = ...
const encode = ...
const fromCode = ...
const rot13 = ...
const toCode = ...
const transform = ...

export { atbash, caesar, cipher, compose, decode, encode, rot13 }

當我們編寫程序時,我們只導入我們需要的部分——

// main.js

import { compose, atbash, caesar, rot13 } from "./cipher.js"

const superSecret =
  compose(rot13, atbash, caesar(3))

console.log(encode(superSecret, "DON'T CAUSE PANIC!"))
console.log(decode(superSecret, "MBC'W NPVXL APCHN!"))
MBC'W NPVXL APCHN!
DON'T CAUSE PANIC!

演示

展開下面的代碼片段以在您自己的瀏覽器中驗證結果 -

 // cipher.js const fromCode = n => String.fromCharCode(n) const toCode = s => s.toUpperCase().charCodeAt(0) const cipher = (encode, decode) => ({ encode, decode }) const atbash = cipher(n => 25 - n, n => 25 - n) const caesar = shift => cipher ( n => period(26, n + shift), n => period(26, n - shift) ) const rot13 = caesar(13) const filter = alg => n => n < 65 || n > 90? n: 65 + alg(n - 65) const period = (z, n) => (z + n % z) % z const transform = (f, s) => Array.from(s, composeL(toCode, filter(f), fromCode)).join("") const encode = (alg, s) => transform(alg.encode, s) const decode = (alg, s) => transform(alg.decode, s) const composeCipher = (...ciphers) => cipher ( composeL(...ciphers.map(c => c.encode)), composeR(...ciphers.map(c => c.decode)) ) // func.js const composeL = (...fs) => x => fs.reduce((r, f) => f(r), x) const composeR = (...fs) => x => fs.reduceRight((r, f) => f(r), x) // main.js const myCipher = composeCipher(rot13, atbash, caesar(3)) console.log(encode(myCipher, "DON'T CAUSE PANIC.")) console,log(decode(myCipher, "MBC'W NPVXL APCHN!"))

MBC'W NPVXL APCHN!
DON'T CAUSE PANIC!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM