ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

网络加密算法之置换与替代算法

2021-05-15 22:04:05  阅读:145  来源: 互联网

标签:return String int 置换 System char 算法 length 加密算法


主程序

/**
 * 程序控制台
 * @author 落霞不孤
 */
public class Main {
    private static Scanner in = new Scanner(System.in);

    public static void main(String[] args) {
        while (true) {
            System.out.println("实现的密码算法");
            System.out.println("\t1.替代算法");
            System.out.println("\t2.置换算法");
            System.out.println("\t3.退出");
            System.out.print("请输入需要的密码算法:");
            int choice = in.nextInt();
            switch (choice) {
                case 1:
                    chooseFun(new SubstitutePassword());
                    break;
                case 2:
                    chooseFun(new ReplacementPassword());
                    break;
                case 3:
                    in.close();
                    return;
                default:
                    System.out.println("选择有误~请重新输入...");
            }
        }

    }

    private static void chooseFun(AbstractPassword abstractPassword) {
        System.out.println("密码算法功能:");
        System.out.println("\t1.加密");
        System.out.println("\t2.解密");
        System.out.print("请输入需要的密码算法功能:");
        int fun = in.nextInt();
        if (fun == 1) {
            System.out.print("请输入明文:");
            in.nextLine();
            String plaintext = in.nextLine();
            System.out.println("明文加密后的密文:" + abstractPassword.encryption(plaintext));
        }
        if (fun == 2) {
            System.out.print("请输入密文:");
            in.nextLine();
            String ciphertext = in.nextLine();
            System.out.println("密文解密后的明文:" + abstractPassword.decryption(ciphertext));
        }
    }
}

密码加密解密接口

/**
 * 加密解密接口
 * @author 落霞不孤
 */
public interface FindPassword {
    /**
     * 加密
     * @param plaintext 明文
     * @return 加密后的密文
     */
    String encryption(String plaintext);

    /**
     * 解密
     * @param ciphertext 密文
     * @return 解密后的明文
     */
    String decryption(String ciphertext);
}

密码加密解密抽象类

/**
 * 抽象类密码
 * @author 落霞不孤
 */
public abstract class AbstractPassword implements FindPassword {
    public static String key;
    public static int k;

    /**
     * 输入密钥 k
     */
    void inputK() {
        Scanner in = new Scanner(System.in);
        System.out.print("请输入密钥k:");
        k = in.nextInt();
    }

    /**
     * 输入密钥 key
     */
    void inputKey() {
        Scanner in = new Scanner(System.in);
        System.out.print("请输入密钥key:");
        key = in.nextLine();
    }


    /**
     * 找出字母的位置,从0算起
     *
     * @param c 字母
     * @return 字母在字母表的位置
     */
    int posInAlphabet(char c) {
        int pos = Character.toLowerCase(c) - 97;
        return pos;
    }

    /**
     * 找出c偏移量为k的字母
     *
     * @param c 字母
     * @param k 偏移量
     * @return c偏移量为k的字母
     */
    char findAlphabetByPos(char c, int k) {
        if (Character.isLowerCase(c)) {
            return (char) ((posInAlphabet(c) + k) % 26 + 97);
        }
        return (char) (char) ((posInAlphabet(c) + k) % 26 + 65);
    }

    /**
     * 获得密钥中每个字母出现的顺序
     *
     * @param cipher 密钥
     * @return map<Character, Integer> k 是字母,v是出现的顺序
     */
    public Map<Character, Integer> findCipherPos(String cipher) {
        Map<Character, Integer> map = new HashMap<Character, Integer>();
        int weight = 0;
        char min;
        // 每次找出cipher的最小字符,并赋权重
        while (cipher.length() > 0) {
            for (int i = 0; i < cipher.length(); i++) {
                min = cipher.charAt(i);
                for (int j = i + 1; j < cipher.length(); j++) {
                    if (Character.toUpperCase(min) > Character.toUpperCase(cipher.charAt(j))) {
                        min = cipher.charAt(j);
                    }
                }
                // 找出最小的字母后,用""取代
                cipher = cipher.replace(Character.toString(min), "");
                map.put(min, weight++);
                break;
            }
        }
        return map;
    }

