Vigenere密码

Vigenere密码技术:


在单字符单表替换密码中,明文中的字符与密文中字符是一一对应的(在明文表中的字符也存在于在密文表中),
明文中字符的统计特性在密文中没有得到改变。
单字符多表替换密码技术是用一系列(两个以上)替换表依次对明文的字符进行替换。
假设明文字符表为Zq,替换表序列为L=L1L2L3...., 明文字符序列为m=m1m2m3...,
则相应的密文序列C=L(m)=L1(m1)L2(m2).....



如果替换序列是非周期的无限序列,则相应的密码技术为非周期多表替换密码技术,
对每个明文都采用了不同的替换表进行加密,理论上是不可破译的。
例如,非周期多表:替换表序列为L=A1A2A3...AnB1B2..BnC1C2..Cn  (ABC..指不同密文表)


在实际应用中,大多采用周期多表替换,使用有限的替换表,以完成对明文的加密。
例如,周期是d,则替换表序列为L=L1L2L3..LdL1L2L3..Ld..。 (采用同一表周期循环来组成)
(当d=1时,即为单字符单表替换)


此类多表替换时,每一个字符的对应密文由i,j 二维决定,i确定为哪个替换表,j确定为该替换表中的几号字符。


下面介绍典型的一种单字符多表替换密码技术:Vigenere密码
人们在单一恺撒密码的基础上扩展出多表密码,称为“维吉尼亚”密码。
于1586年由法国密码学家 Blaise de Vigenere发明。
Vigenere密码使用一个字符串作为密钥,字符串中的每一个字符都作为移位替换密码的密钥并确定一个替换表
(即确定了使用多表中的哪个表,即上述提到的i的作用)


设密钥K=k1k2..kd,明文与密文表中均包含n个字母
明文M=m1m2... 密文C=c1c2....


则加密Ci=(mi+ki)mod n
  解密Mi=(Ci-ki+n)%n

  
在通常的Vigenere密码中,替换表由26个英文字母组成,为周期循环
若看成一维表,由于共26个字母,每个字母可做一个i 指定一个替换表,即共26个替换表
即本总密文表长度为26X26   
注意:Vigenere密码的26个密码表,每个表相对前一个表发生一次左移。
若看成二维表,则可能更容易对比。
左侧的a-z为密钥,上方的为明文, 由此(i,j)确定下此环境时的相应密文。
可将a-z看做0-26 更容易计算。



例如:
n=26, 密钥K=somuch, 当明文M=a man liberal in his views时,
对应加密后C=s amh nptsdun pf vun xpwke


密钥K的长度d=6,即选择了Vigenere密码方阵表中的somuch 对应的6个表来依次对明文加密。


测试例子如下:(使用了二维数组存储生成的密码方阵表)

import java.util.ArrayList;
import java.util.Scanner;

public class Vigenere密码技术 {
static ArrayList<Character> templist=new ArrayList<>();

public static void EkandDk(String normalStr,String cipher,char[][]CharArrays,int n){
char[] cipherChars=cipher.toCharArray();//转换得到密钥串字符组
String splitStrs[]=normalStr.split(" ");
int d=cipherChars.length;
int cipherIndex=0;
for (int j = 0; j < splitStrs.length; j++) {
char normalChars[]=splitStrs[j].toCharArray();
for (int p = 0; p < normalChars.length; p++) {
int hang=cipherChars[cipherIndex]-'a';
int lie=normalChars[p]-'a';
normalChars[p]=CharArrays[hang][lie];//加密
System.out.print(normalChars[p]);
normalChars[p]=CharArrays[hang][(lie-hang+n)%n];//解密
templist.add(normalChars[p]);
cipherIndex=(cipherIndex+1)%d;
}
System.out.print(" ");
templist.add(' ');
}
}
public static void outPut(){
for(Character o:templist){
System.out.print(o);
}
System.out.println();
}
public static void createTables(char CharArrays[][]){
for (int i = 1; i < CharArrays.length; i++) {
for (int j = 0; j < CharArrays.length; j++) {
CharArrays[i][j]=CharArrays[0][(j+i)%CharArrays.length];
}
}
}
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
System.out.println("第一行输入密码表总数n\n"
+ "第二行输入各明文字符\n"
+ "第三行输入密钥字\n"
+ "第四行输入待加密明文");
int n=scan.nextInt();
char CharArrays[][]=new char[n][n];
CharArrays[0]=scan.next().toCharArray();
String cipher=scan.next();
scan.nextLine();
String normalStr=scan.nextLine();
createTables(CharArrays);//创建Vigenere密码方阵表

System.out.println("加密后如下:");
EkandDk(normalStr, cipher, CharArrays, n);

/*由于是二维表,通过关键字已经确定下了替换表,即上述hang号对应的替换表
* 密文字符在对应的替换表中列号顺序是确定的(因为总表和密钥已确定)
* 又因为第hang号表的字符左移了hang位,所以该密文左移hang位即为真正的明文序号*/


System.out.println("\n解密后如下:");
outPut();
System.out.println("---------------\n密码方阵表如下:");
for (int i = 0; i < CharArrays.length; i++) {
for (int j = 0; j < CharArrays.length; j++) {
System.out.print(CharArrays[i][j]);
}
System.out.println();
}
}
}


运行结果如下:

第一行输入密码表总数n
第二行输入各明文字符
第三行输入密钥字
第四行输入待加密明文
26
abcdefghijklmnopqrstuvwxyz
somuch
a man liberal in his views
加密后如下:
s amh nptsdun pf vum xpwke 
解密后如下:
a man liberal in his views 
--------------------------
密码方阵表如下:
abcdefghijklmnopqrstuvwxyz
bcdefghijklmnopqrstuvwxyza
cdefghijklmnopqrstuvwxyzab
defghijklmnopqrstuvwxyzabc
efghijklmnopqrstuvwxyzabcd
fghijklmnopqrstuvwxyzabcde
ghijklmnopqrstuvwxyzabcdef
hijklmnopqrstuvwxyzabcdefg
ijklmnopqrstuvwxyzabcdefgh
jklmnopqrstuvwxyzabcdefghi
klmnopqrstuvwxyzabcdefghij
lmnopqrstuvwxyzabcdefghijk
mnopqrstuvwxyzabcdefghijkl
nopqrstuvwxyzabcdefghijklm
opqrstuvwxyzabcdefghijklmn
pqrstuvwxyzabcdefghijklmno
qrstuvwxyzabcdefghijklmnop
rstuvwxyzabcdefghijklmnopq
stuvwxyzabcdefghijklmnopqr
tuvwxyzabcdefghijklmnopqrs
uvwxyzabcdefghijklmnopqrst
vwxyzabcdefghijklmnopqrstu
wxyzabcdefghijklmnopqrstuv
xyzabcdefghijklmnopqrstuvw
yzabcdefghijklmnopqrstuvwx

zabcdefghijklmnopqrstuvwxy


-------------------------------------------------------------------

相关图解如下:







  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值