2024-03-21
原文作者:小小工匠 原文地址: https://artisan.blog.csdn.net/article/details/136464488

202403212042277951.png


Pre

PKI - 02 对称与非对称密钥算法


概述

凯撒密码是一种简单的替换加密技术,也称为移位密码。它是古典密码学中最早的密码之一,得名于古罗马军队领袖凯撒·尤利乌斯(Julius Caesar),据说他曾经使用过这种加密方法。

恺撒密码,也称为恺撒加密或恺撒变换,是一种最古老且最简单的密码之一。它的原理很简单,就是通过将明文中的每个字母按照字母表顺序向后(或向前)移动固定的位置来进行加密。这个固定的位置就是密钥,通常用一个整数来表示,称为偏移量。

例如,当偏移量为3时,明文中的字母A将被加密为D,B被加密为E,以此类推。如果偏移量是负数,则向前移动相应的位置。这种方法相当于在字母表上进行循环移位。

加密过程

  1. 确定偏移量(密钥)。
  2. 对于要加密的明文中的每个字母,按照偏移量进行移位。
  3. 输出密文。

202403212042286262.png

解密过程

  1. 知道加密时使用的偏移量。
  2. 对于密文中的每个字母,按照偏移量的负值进行移位。
  3. 输出明文。

示例

假设明文为:“HELLO”,偏移量为3。

  • 加密:H + 3 = K,E + 3 = H,L + 3 = O,L + 3 = O,O + 3 = R
  • 密文为:“KHOOR”

安全性

恺撒密码的安全性非常低,因为它只有26种可能的密钥(偏移量),攻击者可以很容易地通过穷举法来破解。因此,它更多地被用于教学和娱乐,而不是实际的安全通信中。

应用

恺撒密码虽然安全性低,但在教学、编程练习以及简单的加密需求中仍有一定的应用价值。


Code 实现 凯撒密码

    public class KaiserDemo {
        public static void main(String[] args) {
            // 定义原文
            String input = "Hello Artisan";
            // 把原文右边移动3位
            int key = 3;
            // 凯撒加密
            String s = encrypt(input, key);
            System.out.println("加密 " + s);
            String s1 = decrypt(s, key);
            System.out.println("明文 " + s1);
        }
    
        /**
         * 解密
         *
         * @param s   密文
         * @param key 密钥
         * @return
         */
        public static String decrypt(String s, int key) {
            char[] chars = s.toCharArray();
            StringBuilder sb = new StringBuilder();
            for (char aChar : chars) {
                int b = aChar;
                // 偏移数据
                b -= key;
                char newb = (char) b;
                sb.append(newb);
            }
            return sb.toString();
        }
    
        /**
         * 加密
         *
         * @param input 原文
         * @return
         */
        public static String encrypt(String input, int key) {
            // 抽取快捷键 ctrl + alt + m
            // 把字符串变成字节数组
            char[] chars = input.toCharArray();
            StringBuilder sb = new StringBuilder();
            for (char aChar : chars) {
                int b = aChar;
                // 往右边移动3位
                b = b + key;
                char newb = (char) b;
                sb.append(newb);
            }
            return sb.toString();
        }
    }

202403212042289653.png


字母频率分析攻击

字母频率分析是一种破译凯撒密码的常见方法。它利用了自然语言中字母的分布特征,即某些字母在文本中出现的频率比其他字母更高。

步骤

  1. 收集密文。
  2. 统计密文中每个字母出现的次数,得到各个字母的频率。
  3. 将频率从高到低排序。
  4. 将排序后的频率与自然语言中字母的频率进行比较,找到最可能对应的字母。
  5. 推断偏移量,并进行解密。

举例

假设有一段密文为:“WKLQJ LV NHHS”。

  1. 统计各个字母出现的次数:

    • W: 1次
    • K: 1次
    • L: 1次
    • Q: 1次
    • J: 1次
    • V: 1次
    • N: 1次
    • H: 2次
    • S: 1次
  2. 按频率排序:H > W, K, L, Q, J, V, N, S

  3. 与自然语言中英文字母的频率进行比较,发现"H"的频率较高,可能对应原文中的"E"。

  4. 推断偏移量为3。

  5. 解密密文:“WKLQJ LV NHHS” -> “THINK IS MEET”

安全性
凯撒密码的安全性很低,因为它只有26种可能的密钥(偏移量),而且容易受到字母频率分析等简单攻击的破解。

Code解密凯撒密码

    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @author 小工匠
     * @version 1.0
     * @mark: show me the code , change the world
     */
    public class CaesarCipherBreaker {
    
        public static void main(String[] args) {
            String ciphertext = "Khoor#Duwlvdq";
            crackCaesarCipher(ciphertext);
        }
    
        // 字母频率分析破解凯撒密码
        public static void crackCaesarCipher(String ciphertext) {
            // 统计密文中每个字母出现的次数
            Map<Character, Integer> frequencies = new HashMap<>();
            for (char c : ciphertext.toCharArray()) {
                if (Character.isLetter(c)) {
                    char uppercaseChar = Character.toUpperCase(c);
                    frequencies.put(uppercaseChar, frequencies.getOrDefault(uppercaseChar, 0) + 1);
                }
            }
    
            // 将统计结果按出现次数从高到低排序
            frequencies.entrySet().stream()
                    .sorted((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()))
                    .forEach(entry -> {
                        char letter = entry.getKey();
                        int frequency = entry.getValue();
                        System.out.println(letter + ": " + frequency);
                        int offset = letter - 'E';
                        if (offset < 0) {
                            offset += 26;
                        }
                        String decryptedText = decryptCaesarCipher(ciphertext, offset);
                        System.out.println("Decrypted Text with offset " + offset + ": " + decryptedText);
                    });
        }
    
        // 凯撒密码解密
        public static String decryptCaesarCipher(String ciphertext, int offset) {
            StringBuilder plaintext = new StringBuilder();
            for (char c : ciphertext.toCharArray()) {
                if (Character.isLetter(c)) {
                    char baseChar = Character.isLowerCase(c) ? 'a' : 'A';
                    int index = (c - baseChar - offset + 26) % 26;
                    plaintext.append((char) (baseChar + index));
                } else {
                    plaintext.append(c);
                }
            }
            return plaintext.toString();
        }
    }

我们对每个出现频率的字母都尝试解密文本,并输出每个偏移量对应的解密文本

202403212042292844.png

发现我们可以读懂,解密成功

202403212042298635.png

小结

尽管凯撒密码很容易理解和实现,但由于它的简单性,它并不安全,容易受到 字母频率分析等攻击 。因此,现代加密通常不再使用凯撒密码,而是使用更加复杂的加密算法来保护数据的安全。

202403212042305626.png

阅读全文