一、手写简单加密算法(凯撒密码)

  1. 首先,我们需要知道几个基本概念:
  1. 明文:原始信息。
  2. 密钥:加密与解密算法的参数,直接影响对明文进行变换的结果。
  3. 密文:对明文进行变换的结果。
  4. 加密算法:以密钥为参数,对明文进行多种置换和转换的规则和步骤,变换结果为密文。
  5. 解密算法:加密算法的逆变换,以密文为输入、密钥为参数,变换结果为明文。

1. 凯撒密码介绍

  1. 凯撒密码作为一种最为古老的加密技术,在古罗马的时候都已经很流行,他的基本思想是:通过把字母移动一定的位数来实现加密和解密。明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。
  2. 例如,当偏移量是 3 的时候,所有的字母 A 将被替换成 DB 变成 E,由此可见,位数就是凯撒密码加密和解密的密钥。<br /> 字符串”ABC”的每个字符都右移 3 位则变成”DEF”,解密的时候”DEF”的每个字符左移 3 位即能还原,如下图所示:
  3. ![图1.png](https://cdn.nlark.com/yuque/0/2022/png/25780490/1642943964749-730ac85d-d510-442e-aa8a-f1827a60fa01.png#clientId=u3c0030a6-0d15-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=ued1dd5eb&margin=%5Bobject%20Object%5D&name=%E5%9B%BE1.png&originHeight=230&originWidth=482&originalType=binary&ratio=1&rotation=0&showTitle=false&size=85333&status=done&style=none&taskId=ub73c9c7e-2c05-444c-ae45-5bb72d82c82&title=)
  1. public class CaesarDemo {
  2. private static final String str = "hei ma!";
  3. private static final int key = 3;
  4. public static void main(String[] args) {
  5. String encrypt = encrypt(str,key);
  6. System.out.println("加密后的文本:" + encrypt);
  7. String decrypted = decrypted(encrypt,key);
  8. System.out.println("解密后的文本:" + decrypted);
  9. }
  10. /**
  11. * 加密
  12. * @param input 数据源(需要加密的数据)
  13. * @param key 秘钥,即偏移量
  14. * @return 返回加密后的数据
  15. */
  16. public static String encrypt(String input,int key) {
  17. char[] charArray = input.toCharArray();
  18. for (int i = 0; i < charArray.length; i++) {
  19. //字符转换成 ASCII 码值
  20. int ascii = charArray[i];
  21. //字符偏移,例如 a->b
  22. ascii = ascii + key;
  23. //ASCII 码值转换为 char
  24. char newChar = (char) ascii;
  25. //替换原有字符
  26. charArray[i] = newChar;
  27. //以上 4 行代码可以简写为以下两种任一行
  28. //charArray[i] = (char) (charArray[i] + key)
  29. //charArray[i] += key;
  30. }
  31. return new String(charArray);
  32. }
  33. //解密:就是加密的反操作
  34. public static String decrypted(String input,int key) {
  35. char[] charArray = input.toCharArray();
  36. for (int i = 0; i < charArray.length; i++) {
  37. charArray[i] -= key;
  38. }
  39. return new String(charArray);
  40. }
  41. }

2. 破解凯撒密码-频率分析法

  1. 如果我们知道一个密码是用凯撒密码加密的,可以使用暴力破解法来解密:凯撒移位密码只有25种密钥,最多就是将这25种可能性挨个检测一下可以了。
  2. 那在不知道的前提下,又怎样判断是凯撒密码呢?这得用到 **频率分析法**。
  3. 在任何一种书面语言中,不同的字母或字母组合出现的频率各不相同。而且,对于以这种语言书写的任意一段文本,都具有大致相同的特征字母分布。
  4. 比如,在英语中,字母 E 出现的频率很高,而 X 则出现得较少。英语文本中典型的字母分布情况如下图所示:

图3.png

破解流程:
1. 统计密文里出现次数最多的字符,例如出现次数最多的字符是是’h’。
2. 计算字符’h’到’e’的偏移量,值为 3,则表示原文偏移了 3 个位置。
3. 将密文所有字符恢复偏移 3 个位置。

注意点:

  1. 统计密文里出现次数最多的字符时,需多统计几个备选,因为最多的可能是空格或者其他字符。
  2. 短文可能严重偏离标准频率,假如文章少于100个字母,那么对它的解密就会比较困难,而且不是所有文章都适用标准频度.

二.对称加密

1. 概述

  1. 加密和解密都使用同一把密钥,这种加密方法称为对称加密,也称为单密钥加密。
  2. 简单理解为:加密解密都是同一把钥匙。 ![图4.png](https://cdn.nlark.com/yuque/0/2022/png/25780490/1642944031712-f832ddf2-f553-49a4-a0cf-4fe4038f07ca.png#clientId=u3c0030a6-0d15-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=uac33d10a&margin=%5Bobject%20Object%5D&name=%E5%9B%BE4.png&originHeight=194&originWidth=440&originalType=binary&ratio=1&rotation=0&showTitle=false&size=44970&status=done&style=none&taskId=ufd5bdbea-a901-4a51-a858-19e7bb5f650&title=)
  3. 上节中学到的凯撒密码就属于对称加密,他的字符偏移量即为密钥。
  4. 基于“对称密钥”的加密算法主要有DES算法,3DES算法,AES算法,Blowfish算法,RC5算法和IDEA算法等等,我们这里主要介绍DES算法和AES算法。

2.对称密码常用的数学运算

对称密码当中有几种常用到的数学运算。

◆移位和循环移位
  移位就是将一段数码按照规定的位数整体性地左移或右移。循环右移就是当右移时,把数码的最后的位移到数码的最前头,循环左移正相反。

  1. 例如,对十进制数码12345678循环右移1位(十进制位)的结果为81234567,而循环左移1位的结果则为23456781。<br />**◆置换**<br />  就是将数码中的某一位的值根据置换表的规定,用另一位代替。它不像移位操作那样整齐有序,看上去杂乱无章。这正是加密所需,被经常应用。<br />**◆扩展**<br />  就是将一段数码扩展成比原来位数更长的数码。扩展方法有多种,例如,可以用置换的方法,以扩展置换表来规定扩展后的数码每一位的替代值。<br />**◆压缩**<br />  就是将一段数码压缩成比原来位数更短的数码。压缩方法有多种,例如,也可以用置换的方法,以表来规定压缩后的数码每一位的替代值。<br />**◆异或**<br />  这是一种二进制布尔代数运算。异或的数学符号为⊕ ,它的运算法则如下:<br /> 11 = 0 <br /> 00 = 0 <br /> 10 = 1 <br /> 01 = 1 <br />  也可以简单地理解为,参与异或运算的两数位如相等,则结果为0,不等则为1。<br />**◆迭代**<br />  迭代就是多次重复相同的运算,这在密码算法中经常使用,以使得形成的密文更加难以破解。

总结:这些运算主要是对比特位进行操作,其共同目的就是把被加密的明文数码尽可能深地打乱,从而加大破译的难度。

三.对称加密算法

1. DES算法

①.简介

  1. DESData Encryption Standard(数据加密标准)的缩写。它是由IBM公司研制的一种对称密码算法,美国国家标准局于1977年公布把它作为非机要部门使用的数据加密标准,三十年来,它一直活跃在国际保密通信的舞台上,扮演了十分重要的角色。
  2. DES是一个分组加密算法,典型的DES64位为分组对数据加密,加密和解密用的是同一个算法。它的密钥长度是56位(因为每个第8 位都用作奇偶校验),密钥可以是任意的56位的数,其保密性依赖于密钥。
  3. DES加密的算法框架大致如下:

首先要生成一套加密密钥,从用户处取得一个64位长的密码口令,然后通过等分、移位、选取和迭代形成一套16个加密密钥,分别供每一轮运算中使用。

  1. DES64位(bit)的明文分组M进行操作,M经过一个初始置换IP,置换成m0。将m0明文分成左半部分和右半部分,各32位长。
  2. 然后进行16轮完全相同的运算(迭代),在每一轮运算过程中数据与相应的密钥结合。

经过16轮迭代后,左、右半部分合在一起经过一个末置换(数据整理),这样就完成了加密过程。
加密流程如图所示:

  1. ![des.png](https://cdn.nlark.com/yuque/0/2022/png/25780490/1642944102521-0cd5c548-155d-4b11-baa6-99e7d362890f.png#clientId=u3c0030a6-0d15-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=ub2362f25&margin=%5Bobject%20Object%5D&name=des.png&originHeight=307&originWidth=291&originalType=binary&ratio=1&rotation=0&showTitle=false&size=42910&status=done&style=none&taskId=ua51e806c-e5d0-43ce-ae9d-d0337d712e5&title=)

②代码实现

  1. import java.security.Key;
  2. import javax.crypto.Cipher;
  3. import javax.crypto.spec.SecretKeySpec;
  4. public class DesTest {
  5. public static void main(String[] args) throws Exception {
  6. String str = "这是原文";
  7. String psw = "12345678";
  8. String encrypt = encrypt(str, psw);
  9. System.out.println("加密后:"+encrypt);
  10. String decrypt = decrypt(encrypt, psw);
  11. System.out.println("解密后:"+decrypt);
  12. }
  13. public static String encrypt(String original,String psw) throws Exception {
  14. //创建加密对象,参数为加密算法
  15. Cipher cipher = Cipher.getInstance("DES");
  16. // 调用自己的方法生成密钥
  17. Key key = getKey(psw);
  18. /**
  19. * 初始化加密器
  20. * 参数 1:加密模式
  21. * 参数 2:密钥
  22. */
  23. cipher.init(Cipher.ENCRYPT_MODE, key);
  24. //执行加密,解密后得到的字节数组
  25. byte[] doFinal = cipher.doFinal(original.getBytes());
  26. //将自己数组用 Base64 编码,转换为字符串
  27. String encode = Base64.encode(doFinal);
  28. return encode;
  29. }
  30. /**
  31. * 这个方法可以让任意长度的密码转成64位的密码
  32. * 1. 从指定字符串生成密钥,密钥所需的字节数组长度为 8 位
  33. * 2. 不足 8 位时后面补 0,超出 8 位只取前 8 位
  34. */
  35. private static SecretKeySpec getKey(String psw) {
  36. byte[] buffer = new byte[8];
  37. byte[] bytes = psw.getBytes();
  38. for(int i=0;i<buffer.length&&i<bytes.length;i++){
  39. buffer[i]=bytes[i];
  40. }
  41. return new SecretKeySpec(buffer, "DES");
  42. }
  43. public static String decrypt(String original,String psw) throws Exception{
  44. //获取加密器(同时也是解密器)
  45. Cipher cipher = Cipher.getInstance("DES");
  46. //获取密钥
  47. Key key = getKey(psw);
  48. //初始化密码器,设置为解密模式
  49. cipher.init(Cipher.DECRYPT_MODE, key);
  50. //解密。注意,这里需要将传入的原文使用 Base64 编码转换为 byte,因为加密后的密文是用 Base64 编码的
  51. byte[] doFinal = cipher.doFinal(Base64.decode(original));
  52. //将解密后的字节数组转换为字符串
  53. return new String(doFinal);
  54. }
  55. }

2. Base64编码

①简介

  1. 加密后的结果是字节数组,这些被加密后的字节在码表(例如GBK UTF-8 码表)上找不到对应字符,会出现乱码,当乱码字符串再次转换为字节数组时,长度会变化,导致解密失败,所以转换后的数据是不安全的。
  2. 使用 Base64 对字节数组进行编码,任何字节都能映射成对应的 Base64 字符,之后能恢复到字节数组,利于加密后数据的保存和传输,所以转换是安全的。
  3. Base64码表如下:

②编解码原理

a、当字符串字符个数为3的整数倍时:

  1. 比如字符串“ABC”,其在计算机内存中的 十六进制表示为 414243,十进制表示为“65”“66”“67”;二进制表示为
  2. 01000001  01000010  01000011  将这三个二进制数依次取6bit

,010000/01 0100/0010 01/000011  就转换成了:

  1. 010000 010100 001001 000011,将这四个二进制数转换成十六制数为:

10,14,9,3,十进制数位为16,20,9,3。对照上面的码表,分别查

找出对应的字符为Q,U,J,D。

  1. 也是就说字符串“ABC”经过BASE64编码后得 出“QUJD”。这是最简单的情况,即ASCII码字符数刚好可以被3整除。接着继续讨论余数为2、为1的情况。

b、当字符串字符个数除以3余数为2时:

  1. 比如字符串“ce”,其在内存中十六进制表示为6365;十 进制表示表示99101;二进制表示为
  2. 01100011 01100101 依次取6bit

011000/11 0110/0101 这时,第3个字符不足6位,在后面补零,也就

是0101变成010100。转换结果为

  1. 011000 110110 010100  这3个二进 制数转换成十六制数为183614;十进制数位为245420。对照码表 得出结果“Y2U”。编码后的字符个数不足4位,用“=”填充,最后编码得出“Y2U=”。

c、当余数为1时:

  1. 比如字符串“{”,其在内存中的十六进制表示为$7B,十进制为 123,二进制位表示为
  2. 01111011 依次取6bit
  3. 011110/11 补0后为

011110/110000  转换结果为011110和110000。这两个二进制数转换成

十六进制数为1E,30,十进制数为30,48。对照码表得出结果为“ew”,补上

“=”,最后编码得出“ew= =”。解码也很简单,是编码的逆过程,即将每 个字符对照码表换算成6bit的二进制数,然后重组起来,按8位进行截取,得出原码。

3. 3DES和AES算法

①3DES算法

  1. DES 的安全性首先取决于密钥的长度。密钥越长,破译者利用穷举法搜索密钥的难度就越大。DES采用**64bit分组长度**和**56bit密钥长度**:<br />![DES破解.png](https://cdn.nlark.com/yuque/0/2022/png/25780490/1642944360708-48291709-5a64-4122-a4cc-87bea0c83092.png#clientId=u3c0030a6-0d15-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=ufb70459f&margin=%5Bobject%20Object%5D&name=DES%E7%A0%B4%E8%A7%A3.png&originHeight=85&originWidth=800&originalType=binary&ratio=1&rotation=0&showTitle=false&size=6815&status=done&style=none&taskId=ufb5cda34-99a9-414b-b0b0-4bc9ef0400b&title=)
  2. 随着软硬件技术的发展,多核CPU、分布式计算、量子计算等理论的实现,DES在穷举方式的暴力攻击下还是相当脆弱的,因此很多人想办法用某种算法替代它,面对这种需求广泛被采用的有两种方案: <br /> 1. 设计一套全新的算法,例如AES,这个在后面会说到。 <br /> 2. 为了保护已有软硬件的投资,仍使用DES,但使用多个密钥进行多次加密,这就是多重DES加密。
  3. 例如后来演变出的 **3-DES** 算法使用了 3 个独立密钥(密钥长度为168bit)进行三重 DES 加密,这就比 DES 大大提高了安全性。如果 56 DES 用穷举搜索来破译需要 256 次运算,而 3-DES 则需要 2112 次。

3des.jpg

②AES算法

a.简介
  1. 3DES缺点是算法运行相对较慢。因为原来DES是为70年代的硬件设计的,算法代码并不是很高效,而3DESDES算法的3轮迭代,因此更慢。而且DES3DES的分组大小都是64bit3DES密钥长度却是168bit,处于加密效率和安全的考虑,需要更大的分组长度。于是AES应运而生。
  2. Advanced Encryption Standard 高级加密标准,该标准是美国国家标准技术研究所于2001年颁布的。AES旨在取代DES成为广泛使用的标准,2006AES已成为最流行的对称加密算法。
  3. AES使用的**分组大小为128bit**,密钥长度可以为128192256 bit。最简单最常用的也就是 **128 bit(16字节)** 的密钥。
  4. **b.算法原理**
  5. AES 加密过程涉及到 4 种操作:字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。
  6. 解密过程分别为对应的逆操作。由于每一步操作都是可逆的,按照相反的顺序进行解密即可恢复明文。加解密中每轮的密钥分别由初始密钥扩展得到。算法中 16byte)字节的明文、密文和轮密钥都以一个 4x4 的矩阵表示。 <br />![AES.png](https://cdn.nlark.com/yuque/0/2022/png/25780490/1642944437005-e5793282-513e-4807-828c-0bec6fea869a.png#clientId=u3c0030a6-0d15-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=u07cb0f04&margin=%5Bobject%20Object%5D&name=AES.png&originHeight=669&originWidth=508&originalType=binary&ratio=1&rotation=0&showTitle=false&size=42097&status=done&style=none&taskId=ud93faa97-d5a1-401a-96e9-51d26c0481c&title=)
  7. **c.代码实现**
  8. AESjava实现比较简单,只需要把密码设置为16byte,然后将DES算法实现的java代码中,将DES修改为AES即可。

四.总结

  1. 到这里,我们的课程也即将告一段落了。最后大致的总结一下三种对称加密算法:

三种算法总结.png

  1. DES作为安全性最弱的算法已经在实际运用面临淘汰,而3DES依然在已有的软硬件中返回余热。不过3DES效率太低,在更多的领域被安全和效率兼具的AES所替代。
  2. 在实际开发中,对称加密算法这部分的运用大致如下图所示:

流程图.png

  1. 当然,这只是一个非常简易的模型。我们学习到这,加密也就入门,更多的知识有待于大家进一步发掘!