1、单字母替换加密方法——恺撒密码
恺撒密码是通过把英文字母按字母表的顺序编号作为明文,将密钥定为X,加密算法为将明文加上密钥X,得到密码表。输入原文后对照密码表中相同位置的字母输出得到密文。
在这里我没有专门的去生成一个密码表,而是先使用indexOf方法得出原文每个字母在明文中对应的位置,然后直接计算每个字母位移后在明文中对应的位置,最后利用charAt方法得出加密后的密文。
function reverseText1_1(){
var inputText = document.getElementById("inputBox1_1").value;
inputText = inputText.replace(/[^a-zA-Z]/g,"");
var codeNumber = parseInt(document.getElementById("code1_1").value);
var resultText = "";
for (var i = 0; i < inputText.length; i++) {
var index = alphabet1.indexOf(inputText[i].toUpperCase());
if (index === -1) {
resultText += inputText[i];
continue;
}
var codeIndex = (index + codeNumber) % 26;
var codeChar = alphabet1.charAt(codeIndex);
resultText += codeChar;
}
document.getElementById("outputBox1_1").value = resultText;
}
恺撒密码解密部分和加密部分原理相同,不过计算位移后的位置时由于变成了减法,所以要加入一个while循环保证得出的结果不小于0。
function reverseText1_2(){
var inputText = document.getElementById("inputBox1_2").value;
inputText = inputText.replace(/[^a-zA-Z]/g,"");
var codeNumber = parseInt(document.getElementById("code1_2").value);
var resultText = "";
for (var i = 0; i < inputText.length; i++) {
var index = alphabet2.indexOf(inputText[i].toLowerCase());
if (index === -1) {
resultText += inputText[i];
continue;
}
var mark = index - codeNumber;
while(mark<0){
mark += 26;
}
var codeIndex = mark % 26;
var codeChar = alphabet2.charAt(codeIndex);
resultText += codeChar;
}
document.getElementById("outputBox1_2").value = resultText;
}
2、单字母替换加密方法——字母倒排序
字母倒排序在加密、解密的过程中明文和密文按照字母表的顺序倒排对应,即A对应Z,B对应Y。
字母倒排序法中我直接设定了一个顺序相反的一个字母表作为密码表,加密解密的原理相同,直接通过indexOf方法找出在字母表中的位置,再利用charAt方法找出密码表中该位置的字母输出就可得到结果。
function reverseText2_1(){
var inputText = document.getElementById("inputBox2_1").value;
inputText = inputText.replace(/[^a-zA-Z]/g,"");
var alphabet3 = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
var resultText = "";
for (var i = 0; i < inputText.length; i++) {
var index = alphabet1.indexOf(inputText[i].toUpperCase());
resultText += alphabet3[index];
}
document.getElementById("outputBox2_1").value = resultText;
}
3、单字母替换加密方法——单表置换密码
单表置换密码是将输入的密钥字符串去重后,然后将字母表中未出现的字母按顺序排列在密钥字符串后得到密码表,根据明文表和密码表完成加密。
首先使用一个for循环将密钥去重后加入密码表。接着继续使用for循环查找还未出现在密码表中的字母,将其按顺序加入密码表。最后就是找出原文中每个字母在字母表中的位置,并且按照位置从密码表中找出结果。解密算法和加密算法的思路是一样的,只是最后是按照密码表中的顺序从字母表中输出结果。
function reverseText3_1(){
var inputText = document.getElementById("inputBox3_1").value;
inputText = inputText.replace(/[^a-zA-Z]/g,"");
var codeString = document.getElementById("code3_1").value;
codeString = codeString.replace(/[^a-zA-Z]/g,"");
var codeText = "";
for (var i = 0; i < codeString.length; i++) {
var index = codeText.indexOf(codeString[i].toUpperCase());
if (index === -1) {
codeText += codeString[i].toUpperCase();
continue;
}
}
for (var i = 0; i < alphabet1.length; i++) {
var index = codeText.indexOf(alphabet1[i]);
if (index === -1) {
codeText += alphabet1[i];
continue;
}
}
var resultText = "";
for (var i = 0; i < inputText.length; i++) {
var index = alphabet1.indexOf(inputText[i].toUpperCase());
var codeChar = codeText.charAt(index);
resultText += codeChar;
continue;
}
document.getElementById("outputBox3_1").value = resultText;
}
3、多字母替换加密方法——维吉利亚密码
维吉尼亚密码:假设明文m=m1 m2 m3 … mn,密钥k=k1 k2 k3 … kn,对应密文c=c1 c2 c3 … cn,则密文为:ci=(mi+ki )mod 26 ,26个字母的序号依次为0~25,ci , mi ,ki是分别是密文明文密钥中第i个字母的序号。
维吉尼亚密码加密时,我先使用index1储存明文中每个字母在字母表中的位置。再利用codeText[i%i1],i为当前为第几个明文,i1为密钥的长度,得出第i个明文对应的密钥字母,以及密钥字母在字母表中的位置index2。最后,index = (index1 + index2) % 26算出密文在字母表中的位置以得出密文。
function reverseText4_1(){
var inputText = document.getElementById("inputBox4_1").value;
inputText = inputText.replace(/[^a-zA-Z]/g,"");
var codeString = document.getElementById("code4_1").value;
codeString = codeString.replace(/[^a-zA-Z]/g,"");
var codeText = codeString;
var resultText = "";
for (var i = 0; i < inputText.length; i++) {
var i1 = codeText.length;
var index1 = alphabet1.indexOf(inputText[i].toUpperCase());
var index2 = alphabet1.indexOf(codeText[i%i1].toUpperCase());
var index = (index1 + index2) % 26;
var codeChar = alphabet1.charAt(index);
resultText += codeChar;
}
document.getElementById("outputBox4_1").value = resultText;
}
维吉尼亚密码解密和加密的原理相似,不过在计算index时需要使用一个while循环保证其大于0。
function reverseText4_2(){
var inputText = document.getElementById("inputBox4_2").value;
inputText = inputText.replace(/[^a-zA-Z]/g,"");
var codeString = document.getElementById("code4_2").value;
codeString = codeString.replace(/[^a-zA-Z]/g,"");
var codeText = codeString;
var resultText = "";
for (var i = 0; i < inputText.length; i++) {
var i1 = codeText.length;
var index1 = alphabet1.indexOf(inputText[i].toUpperCase());
var index2 = alphabet1.indexOf(codeText[i%i1].toUpperCase());
var mark = index1 - index2;
while(mark<0){
mark += 26;
}
var index = mark % 26;
var codeChar = alphabet1.charAt(index);
resultText += codeChar.toLowerCase();
}
document.getElementById("outputBox4_2").value = resultText;
}
4、转换加密方法1——先列后行
先列后行:将输入的明文按密钥X分为每行只有X个字符的字符串,最后按照从左到右的顺序从第一列开始输出得到密文。
加密时,我没有刻意的去将明文分解成一个个的数组,而是利用该方法的特点对明文中每个字母的顺序进行求模运算j%codeNumber ,得到的余数就是该字母所在的列数,接着从第一列开始从上到下输出就能直接得到密文。
function reverseText5_1(){
var inputText = document.getElementById("inputBox5_1").value;
inputText = inputText.replace(/[^a-zA-Z]/g,"");
var codeNumber = parseInt(document.getElementById("code5_1").value);
var resultText = "";
for (var i = 0;i < codeNumber;i++){
for (var j = 0;j < inputText.length;j++){
if (j%codeNumber == i){
resultText += inputText[j].toUpperCase();
}
}
}
document.getElementById("outputBox5_1").value = resultText;
}
解密时,我用了一个二维数组存放数据。首先根据求模运算col1 = inputText.length % codeNumber找出最后一行有没有空闲,如果没有就直接将密文存入二维数组,再按照相反的方向输出就能直接得到明文。如果最后一行有空闲,就先根据col1判断,二维数组中前col1个数组可以填满,之后的数组就应该让最后一个元素为空。最后同样是按照相反的方向输出二维数组就可以得到明文了。
function reverseText5_2() {
var inputText = document.getElementById("inputBox5_2").value;
inputText = inputText.replace(/[^a-zA-Z]/g, "");
var codeNumber = parseInt(document.getElementById("code5_2").value);
var row = Math.ceil(inputText.length / codeNumber);
var col1 = inputText.length % codeNumber;
var resultText = "";
var index = 0;
var twoDArray = new Array(codeNumber);
if(col1 != 0){
for(var i = 0; i < col1; i++){
twoDArray[i] = new Array(row);
for(var j = 0; j < row; j++){
index = i * row + j;
twoDArray[i][j] = inputText.charAt(index);
}
}
for(var i = col1; i < codeNumber; i++){
twoDArray[i] = new Array(row);
for(var j = 0; j < row-1; j++){
index = row * col1 + j + (i - col1) * (row - 1);
twoDArray[i][j] = inputText.charAt(index);
}
twoDArray[i][row-1] = "0";
}
for (var i = 0; i < row; i++) {
for (var j = 0; j < codeNumber; j++) {
resultText += twoDArray[j][i].toLowerCase();
}
}
}
else{
for(var i = 0; i < codeNumber; i++){
twoDArray[i] = new Array(row);
for(var j = 0; j < row; j++){
index = i * row + j;
twoDArray[i][j] = inputText.charAt(index);
}
}
for (var i = 0; i < row; i++) {
for (var j = 0; j < codeNumber; j++) {
resultText += twoDArray[j][i].toLowerCase();
}
}
}
resultText = resultText.replace(/[^a-zA-Z]/g, "");
document.getElementById("outputBox5_2").value = resultText;
}
5、转换加密方法2——字母倒排
字母倒排:将输入的明文按密钥X分为每行只有X个字符的字符串,最后每一行按照从右到左的顺序输出得到密文。
加密时,由于明文排列后的行数i和列数j以及密钥可以直接计算得到该字母在明文中所处的位置index = i * codeNumber + j,可以使用一个二维数组twoDArray[i][j]直接储存明文。利用Math.ceil(inputText.length / codeNumber)计算出全部行数row,先将前row-1行的字母倒排后输出,最后一行根据有没有空闲分不同的情况输出。解密的原理和加密相同。
function reverseText7_1(){
var inputText = document.getElementById("inputBox7_1").value;
inputText = inputText.replace(/[^a-zA-Z]/g,"");
var codeNumber = parseInt(document.getElementById("code7_1").value);
var resultText = "";
var row = Math.ceil(inputText.length / codeNumber);
var twoDArray = new Array(row);
for (var i = 0;i < row;i++){
twoDArray[i] = new Array(codeNumber);
for (var j = 0;j < codeNumber;j++){
var index = i * codeNumber + j;
twoDArray[i][j] = inputText.charAt(index).toUpperCase();
}
}
for (var i = 0;i < row-1;i++){
for (var j = codeNumber-1;j >= 0;j--){
resultText += twoDArray[i][j];
}
}
var index1 = inputText.length % codeNumber;
if (index1 == 0){
for (var j = codeNumber;j >= 0;j--){
resultText += twoDArray[row-1][j];
}
}
else{
for (var j = index1-1;j >= 0;j--){
resultText += twoDArray[row-1][j];
}
}
document.getElementById("outputBox7_1").value = resultText;
}
5、转换加密方法3
将输入的明文按密钥长度X分为每行只有X个字符的字符串,根据每一列对应的密钥字母在字母表中的位置从小到大输出列,相同的列先输出左边的列。
根据row = Math.ceil(inputText.length / codeNumber)计算出行数row,再设置一个有row+1个数组的二维数组,每个数组的长度等于输入密钥的长度。接着将密钥字符串填入第一个数组作为标记,然后将明文依次填入二维数组。最后设置一个26位的for循环,将第一个数组的每一个元素和字母表依次比对,按序输出先比对成功的列得到密文。
function reverseText6_1(){
var inputText = document.getElementById("inputBox6_1").value;
inputText = inputText.replace(/[^a-zA-Z]/g,"");
var codeString = document.getElementById("code6_1").value;
codeString = codeString.replace(/[^a-zA-Z]/g,"");
var resultText = "";
var codeNumber = codeString.length;
var row = Math.ceil(inputText.length / codeNumber);
var index = 0;
var twoDArray = new Array(row+1);
for (var i = 0;i < row+1;i++){
twoDArray[i] = new Array(codeNumber);
}
for (var j = 0;j < codeNumber;j++){
twoDArray[0][j] = codeString.charAt(j).toUpperCase();
}
for (var i = 1;i < row+1;i++){
for (var j = 0;j < codeNumber;j++){
index = (i - 1) * codeNumber + j;
twoDArray[i][j] = inputText.charAt(index).toUpperCase();
}
}
for (var i = 0;i < 26;i++){
for (var j = 0;j < codeNumber;j++){
if(alphabet1[i] === twoDArray[0][j]){
for (var k = 1;k < row+1;k++){
resultText += twoDArray[k][j];
}
}
}
}
document.getElementById("outputBox6_1").value = resultText;
}
解密时,同样是先设置一个有row+1个数组的二维数组,不过在这里用fill('')将其用空字符填充完整。接着将密钥字符串填入每个数组的第一个作为标记,然后将明文依次填入二维数组。填入时要使用一个col1 = inputText.length % codeNumber判断哪几个数组的最后一个元素为空,按照密钥中字母在字母表中的顺序依次填入,如果最后一个元素不为空则填入row个,为空则填入row-1个。最后依次输出二维数组,并用replace移除字母以外的字符就可得到明文。
function reverseText6_2(){
var inputText = document.getElementById("inputBox6_2").value;
inputText = inputText.replace(/[^a-zA-Z]/g,"");
var codeString = document.getElementById("code6_2").value;
codeString = codeString.replace(/[^a-zA-Z]/g,"");
var codeNumber = codeString.length;
var row = Math.ceil(inputText.length / codeNumber);
var col1 = inputText.length % codeNumber;
var twoDArray = new Array(codeNumber);
for (var i = 0;i < codeNumber;i++){
twoDArray[i] = new Array(row + 1).fill('');
}
for (var j = 0;j < codeNumber;j++){
twoDArray[j][0] = codeString.charAt(j).toUpperCase();
}
var index = 0;
if (col1 === 0){
for (var i = 0;i < 26;i++){
for (var j = 0;j < codeNumber;j++){
if(alphabet1[i] === codeString.charAt(j).toUpperCase()){
for (var k = 1;k < row+1;k++){
twoDArray[j][k] += inputText.charAt(index).toLowerCase();
index += 1;
}
}
}
}
}
else{
for (var i = 0;i < 26;i++){
for (var j = 0;j < codeNumber;j++){
if(alphabet1[i] === codeString.charAt(j).toUpperCase()){
if (j<col1){
for (var k = 1;k < row+1;k++){
twoDArray[j][k] += inputText.charAt(index).toLowerCase();
index += 1;
}
}
else{
for (var k = 1;k < row;k++){
twoDArray[j][k] += inputText.charAt(index).toLowerCase();
index += 1;
}
}
}
}
}
}
var resultText = "";
for (var i = 1;i < row+1;i++){
for (var j = 0;j < codeNumber;j++){
resultText += twoDArray[j][i];
}
}
resultText = resultText.replace(/[^a-zA-Z]/g, "");
document.getElementById("outputBox6_2").value = resultText;
}