20145335郝昊 Java学习心得
密码学代码复写
本学期我们学习了现代密码学这门课程,在上课的时候接触到了很多种类型的密码体制,对于一些典型很通用的密码体制有自己的学习和设计。不论是从密码体制还是密码的加解密算法都有学习和认识。现在把上实验课用c语言实现的算法用java语言重新复写一遍。
-
凯撒密码
-
凯撒密码内容:
是一种移位密码,在第一次java实验课就有学习和设计它将明文加密的算法是将每一个字母依次向后或向前用其它字母来代替需要加密的明文密码,从而计算出密文密码。在字母表中,在移位前先将移动的位数(key)和26取模。Java将字符加上一个正整数即代表在字母表中右移多少位。如果移动的位数是负值,则代表在字母表中左移多少位。
-
实验代码:
//JAVA 凯撒密码
import java.io.*; import java.util.Scanner; public class kaisa { public static void main(String[] args) { System.out.print("请输入密钥: "); Scanner s = new Scanner(System.in); int a = s.nextInt(); C(a); } public static void C(int n) { try { char b[]; BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in)); System.out.println("请输入一段明文: "); String str2 = br2.readLine(); b = str2.toCharArray(); System.out.println("密文为: "); int k = n; for (int i = 0; i < str2.length(); i++) { char ch = (char) ((b[i] - 'a' + k) % 26 + 'a'); System.out.print(ch); } System.out.println("密钥k = " + k); } catch (IOException e) { System.out.println(e.getMessage()); } } }
-
-
注意:
尽管在移动之前已经将移动的位数和26取了模,但通过这种方式实现右移或左移仍可能发生超界。如字母
x
右移4位应该是字母b
,但将字母x增加4后超出26个字母的范围。因此移位后使用两个if语句判断一下,如果向左超界(c<'a'
)则增加26;如果向右超界(c>'z'
)则减去26。此外,由于大写字母和小写字母判断是否超界的依据不同,程序中将字符分为大写和小写分别处理。 -
随机数的生成
-
内容:
随机数的生成要产生随机数,可以使用
Java ap
i中java.lang
包中的Math
类.Math
类以静态方法的方式提供常用的数学方法。用java语言实现1~100中的随机数。 -
实验代码:
//JAVA随机数的生成
import java.util.Random; public class RandomTest { public static void main(String[] args) { int max=20; int min=10; Random random = new Random(); int s = random.nextInt(max)%(max-min+1) + min; System.out.println(s); } }
-
-
希尔排序
-
内容:
先取一个小于
n
的整数d1
作为第一个增量,把文件的全部记录分组。所有距离为d1
的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1
重复上述的分组和排序,直至所取的增量 =1(< …<d2<d1
),即所有记录放在同一组中进行直接插入排序为止。该方法实质上是一种分组插入方法 -
实验代码:
//JAVA 希尔排序
public class Hillshort {
public static int[] a = { 10, 32, 1, 9, 5, 7, 12, 0, 4, 3 }; public static void main(String args[]) { int i; // 循环计数变量 int Index = a.length;// 数据索引变量 System.out.print("排序前: "); for (i = 0; i < Index - 1; i++) System.out.printf("%3s ", a[i]); System.out.println(""); ShellSort(Index - 1); // 选择排序 // // 排序后结果 System.out.print("排序后: "); for (i = 0; i < Index - 1; i++) System.out.printf("%3s ", a[i]); System.out.println(""); }
public static void ShellSort(int Index) {
int i, j, k; // 循环计数变量
int Temp; // 暂存变量
boolean Change; // 数据是否改变
int DataLength; // 分割集合的间隔长度
int Pointer; // 进行处理的位置
DataLength = (int) Index / 2; // 初始集合间隔长度
while (DataLength != 0) // 数列仍可进行分割
{
// 对各个集合进行处理
for (j = DataLength; j < Index; j++) {
Change = false;
Temp = a[j]; // 暂存Data[j]的值,待交换值时用
Pointer = j - DataLength; // 计算进行处理的位置
// 进行集合内数值的比较与交换值
while (Temp < a[Pointer] && Pointer >= 0 && Pointer <= Index) {
a[Pointer + DataLength] = a[Pointer];
// 计算下一个欲进行处理的位置
Pointer = Pointer - DataLength;
Change = true;
if (Pointer < 0 || Pointer > Index)
break;
}
// 与最后的数值交换
a[Pointer + DataLength] = Temp;
if (Change) {
// 打印目前排序结果
System.out.print("排序中: ");
for (k = 0; k < Index; k++)
System.out.printf("%3s ", a[k]);
System.out.println("");
}
}
DataLength = DataLength / 2; // 计算下次分割的间隔长度
}
}
}
-
-
vigenere算法:
-
内容:
人们在单一恺撒密码的基础上扩展出多表密码,称为“维吉尼亚”密码。维吉尼亚密码引入了“密钥”的概念,即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计。
-
实验代码:
//vignerer密码体制
class VigenereCipher { private String sctKey;//sctKey用来存储密匙 int keyLen; //keyLen用来存储密匙的长度 static char[][] vigSquare={ {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O' ,'P','Q','R','S','T','U','V','W','X','Y','Z'}, {'B','C','D','E','F','G','H','I','J','K','L','M','N','O','P' ,'Q','R','S','T','U','V','W','X','Y','Z','A'}, {'C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q' ,'R','S','T','U','V','W','X','Y','Z','A','B'}, {'D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R' ,'S','T','U','V','W','X','Y','Z','A','B','C'}, {'E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S' ,'T','U','V','W','X','Y','Z','A','B','C','D'}, {'F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T' ,'U','V','W','X','Y','Z','A','B','C','D','E'}, {'G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U' ,'V','W','X','Y','Z','A','B','C','D','E','F'}, {'H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V' ,'W','X','Y','Z','A','B','C','D','E','F','G'}, {'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W' ,'X','Y','Z','A','B','C','D','E','F','G','H'}, {'J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X' ,'Y','Z','A','B','C','D','E','F','G','H','I'}, {'K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y' ,'Z','A','B','C','D','E','F','G','H','I','J'}, {'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' ,'A','B','C','D','E','F','G','H','I','J','K'}, {'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A' ,'B','C','D','E','F','G','H','I','J','K','L'}, {'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B' ,'C','D','E','F','G','H','I','J','K','L','M'}, {'O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C' ,'D','E','F','G','H','I','J','K','L','M','N'}, {'P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D' ,'E','F','G','H','I','J','K','L','M','N','O'}, {'Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E' ,'F','G','H','I','J','K','L','M','N','O','P'}, {'R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F' ,'G','H','I','J','K','L','M','N','O','P','Q'}, {'S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G' ,'H','I','J','K','L','M','N','O','P','Q','R'}, {'T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H' ,'I','J','K','L','M','N','O','P','Q','R','S'}, {'U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I' ,'J','K','L','M','N','O','P','Q','R','S','T'}, {'V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J' ,'K','L','M','N','O','P','Q','R','S','T','U'}, {'W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K' ,'L','M','N','O','P','Q','R','S','T','U','V'}, {'X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L' ,'M','N','O','P','Q','R','S','T','U','V','W'}, {'Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M' ,'N','O','P','Q','R','S','T','U','V','W','X'}, {'Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N' ,'O','P','Q','R','S','T','U','V','W','X','Y'}, }; VigenereCipher(String sctKey){ this.sctKey=sctKey; keyLen=sctKey.length(); } // 加密方法,参数为一字符串,代表明文 String encrypt(String plainText){ //len用来存储明文长度,cnt用来记录使用了密匙的那个位置, //cipherText用来存储密文 int len,i,j,k,cnt; String cipherText; char[]ch=new char[1]; String ss; //在加密前,先把明文中的字母全部转换为小写 plainText=plainText.toLowerCase(); cipherText=new String(); len=plainText.length(); cnt=0; for(k=0;k<len;k++){ if(cnt==keyLen){ cnt=0; } ch[0]=plainText.charAt(k); if(ch[0]>='a'&&ch[0]<='z'){ //获得方阵的位置 i=(int)ch[0]-97; j=(int)sctKey.charAt(cnt)-97; ch[0]=vigSquare[i][j]; cnt++; } ss=new String(ch); cipherText=cipherText.concat(ss); } return cipherText; } String decrypt(String cipherText){ //len用来存储明文的长度,cnt用来记录使用到了密匙的那个位置 //plainText用来存储密文 int len,i,j,k,cnt; String plainText; char[] ch=new char[1]; String ss; plainText=new String(); len=cipherText.length(); cnt=0; for(k=0;k<len;k++){ if(cnt==keyLen){ cnt=0; } ch[0]=cipherText.charAt(k); if(ch[0]>='A'&&ch[0]<='Z'){ i=(int)sctKey.charAt(cnt)-97; for(j=0; ;j++){ if(vigSquare[i][j]==ch[0]){ break; } } ch[0]=(char)(j+97); cnt++; } ss=new String(ch); plainText=plainText.concat(ss); } return plainText; } String getSctKey(){ return sctKey; } } public class vigenere{ public static void main(String[] args){ VigenereCipher a=new VigenereCipher("good"); VigenereCipher b=new VigenereCipher("bad"); String sctKey,s,s1,s2; s="June six,Allied forces will land in the Normandy."; System.out.println("测试用的消息为:"+s); sctKey=a.getSctKey(); System.out.println("使用用密匙"+sctKey+": "); s1=a.encrypt(s); System.out.println("加密后的消息:"+s1); s2=a.decrypt(s1); System.out.println("解密后的消息:"+s2); sctKey=b.getSctKey(); System.out.println("使用用密匙"+sctKey+": "); s1=b.encrypt(s); System.out.println("加密后的消息:"+s1); s2=b.decrypt(s1); System.out.println("解密后的消息:"+s2); } }
-
-
注意:
>设计一个`vigenere`密码类,类的对象各自拥有不用的密匙。用不用对象加密相同的明文,将会获得不同的密文。`vigenere`密码是最古老、最著名的多表密码体制之一,加密过程如下:设密匙为`K=k1k2.......kn`,明文为`M=m1m2.......mn`,密文为`C=c1c2.......cn`,其中`k1k2.........kn`,`m1m2...........mn........cn`,每个都代表一个字母。将字母`A`到`Z`编号,从`0`到`25`,那么它们之间有这样的对应关系:`ci=(mi+ki)mod26`。例如,`M=data security,K=best`,那么首先将`M`分解成长为`4`的序列:`data secu rity`每一节都使用密匙`K=best`进行加密,得到序列:`EELT TIUN SMLR`将明文的空格添加进去,就得到密文:`EELT TIUNSMLR`出于密码体制的需要,密文中的字母全部使用大写字母。
-
心得体会:
>java语言是一门十分有用的语言,可能在学习起来存在难度,但只要坚持还是会有很大的效果,虽然以上的密码学代码复写有些函数是从网上借鉴来的,但是依然学习到了有关知识,就比如`java.lang`包中的`Math`类用来产生随机数等小问题都是经过学习和借鉴得到的。总之坚持学习总是会有效果的。