[英]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
So I have a project where I need to create a cipher which has 3 different types of ciphers built into it.所以我有一个项目,我需要创建一个密码,其中内置了 3 种不同类型的密码。 In my case I have a Caesar cipher, Atbash cipher and ROT13.
就我而言,我有一个凯撒密码、阿特巴什密码和 ROT13。 Whenever I try to decrypt a message however, some characters don't show up, while some show up as symbols.
但是,每当我尝试解密消息时,有些字符不会显示,而有些则显示为符号。
Below is my code in Javascript下面是我在 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;
}
This what the output looks like:这就是 output 的样子:
character codes字符代码
Our simple ciphers will work on capital letters AZ and perform simple transformations of their ASCII character codes.我们的简单密码将处理大写字母 AZ 并对其 ASCII 字符代码执行简单的转换。 We can go from a letter to a character code -
我们可以 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
Or from a character code to a letter -或者从一个字符代码到一个字母——
console.log(String.fromCharCode(65)) // "A"
console.log(String.fromCharCode(66)) // "B"
console.log(String.fromCharCode(67)) // "C"
console.log(String.fromCharCode(90)) // "Z"
We will write reusable functions toCode
and fromCode
to simplify the rest of our program -我们将编写可重用的函数
toCode
和fromCode
来简化我们程序的 rest -
const toCode = s =>
s.toUpperCase().charCodeAt(0)
const fromCode = n =>
String.fromCharCode(n)
cipher密码
A cipher
is an isomorphism - ie, it is a pair of functions whereby one function can reverse the effect of the other. cipher
是一种同构- 即,它是一对函数,其中一个 function 可以反转另一个的效果。 Each cipher we write will have an encode
and decode
function -我们编写的每个密码都有一个
encode
和decode
function -
const cipher = (encode, decode) =>
({ encode, decode })
Character A
starts at offset 65
, Z
ends at 90
, and we don't want to apply our cipher to characters out of this range.字符
A
从偏移量65
开始, Z
在90
结束,我们不想将密码应用于超出此范围的字符。 Instead of handling this logic in each cipher, it would be nice if we could write our ciphers that work on a simple AZ charset that goes from 0-25 -如果我们可以编写适用于从 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)
For any given alg
orithm and character code n
, we can filter
characters that are out of the 65-90 range, and automatically apply appropriate offset to the algorithm's response -对于任何给定的
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阿特巴什
Now let's write our first cipher, atbash
-现在让我们编写我们的第一个密码
atbash
-
atbash(n) ![]() |
cipher![]() |
---|---|
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 ![]() |
The implementation is simple.实现很简单。 As the table above reveals, the process to encode atbash is exactly the same as the decoding process.
如上表所示,对 atbash 进行编码的过程与解码过程完全相同。 In other words,
atbash
is a pair of identical functions -换句话说,
atbash
是一对相同的函数——
const atbash =
cipher(n => 25 - n, n => 25 - n)
rot13 rot13
Next we look at our second cipher, rot13
-接下来我们看看我们的第二个密码,
rot13
-
rot13(n) ![]() |
cipher![]() |
---|---|
rot13(0) ![]() |
A → N ![]() |
rot13(1)![]() |
B → O ![]() |
rot13(2)![]() |
C → P ![]() |
rot13(23)![]() |
X → K ![]() |
rot13(24)![]() |
Y → L ![]() |
rot13(25)![]() |
Z → M ![]() |
Rot13 is a Caesar shift of 13, so we can simply define it as Rot13是13 的凯撒位移,所以我们可以简单地将其定义为
const rot13 =
caesar(13)
caesar凯撒
And lastly Caesar allows us shift the character code by a specified amount -最后,Caesar 允许我们将字符代码移动指定的量 -
caesar(shift,n)![]() |
cipher![]() |
---|---|
caesar(-3,0)![]() |
A → X ![]() |
caesar(-2,0)![]() |
A → Y ![]() |
caesar(-1,0)![]() |
A → Z ![]() |
caesar(0,0)![]() |
A → A![]() |
caesar(1,0)![]() |
A → B![]() |
caesar(2,0)![]() |
A → C ![]() |
caesar(3,0)![]() |
A → D ![]() |
caesar(-100,0)![]() |
A → E ![]() |
caesar(100,0)![]() |
A → W ![]() |
We can implement caesar
by parameterizing a cipher
with a shift
amount.我们可以通过使用
shift
量参数化cipher
来实现caesar
。 period
is used to perform basic modular arithmetic and support any positive or negative shift amount - 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 and decode编码和解码
The ciphers we defined operate on character codes but we don't expect the user to do handle that conversion manually.我们定义的密码对字符代码进行操作,但我们不希望用户手动处理该转换。 We will provide a simple
encode
function to work with -我们将提供一个简单的
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"
As well as the reversing decode
function -以及反向
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
and decode
accept a cipher, c
, and an input string, s
- encode
和decode
接受密码c
和输入字符串s
-
const encode = (c, s) =>
transform(c.encode, s)
const decode = (c, s) =>
transform(c.decode, s)
The transform
procedure is the same whether you are encoding or decoding.无论您是编码还是解码,
transform
过程都是相同的。 The only things that changes is the alg
orithm being used -唯一改变的是正在使用的
alg
-
const transform = (alg, s) =>
Array
.from(s, composeL(toCode, filter(alg), fromCode))
.join("")
myCipher我的密码
Finally we write composeCipher
which allows you to construct your own complex cipher
from a sequence of ciphers.最后,我们编写
composeCipher
,它允许您从一系列密码构建自己的复杂cipher
。 The sequence of encoders runs from left-to-right using composeL
.编码器序列使用
composeL
。 Naturally, the sequence of decoders runs in reverse from right-to-left using composeR
-自然地,解码器序列使用
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!
reusable functions可重用函数
Above we use composeL
(left) and composeR
(right) which are generic function composition procedures.上面我们使用
composeL
(左)和composeR
(右),它们是通用的function 组合程序。 These allow us to building a single function out of a sequence of input functions.这些允许我们从一系列输入函数中构建单个 function。 You don't need to understand their implementation in order to use them -
您无需了解它们的实现即可使用它们 -
// 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, ... }
modules模块
Like we did with the func
module above, you should bundle your very own cipher
module to keep your code nice and tidy.就像我们对上面的
func
模块所做的那样,你应该捆绑你自己的cipher
模块来保持你的代码整洁。 This also allows us to choose which parts of the module should be accessible to the user -这也允许我们选择用户应该可以访问模块的哪些部分 -
// 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 }
When we write our program, we only import the parts we need -当我们编写程序时,我们只导入我们需要的部分——
// 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!
demo演示
Expand the snippet below to verify the result in your own browser -展开下面的代码片段以在您自己的浏览器中验证结果 -
// 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.