[英]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"
我們將編寫可重用的函數toCode
和fromCode
來簡化我們程序的 rest -
const toCode = s =>
s.toUpperCase().charCodeAt(0)
const fromCode = n =>
String.fromCharCode(n)
密碼
cipher
是一種同構- 即,它是一對函數,其中一個 function 可以反轉另一個的效果。 我們編寫的每個密碼都有一個encode
和decode
function -
const cipher = (encode, decode) =>
({ encode, decode })
字符A
從偏移量65
開始, Z
在90
結束,我們不想將密碼應用於超出此范圍的字符。 如果我們可以編寫適用於從 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 |
Rot13是13 的凱撒位移,所以我們可以簡單地將其定義為
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"
encode
和decode
接受密碼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.