置换密码算法的原理是不改变明文字符,只将字符在明文中的排列顺序改变,从而实现明文信息的加密。置换密码有时又称为换位密码。 矩阵换位法是实现置换密码的一种常用方法。它将明文中的字母按照给的顺序安排在一个矩阵中,然后用根据密钥提供的顺序重新组合矩阵中字母,从而形成密文。例如,明文为attack begins at five,密钥为cipher,将明文按照每行6列的形式排在矩阵中,形成如下形式: a t t a c k b e g i n s a t f i v e 根据密钥cipher中各字母在字母表中出现的先后顺序,给定一个置换: 1 2 3 4 5 6 f = 1 4 5 3 2 6 根据上面的置换,将原有矩阵中的字母按照第1列,第4列,第5列,第3列,第2列,第6列的顺序排列,则有下面形式: a a c t t k b i n g e s a i v f t e 从而得到密文:aacttkbingesaivfte |
- package cn.hdu.edu.encrypt;
- /*
- * 古典密码算法之 置换算法
- * @author ni掌柜
- */
- public class Change {
- //当加密或者解密成功时返回CRYPT_OK,失败时返回CRYPT_ERROR
- private final static int CRYPT_OK = 1;
- private final static int CRYPT_ERROR = 0;
- /*
- * @param initCode 没有加密前的字符串
- * @CRYPT_OK 加密成功
- * @CRYPT_ERROR 加密失败
- */
- public static int encrypt(String initCode)throws Exception{
- //用来输出加密后的字符
- StringBuilder sb = new StringBuilder();
- //获取initCode的字符串长度
- int codeLength = initCode.length();
- //根据这个codeLength来确定要几行6列
- int rows = (int)Math.ceil(codeLength/6.0 );
- //构造一个rows行6列的数组
- char[][] initChar = new char[rows][6];
- //存放initCode中的所有字符,包括空格
- for(int i = 0; i < initChar.length; i++ )
- for(int j=0; j < initChar[0].length; j++){
- //将对应字符放入这个数组中
- try{
- initChar[i][j] = initCode.charAt(
- (i ) * initChar[0].length + j
- );
- }catch(Exception e){
- //多出来的用@表示
- initChar[i][j] = 64;
- }
- }
- //进行如下转换
- /*
- * 00 01 02 03 04 05
- * 10 11 12 13 14 15
- */
- // 1 4 5 3 2 6
- //构造一个rows行6列的数组 作为目标
- char[][] targetChar = new char[rows][6];
- for(int i = 0; i < targetChar.length; i++ )
- for(int j=0; j < targetChar[0].length; j++){
- //第二列的字符是initChar中的第四列的字符
- if(j == 1 ){
- targetChar[i][j] = initChar[i][3];
- }
- //第三列的字符是initChar中的第五列的字符
- else if(j == 2){
- targetChar[i][j] = initChar[i][4];
- }
- //第四列的字符是initChar中的第三列的字符
- else if(j == 3){
- targetChar[i][j] = initChar[i][2];
- }
- //第五列的字符是initChar中的第二列的字符
- else if(j == 4){
- targetChar[i][j] = initChar[i][1];
- }
- //第一和六列的字符不变
- else{
- targetChar[i][j] = initChar[i][j];
- }
- }
- //整合成一个密文
- //==================输出======================
- for(int i = 0; i < targetChar.length; i++ )
- for(int j=0; j < targetChar[0].length; j++){
- sb.append(targetChar[i][j] );
- }
- // ==================输出======================
- // for(int i = 0; i < initChar.length; i++ )
- // for(int j=0; j < initChar[0].length; j++){
- // System.out.print(targetChar[i][j] );
- // }
- //以下就是加密后的字符
- String targetCode = sb.toString();
- System.out.println(targetCode);
- return CRYPT_OK;
- }
- /*
- * @param targetCode 加密后的字符串
- * @CRYPT_OK 解密成功
- * @CRYPT_ERROR 解密失败
- */
- public static int decrypt(String targetCode)throws Exception{
- //用来输出解密后的字符
- StringBuilder sb = new StringBuilder();
- //获取targetCode的字符串长度
- int codeLength = targetCode.length();
- //根据这个codeLength来确定要几行6列
- int rows = (int)Math.ceil(codeLength/6.0 );
- //构造一个rows行6列的数组
- char[][] targetChar = new char[rows][6];
- //存放targetCode中的所有字符,包括空格
- for(int i = 0; i < targetChar.length; i++ )
- for(int j=0; j < targetChar[0].length; j++){
- //将对应字符放入这个数组中
- targetChar[i][j] = targetCode.charAt(
- (i ) * targetChar[0].length + j
- );
- }
- //由于加密的时候是如下变换,现在要变回来
- /*
- * 00 01 02 03 04 05
- * 10 11 12 13 14 15
- */
- // 1 4 5 3 2 6
- //构造一个rows行6列的数组 作为目标
- char[][] initChar = new char[rows][6];
- for(int i = 0; i < initChar.length; i++ )
- for(int j=0; j < initChar[0].length; j++){
- //init第二列的字符是targetChar中的第四列的字符
- if(j == 1 ){
- initChar[i][j] = targetChar[i][3];
- }
- //第三列的字符是targetChar中的第五列的字符
- else if(j == 2){
- initChar[i][j] = targetChar[i][4];
- }
- //第四列的字符是targetChar中的第三列的字符
- else if(j == 3){
- initChar[i][j] = targetChar[i][2];
- }
- //第五列的字符是targetChar中的第二列的字符
- else if(j == 4){
- initChar[i][j] = targetChar[i][1];
- }
- //第一和六列的字符不变
- else{
- initChar[i][j] = targetChar[i][j];
- }
- }
- //整合成一个密文
- //==================输出======================
- for(int i = 0; i < initChar.length; i++ )
- for(int j=0; j < initChar[0].length; j++){
- sb.append(initChar[i][j] );
- }
- // ==================输出======================
- // for(int i = 0; i < initChar.length; i++ )
- // for(int j=0; j < initChar[0].length; j++){
- // System.out.print(targetChar[i][j] );
- // }
- //以下就是init的字符
- String initCode = sb.toString();
- System.out.println(initCode);
- return CRYPT_OK;
- }
- }