【实验】设计一个加密算法(英文、中文)

    xiaoxiao2021-03-25  89

    实验一、英文加解密

    设计思路:

    现有的ASCII编码方式可以表示全部的英文字符和常用的标点符号,于是选用ASCII编码,可见字符的范围是32~126。 基于字符的分组加密: 输入一串数字作为密钥K,循环使用该数字序列对明文进行加密。 对于每一个可见字符Pi,将其ASCII码的值增加Ki得到Ci,若大于126,则将其数值对126取模再加31,使得最终得到的Ci仍然是可见字符,所有的Ci按顺序输出便得到了密文。 对于不可见字符和ASCII码表示范围之外的字符,不作处理,直接作为密文。 解密: 输入加密时的数字序列作为密钥K。 对于每一个可见字符Ci,将其ASCII码的值减去Ki得到Pi,若小于32,则将其数值减去31再加上126,使得最终得到的Pi仍然是可见字符,所有的Pi按顺序输出便得到了明文。 对于不可见字符和ASCII码表示范围之外的字符,不作处理,直接作为明文。

    程序流程:


    语言:java 基于字符的分组加密: 1.提示输入密钥K,并存储在ArrayList中; 2.使用BufferedInputStream按字节从桌面文件plainText.txt中读入明文(文件使用默认的ANSI编码格式创建并保存),若读取失败抛出异常; 3.将明文按照设计的算法转换为密文; 4.使用BufferedOutputStream按字节将密文输出到桌面文件cipherText.txt,若写入失败抛出异常; 5.循环执行2~4,直到明文读取完毕; 6.将BufferedInputStream和BufferedOutputStream关闭,若关闭失败抛出异常; 解密: 1.提示输入密钥K,并存储在ArrayList中; 2.使用BufferedInputStream按字节从桌面文件cipherText.txt中读入密文,若读取失败抛出异常; 3.将密文按照设计的算法转换为明文; 4.使用BufferedOutputStream按字节将明文输出到桌面文件decryptedText.txt,若写入失败抛出异常; 5.循环执行2~4,直到明文读取完毕; 6.将BufferedInputStream和BufferedOutputStream关闭,若关闭失败抛出异常;

    3、测试结果:

    所有的ASCII可见字符和汉字等特殊字符——密钥为:22

    4、源代码:

    【加密】

    package cryptography; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; public class EncryptionMainOfEnglish { //此处为明文文件路径、密文文件路径 private static final String inFilePath = "C:\\Users\\dell\\Desktop\\plainText.txt"; private static final String outFilePath = "C:\\Users\\dell\\Desktop\\cipherText.txt"; private static BufferedInputStream bufferedInput = null; private static BufferedOutputStream bufferedOutput = null; //密钥储存list private static ArrayList<Integer> keyList = new ArrayList<Integer>(); public static void main(String[] args) throws IOException { // TODO Auto-generated method stub EncryptionMainOfEnglish mm = new EncryptionMainOfEnglish(); String clearString="",cipherString=""; int bytesRead = 0; byte[] bufferIn = new byte[1024]; Scanner scanner = new Scanner(System.in); System.out.print("[encrypted English] Please enter the key sequence(only number):"); String keyString = scanner.next(); scanner.close(); for( int i=0;i<keyString.length();i++ ){ keyList.add( keyString.charAt(i)-'0' ); } try { bufferedInput = new BufferedInputStream( new FileInputStream( inFilePath ) ); bufferedOutput = new BufferedOutputStream( new FileOutputStream( outFilePath ) ); //从文件中按字节读取内容,到文件尾部时read方法将返回-1 while ( (bytesRead = bufferedInput.read(bufferIn) ) != -1) { //将读取的字节转为字符串对象 clearString = new String(bufferIn, 0, bytesRead); System.out.println( "[plainText:]"+clearString ); cipherString = mm.getCipherString( clearString ); System.out.println( "[cipherText:]"+cipherString ); bufferedOutput.write( cipherString.getBytes() ); } }catch(Exception e){ System.err.println("文件读取出现异常!"); e.printStackTrace(); }finally { try { bufferedInput.close(); bufferedOutput.close(); } catch (Exception e2) { // TODO: handle exception System.err.println("缓冲区关闭异常!"); e2.printStackTrace(); } } } public String getCipherString( String clearString ){ String cipherString = ""; char chTemp; for( int i=0;i<clearString.length();i++ ){ chTemp = charASCIIAddKey( clearString.charAt(i),keyList.get(i%keyList.size()) ); cipherString += chTemp; } return cipherString; } // key 值的设定 public char charASCIIAddKey( char clearChar, int key ){ char cipherChar = '0'; int clearASCII = ( int ) clearChar; int cipherASCII = 0; if( 32<=clearASCII && clearASCII<=126 ){ if( ( clearASCII + key ) > 126 ){ cipherASCII = ( clearASCII + key ) % 126 + 31 ; }else { cipherASCII = clearASCII + key ; } cipherChar = ( char ) cipherASCII; }else{ //对于ASCII的不可见字符集,均不作处理 cipherChar = clearChar; } return cipherChar; } }

    【解密】

    package cryptography; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; public class DecryptedMainOfEnglish { //此处为明文文件路径、密文文件路径 private static final String inFilePath = "C:\\Users\\dell\\Desktop\\cipherText.txt"; private static final String outFilePath = "C:\\Users\\dell\\Desktop\\decryptedText.txt"; private static BufferedInputStream bufferedInput = null; private static BufferedOutputStream bufferedOutput = null; //密钥储存list private static ArrayList<Integer> keyList = new ArrayList<Integer>(); public static void main(String[] args) throws IOException { // TODO Auto-generated method stub DecryptedMainOfEnglish mm = new DecryptedMainOfEnglish(); String clearString,cipherString; int bytesRead = 0; byte[] bufferIn = new byte[1024]; Scanner scanner = new Scanner(System.in); System.out.print("Please enter your key:"); String keyString = scanner.next(); scanner.close(); for( int i=0;i< keyString.length();i++ ){ keyList.add( keyString.charAt(i) - '0' ); } try { bufferedInput = new BufferedInputStream( new FileInputStream( inFilePath ) ); bufferedOutput = new BufferedOutputStream( new FileOutputStream( outFilePath ) ); //从文件中按字节读取内容,到文件尾部时read方法将返回-1 while ( (bytesRead = bufferedInput.read(bufferIn) ) != -1) { //将读取的字节转为字符串对象 cipherString = new String(bufferIn, 0, bytesRead); System.out.println( "[cipherText:]"+cipherString ); clearString= mm.getClearString( cipherString ); System.out.println( "[plainText:]"+clearString ); bufferedOutput.write( clearString.getBytes() ); } }catch(Exception e){ System.err.println("文件读取出现异常!"); e.printStackTrace(); }finally { try { bufferedInput.close(); bufferedOutput.close(); } catch (Exception e2) { // TODO: handle exception System.err.println("缓冲区关闭异常!"); e2.printStackTrace(); } } } public String getClearString( String cipherString ){ String clearString = ""; char chTemp; for( int i=0;i<cipherString.length();i++ ){ chTemp = charASCIIMinusKey( cipherString.charAt(i),keyList.get( i%keyList.size() )); clearString += chTemp; } return clearString; } / //解密过程 public char charASCIIMinusKey( char cipherChar, int key ){ char clearChar = '0'; int cipherASCII = ( int ) cipherChar; int clearASCII = 0; if( 32<=cipherASCII && cipherASCII<=126 ){ if( ( cipherASCII - key ) < 32 ){ clearASCII = ( cipherASCII - key - 31 + 126 ) ; }else { clearASCII = cipherASCII - key ; } clearChar = ( char ) clearASCII; }else{ //对于ASCII的不可见字符集,均不作处理 clearChar = cipherChar; } return clearChar; } }

    实验二、中文加解密

    设计思路:

    UTF-8包含全世界所有国家需要用到的字符,是国际编码,通用性强,故选用UTF-8作为本程序的字符编码方式。

    基于字节的分组加密: 输入一串数字,并将其转换为字节作为密钥K,循环使用该字节序列对明文进行加密。 对于每一个明文字节Pi,将其与密钥字节Ki异或得到密文字节Ci,由于UTF-8编码格式的原因,Ki的值不能大于7(即00000111),故在生成密钥字节时便将其对8取模后再转换。 所有的Ci按顺序输出便得到了密文。 解密: 输入一串数字,并将其转换为字节作为密钥K。 密钥字节Ki循环异或每一个密文字节Ci得到明文字节Pi,所有的Pi按顺序输出便得到了密文。

    程序流程:

    语言:java 基于字节的分组加密: 1.提示输入密钥K,转换为模8后的字节并存储在ArrayList中; 2.用InputStreamReader初始化bufferedReader,限定编码格式为UTF-8,用OutputStreamWriter初始化bufferedWriter,限定编码格式为UTF-8; 3.bufferedReader.read();跳过文件起始处的BOM头部; 4.使用bufferedReader从桌面文件plainText.txt读取明文内容(文件使用UTF-8编码格式创建并保存),若读取失败抛出异常; 5.将明文按照设计的算法转换为密文; 6.使用bufferedWriter将密文输出到桌面文件cipherText.txt,若写入失败抛出异常; 7.循环执行4~6,直到明文读取完毕; 8.将bufferedReader和bufferedWriter关闭,若关闭失败抛出异常;

    解密: 1.提示输入密钥K,转换为模8后的字节并存储在ArrayList中; 2.用InputStreamReader初始化bufferedReader,限定编码格式为UTF-8,用OutputStreamWriter初始化bufferedWriter,限定编码格式为UTF-8; 3.使用bufferedReader从桌面文件cipherText.txt读取密文内容,若读取失败抛出异常; 4.将密文按照设计的算法解密为明文; 5.使用bufferedWriter将明文输出到桌面文件decryptedText.txt,若写入失败抛出异常; 6.循环执行3~5,直到密文读取完毕; 7.将bufferedReader和bufferedWriter关闭,若关闭失败抛出异常;

    测试结果:

    百科中对于清明节的介绍——密钥为:456789 经测试,只有密钥字节大小为0、1时,才能够完全解密,包括所有的汉字、标点符号、以及其他特殊的字符。 百科中对于清明节的介绍——密钥为:010101 维基百科中对于密码学的介绍——密钥为:01110

    源代码:

    【加密】

    package cryptography; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Scanner; public class EncryptionMainOfChinese { //此处为明文文件路径、密文文件路径 private static final String inFilePath = "C:\\Users\\dell\\Desktop\\plainText.txt"; private static final String outFilePath = "C:\\Users\\dell\\Desktop\\cipherText.txt"; private static BufferedReader bufferedReader; private static BufferedWriter bufferedWriter; //指定编码格式 private static String encoding ="UTF-8"; //密钥字节数组 private static ArrayList<Byte> keyList = new ArrayList<Byte>(); public static void main(String[] args) throws IOException { // TODO Auto-generated method stub EncryptionMainOfChinese cc = new EncryptionMainOfChinese(); String clearString="",cipherString=""; Scanner scanner = new Scanner( System.in ); System.out.print("[encrypted Chinese] Please enter the key sequence(only number):"); String keyString = scanner.next(); scanner.close(); //得到密钥的字节数组 for( int i=0;i<keyString.length();i++ ){ int temp = keyString.charAt(i)-'0'; keyList.add( (byte) (temp%2) ); } try{ InputStreamReader inputStreamReader = new InputStreamReader ( new FileInputStream( new File( inFilePath ) ),encoding ); bufferedReader = new BufferedReader(inputStreamReader); OutputStreamWriter outputStreamWriter = new OutputStreamWriter ( new FileOutputStream( new File( outFilePath ) ),encoding ); bufferedWriter = new BufferedWriter(outputStreamWriter); /* * 跳过UTF-8编码中的BOM头部 * */ bufferedReader.read(); //开始读取明文 while ((clearString = bufferedReader.readLine()) != null) { System.out.println("[plainText:]"+clearString); cipherString = cc.getCipherString(clearString); System.out.println("[cipherText:]"+cipherString); bufferedWriter.write(cipherString); } }catch(Exception e){ System.err.println("文件读取出现异常!"); e.printStackTrace(); }finally { try { bufferedReader.close(); bufferedWriter.close(); }catch (Exception e2) { // TODO: handle exception System.err.println("缓冲区关闭异常!"); e2.printStackTrace(); } } } public String getCipherString( String clearString ) throws UnsupportedEncodingException{ //得到明文的字节数组--指定编码格式 byte[] clearArray = clearString.getBytes( encoding ); for (int i=0;i<clearArray.length;i++){ clearArray[i] = (byte) ( clearArray[i] ^ keyList.get(i%keyList.size())) ; } //得到密文的字节数组--指定编码格式 String cipherString = new String( clearArray,encoding ); return cipherString; } }

    【解密】

    package cryptography; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Scanner; public class DecryptedMainOfChinese { //此处为明文文件路径、密文文件路径 private static final String inFilePath = "C:\\Users\\dell\\Desktop\\cipherText.txt"; private static final String outFilePath = "C:\\Users\\dell\\Desktop\\decryptedText.txt"; private static BufferedReader bufferedReader; private static BufferedWriter bufferedWriter; //指定编码格式 private static String encoding ="UTF-8"; //密钥字节数组 private static ArrayList<Byte> keyList = new ArrayList<Byte>(); public static void main(String[] args) throws IOException { // TODO Auto-generated method stub DecryptedMainOfChinese cc = new DecryptedMainOfChinese(); String clearString="",cipherString=""; Scanner scanner = new Scanner( System.in ); System.out.print("[encrypted Chinese] Please enter the key sequence(only number):"); String keyString = scanner.next(); scanner.close(); //得到密钥的字节数组 for( int i=0;i<keyString.length();i++ ){ int temp = keyString.charAt(i)-'0'; keyList.add( (byte) (temp%2) ); } try{ InputStreamReader inputStreamReader = new InputStreamReader ( new FileInputStream( new File( inFilePath ) ),encoding ); bufferedReader = new BufferedReader(inputStreamReader); OutputStreamWriter outputStreamWriter = new OutputStreamWriter ( new FileOutputStream( new File( outFilePath ) ),encoding ); bufferedWriter = new BufferedWriter(outputStreamWriter); /* * 代码创建的 utf-8 文件不包含 BOM 头部 * */ //bufferedReader.read(); //开始读取明文 while ((clearString = bufferedReader.readLine()) != null) { System.out.println("[cipherText:]"+clearString); cipherString = cc.getCipherString(clearString); System.out.println("[plainText:]"+cipherString); bufferedWriter.write(cipherString); } }catch(Exception e){ System.err.println("文件读取出现异常!"); e.printStackTrace(); }finally { try { bufferedReader.close(); bufferedWriter.close(); }catch (Exception e2) { // TODO: handle exception System.err.println("缓冲区关闭异常!"); e2.printStackTrace(); } } } public String getCipherString( String clearString ) throws UnsupportedEncodingException{ //得到明文的字节数组--指定编码格式 byte[] clearArray = clearString.getBytes( encoding ); for (int i=0;i<clearArray.length;i++){ clearArray[i] = (byte) ( clearArray[i] ^ keyList.get(i%keyList.size())) ; //clearArray[i] = (byte) ( clearArray[i] ^ keysArray[i%keysArray.length]) ; } //得到密文的字节数组--指定编码格式 String cipherString = new String( clearArray,encoding ); return cipherString; } }

    实验心得:

    1.ASCII码的范围是有限的,但用来表示所有的英文字符和常用标点还是足够的; 2.用Window的记事本编辑器创建UTF-8编码格式的文本时,会自动包含了BOM头部(EF BF BD),我的做法是直接跳过,免得干扰加密和解密; 3.使用代码直接创建UTF-8的文本,不会包含BOM头部; 4.感谢ISO和Unicode联盟,做了这么伟大的事情——将全世界的语言文字统一收录和编码; 5.加解密的设计要注意UTF-8的编码格式,如果异或的字节代表的数值过大,会不符合其编码格式的要求,最后在解密时肯定解不出来; 6.最后限定了密钥字节大小为0、1,可以完全加密和解密; 7.对于明文中的回车,解密文档在其后的字符会出现乱码,这个问题尚未解决。

    转载请注明原文地址: https://ju.6miu.com/read-32924.html

    最新回复(0)