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

2021/5/15 22:25:36

本文主要是介绍网络加密算法之置换与替代算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

主程序

/**
 * 程序控制台
 * @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();
    }
}


这篇关于网络加密算法之置换与替代算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程