    /**
     * 将明文变成二维数组
     * @param plaintext 明文
     * @return 明文的二维数组
     */
    public char[][] getCipherTextArr(String plaintext) {
        // 去除明文空格
        plaintext = plaintext.replace(" ", "");
        int col = key.length();
        int row = (int) Math.ceil(plaintext.length()*1.0 / col);
        // 存储明文的二维数组
        char[][] plainArr = new char[row][col];
        // 存储密文的二维数组
        char[][] chars;
        // 把明文存入明文的二维数组,用空格填充不存在的元素
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (i * col + j >= plaintext.length()) {
                    plainArr[i][j] = ' ';
                } else {
                    plainArr[i][j] = plaintext.charAt(i * col + j);
                }
            }
        }
        chars = rule(plainArr);
        return chars;
    }

    /**
     * 获取按照密钥字母顺序加密或者解密的二维数组
     * @param text 密文或明文的二维数组
     * @return 加密或者解密的二维数组
     */
    private char[][] rule(char[][] text) {
        char[][] chars = new char[text.length][text[0].length];
        Map<Character, Integer> map = findCipherPos(key);
        // 加密或解密
        int j = 0;
        for (char tmp : key.toCharArray()) {
            int pos = map.get(tmp);
            for (int i = 0; i < text.length; i++) {
                chars[i][j] = text[i][pos];
            }
            j++;
        }
        return chars;
    }

    /**
     * 按照约定打印密文数组
     * @param chars 密文数组
     * @return 密文
     */
    public String getCipherTextArrStr(char[][] chars) {
        StringBuilder sb = new StringBuilder();
        Map<Character, Integer> cipherPos = findCipherPos(key);
        for (char tmp : key.toCharArray()) {
            int pos = cipherPos.get(tmp);
            for (int i = 0; i < chars.length; i++) {
                if(chars[i][pos] != ' ') {
                    sb.append(chars[i][pos]);
                }
            }
        }
        return sb.toString();
    }

    /**
     * 将密文变成二维数组
     * @param cipherText 密文
     * @return 密文的二维数组
     */
    public char[][] getPlainTextArr(String cipherText) {
        // 去除密文空格
        cipherText = cipherText.replace(" ", "");
        int col = key.length();
        int row = (int) Math.ceil(cipherText.length()*1.0 / col);
        // 存储密文的二维数组
        char[][] plainArr = new char[row][col];
        // 把密文存入二维数组
        // 不是填满矩阵
        boolean flag = col * row > cipherText.length();
        for (int i = 0; i < row; i++) {
            // 统计列数
            int count = 0;
            for (int j = i; j <= cipherText.length(); j+=row) {
                // 填充空格
                if (i * col + count >= cipherText.length()) {
                    plainArr[i][count] = ' ';
                } else if(flag) {
                    if (count > 1) {
                        j--;
                    }
                    if (j == cipherText.length()) {
                        j = cipherText.length() - 1;
                    }
                    if (j >= cipherText.length()) {
                        j -= row;
                    }
                    plainArr[i][count] = cipherText.charAt(j);
                } else {
                    if (j == cipherText.length()) {
                        break;
                    }
                    plainArr[i][count] = cipherText.charAt(j);
                }
                count++;
            }
        }
        return plainArr;
    }

    /**
     * 将密文的二维数组解密,返回明文
     * @param cipherArr 密文的二维数组解密
     * @return 明文
     */
    public String getPlainTextArrStr(char[][] cipherArr) {
        StringBuilder sb = new StringBuilder();
        char[][] tmp = rule(cipherArr);
        char[][] plainArr = rule(tmp);
        for (char[] chars : plainArr) {
            for (int j = 0; j < plainArr[0].length; j++) {
                if (chars[j] != ' ') {
                    sb.append(chars[j]);
                }
            }
        }
        return sb.toString();
    }
}

置换算法具体实现

/**
 * 置换密码
 * @author 落霞不孤
 */
public class ReplacementPassword extends AbstractPassword{
    @Override
    public String encryption(String plaintext) {
        inputKey();
        char[][] cipherTextArr = getCipherTextArr(plaintext);
        return getCipherTextArrStr(cipherTextArr);
    }

    @Override
    public String decryption(String ciphertext) {
        inputKey();
        char[][] cipherTextArr = getPlainTextArr(ciphertext);
        return getPlainTextArrStr(cipherTextArr);
    }
}

替代算法

/**
 * 替代算法
 * @author 落霞不孤
 */
public class SubstitutePassword extends AbstractPassword{
    @Override
    public String encryption(String plaintext) {
        inputK();
        char[] chars = plaintext.toCharArray();
        StringBuilder sb = new StringBuilder();
        for (char ch : chars) {
            if (Character.isLetter(ch)) {
                char e = findAlphabetByPos(ch, k);
                sb.append(e);
            } else {
                sb.append(ch);
            }
        }
        return sb.toString();
    }

    @Override
    public String decryption(String ciphertext) {
        inputK();
        char[] chars = ciphertext.toCharArray();
        StringBuilder sb = new StringBuilder();
        for (char ch : chars) {
            if (Character.isLetter(ch)) {
                if (posInAlphabet(ch) < k) {
                    // 找出密文字母在字母表位置,例如a,字母表位置为1,密钥假设k=2
                    // 计算出 newPos = 1 是需要倒退的距离,从z开始倒退
                    // 即可得到明文应该是y
                    int newPos = posInAlphabet(ch) + 1 - k;
                    if (Character.isLowerCase(ch)) {
                        sb.append(findAlphabetByPos('z', newPos));
                    } else {
                        sb.append(findAlphabetByPos('Z', newPos));
                    }
                } else {
                    sb.append(findAlphabetByPos(ch, -k));
                }
            } else {
                sb.append(ch);
            }
        }
        return sb.toString();
    }
}

标签:return,String,int,置换,System,char,算法,length,加密算法
来源: https://blog.csdn.net/weixin_43783834/article/details/116864406

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有