• 工作中常用的5种加密算法


    背景

    最近,项目中做了一些安全性要求的整改。而加密是使用过程中常用的手段之一。这里简单的整理下,希望对小伙伴有帮助。

    使用场景

    加密是一种将原始信息(明文)转换成难以被直接理解的形式(密文)的过程,

    其主要目的是为了保护信息的安全和隐私。主要应用于以下场景:

    1. 数据保密:防止未经授权的个人身份信息和敏感数据。保护个人隐私、商业机密和国家机密。如:公司内部文件、云存储信息防截获。

    2. 数据完整性:确保数据在传输或存储过程中未被篡改。如:软件下载、银行转账等。

    3. 身份验证:验证通信双方的身份,确保数据是从一个可信的来源发送的,并且在整个传输过程中没有被拦截或篡改。如:用户登录、电子邮件认证等。

    4. 数据访问控制:加密可以限制对数据的访问,只有拥有正确密钥的用户才能解密和访问数据。如:企业 VPN 等。

    5. 网络安全:在互联网上传输数据时,加密可以防止中间人攻击和其他网络攻击,确保数据在网络中的传输安全。如:SSL/TLS 协议等。

    6. 金融交易安全:在电子商务和在线银行中,加密用于保护交易数据,防止信用卡欺诈和其他金融犯罪。如:在线支付(金融机构提供的 RSA 签名和证书)等。

    常用加密算法

    1、MD5 加密

    适用场景

    MD5 作为一种广泛使用的哈希函数,主要用于以下场景:

    1. 数据完整性校验:验证文件传输过程中是否被篡改。

    2. 数字签名:确保信息传输的完整性和来源的真实性。

    3. 密码存储:在数据库中存储用户密码的哈希值,而非明文。

    功能特性

    • 长度固定:无论输入长度如何,输出都是 128 位(16 字节)的哈希值。

    • 快速计算:MD5 算法计算速度快,适用于大量数据的哈希处理。

    • 不可逆性:MD5 加密是不可逆的,因此通常只有加密过程,而没有解密过程

    原理及流程图

    MD5 算法将输入的消息经过填充、分段、循环处理等步骤,最终生成一个 128 位的哈希值。

    用字符串 “Hello” 的加密过程说明 MD5 算法的基本处理流程:

    1. 原始输入(明文)
       |
       |(转换为二进制)
       V
    2. 二进制数据 "Hello"
       |
       |(填充到512位的倍数)
       V
    3. 填充后的二进制数据
       |
       |(添加原始长度的64位表示)
       V
    4. 长度附加后的二进制数据
       |
       |(分割成512位的消息块)
       V
    5. 消息块1 ... 消息块n
       |
       |(每块512位,共16个32位字)
       V
    6. 初始MD5值(ABCD)
       |
       |(通过主循环处理每个块)
       V
    7. 主循环(每块16步)
       |_________|_________|
       |          |          |
       V          V          V
    8. 经过F, G, H, I函数的32位字
       |_________|_________|
       |          |          |
       V          V          V
    9. 更新后的MD5值
       |
       V
    10. 最终MD5散列值(128位)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    代码实现

    使用 Java 实现 MD5 加密的示例代码:

    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    public class MD5Example {
    
       //用于将字节数组转换为十六进制表示的字符串
        public static String toHexString(byte[] bytes) {
            StringBuilder hexString = new StringBuilder();
            for (byte b : bytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        }
    
        public static String getMD5(String input) {
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                byte[] messageDigest = md.digest(input.getBytes());
                return toHexString(messageDigest);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            }
        }
    
        public static void main(String[] args) {
            String password = "Hello, World!";
            //输出结果:65a8e27d8879283831b664bd8b7f0ad4
            System.out.println("MD5 Hash: " + getMD5(password));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    注意事项

    • MD5 算法已经不再被认为是安全的,因此不推荐用于需要高安全性的加密场景。

    • MD5 算法的输出可以作为数据完整性校验,但不应用于加密和解密操作。

    2、AES 加密

    适用场景

    AES(高级加密标准)是一种广泛使用的对称加密算法,适用于以下场景:

    1. 数据传输安全:在网络通信中加密数据,保护数据传输过程中的隐私和完整性。

    2. 文件和数据存储:对存储在服务器或云端的敏感文件进行加密。

    3. VPN 连接:确保远程连接的安全性。

    功能特性

    • 安全性:AES 提供强大的安全性,是目前最推荐使用的对称加密算法之一。

    • 灵活性:支持 128、192 和 256 位的密钥长度,适应不同的安全级别需求。

    • 效率高:AES 算法效率高,适合大量数据的快速加密。

    原理及流程图

    例如,使用 AES 加密算法加密字符串 “hello”

    1. 明文 "hello"
      |
      |(转换为二进制格式)
      V
    2. 128位二进制明文
      |
      |(可能需要填充)
      V
    3. 填充后的128位二进制数据
      |
      |(密钥扩展)
      V
    4. 生成轮密钥
      |
      |(初始轮密钥加)
      V
    5. 与轮密钥异或后的数据块
      |
      |(主轮加密处理)
      V
      |_________________________|
      |                         |
      |   SubBytes(字节代换)     |
      |_________________________|
      |                         |
      |    ShiftRows(行移位)     |
      |_________________________|
      |                         |
      |   MixColumns (列混淆)    |
      |_________________________|
      |                         |
      |  AddRoundKey(轮密钥加)   |
      |_________________________|
      V                       V
    6. 密文数据块
      |
      V
    7. 密文(二进制格式)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    示例代码

    对字符串 “hello” 进行 AES 加密的示例:

    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import java.security.NoSuchAlgorithmException;
    
    public class AESExample {
        public static void main(String[] args) {
            try {
                // 实例化密钥生成器,并初始化为AES(128位)
                KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
                 // 初始化128位 ,可修改
                keyGenerator.init(128);
                SecretKey secretKey = keyGenerator.generateKey();
    
                // 实例化Cipher对象,用于AES加密
                Cipher cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.ENCRYPT_MODE, secretKey);
    
                // 转换明文字符串 "hello" 为二进制数据
                String plainText = "hello";
                byte[] plainTextBytes = plainText.getBytes();
    
                // 加密得到密文
                byte[] encryptedBytes = cipher.doFinal(plainTextBytes);
    
                // 打印加密后的密文(通常以十六进制形式表示)
                System.out.println("Encrypted bytes: " + bytesToHex(encryptedBytes));
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
    
        // 将字节数组转换为十六进制字符串
        private static String bytesToHex(byte[] bytes) {
            StringBuilder hexString = new StringBuilder();
            for (byte b : bytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    注意事项

    • AES 加密是对称加密,加密和解密使用相同的密钥

    • 密钥长度的选择需要根据具体的应用场景和安全需求来确定。

    3、DES 加密

    适用场景

    DES(数据加密标准)是一种较早的对称加密算法,由于密钥长度(56 位有效密钥,相对较短),其安全性相对较低,一般一些旧的系统中仍然使用。

    主要适用场景包括:

    1. 数据传输:在安全性要求不是特别高的场合,DES 仍可用于数据传输的加密。

    功能特性

    • 对称加密:使用相同的密钥进行加密和解密。

    • 密钥长度:实际有效的密钥长度为 56 位,另外 8 位用于奇偶性校验。

    • 效率:由于算法较老,在现代硬件上的相对速度较慢。

    • 安全性:由于密钥长度较短,DES 容易受到暴力破解攻击,因此认为不安全的。

    原理及流程图

    我们通过以下步骤使用 DES 加密字符串 “hello”:

    1. 明文 "hello"
      |
      |(转换为二进制并填充)
      V
    2. 64位二进制明文
      |
      |(初始置换 IP)
      V
    3. 初始置换后的数据块
      |
      |(密钥加)
      V
    4. 与密钥异或后的数据块
      |
      |(Feistel网络处理)
      V
      |_________________________|
      |                       |
      |          密钥加       |
      |_________________________|
      |                       |
      |          置换         |
      |_________________________|
      |                       |
      |          代换         |
      |_________________________|
      |                       |
      |          循环左移     |
      |_________________________|
      V                       V
    5. Feistel网络输出
      |
      |(逆置换 IP^-1)
      V
    6. 逆置换后的密文块
      |
      V
    7. 密文
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    示例代码(Java)

    以下是使用 Java 代码对字符串 “hello” 进行 DES 加密的示例:

    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.IvParameterSpec;
    import java.security.NoSuchAlgorithmException;
    import java.util.Base64;
    
    public class DESExample {
        public static void main(String[] args) {
            try {
                // 实例化密钥生成器,并初始化为DES
                KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
                keyGenerator.init(56); // DES密钥长度为56位
                SecretKey secretKey = keyGenerator.generateKey();
    
                // 实例化Cipher对象,用于DES加密
                Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
                IvParameterSpec iv = new IvParameterSpec(new byte[8]); // 使用8位的IV
                cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
    
                // 转换明文字符串 "hello" 为二进制数据
                String plainText = "hello";
                byte[] plainTextBytes = plainText.getBytes("UTF-8");
    
                // 加密得到密文
                byte[] encryptedBytes = cipher.doFinal(plainTextBytes);
    
                // 打印加密后的密文(通常以Base64形式表示)
                System.out.println("Encrypted text: " + Base64.getEncoder().encodeToString(encryptedBytes));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    注意事项

    • DES 由于其较短的密钥长度,已不适用于安全性要求高的场合。

    • 在实际使用中,推荐使用 AES 或其他更安全的加密算法。

    4、国密算法加密

    适用场景

    国密算法,即中国国家商用密码算法标准,包括但不限于 SM1、SM2、SM3、SM4 等。主要用于:

    1. 金融服务:在金融服务行业中用于保证交易安全。

    2. 政府通信:确保政府数据传输的安全性。

    3. 企业数据保护:用于保护商业机密和客户数据。

    4. 安全令牌:用于安全令牌的加密。

    功能特性

    • 标准性:国密算法符合中国的商用密码标准。

    • 安全性:可抵御多种已知攻击方式。

    • 多样性:包含多种算法,如 SM2 用于数字签名,SM4 用于数据加密。

    原理及流程图

    使用字符串 “hello” 进行说明:

    1. 明文 "hello"
      |
      |(转换为二进制格式)
      V
    2. 二进制明文数据
      |
      |(配置密钥和参数)
      V
    3. 初始化加密模块
      |
      |(设置SM4密钥和IV)
      V
    4. 使用SM4加密明文
      |
      |(多轮迭代加密处理)
      V
    5. 输出SM4密文
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    示例代码(Java)

    使用 Java 伪代码对字符串 “hello” 进行 SM4 加密的示例:

    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.IvParameterSpec;
    import java.security.NoSuchAlgorithmException;
    import java.security.Security;
    
    public class SM4Example {
        public static void main(String[] args) {
            try {
                // 添加Bouncy Castle安全提供者
                Security.addProvider(new BouncyCastleProvider());
    
                // 实例化密钥生成器,并初始化为SM4
                KeyGenerator keyGenerator = KeyGenerator.getInstance("SM4");
                keyGenerator.init(128); // SM4密钥长度为128位
                SecretKey secretKey = keyGenerator.generateKey();
    
                // 实例化Cipher对象,用于SM4加密
                Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS7Padding");
                IvParameterSpec iv = new IvParameterSpec(new byte[16]); // 16字节的IV
                cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
    
                // 转换明文字符串 "hello" 为二进制数据
                String plainText = "hello";
                byte[] plainTextBytes = plainText.getBytes("UTF-8");
    
                // 加密得到密文
                byte[] encryptedBytes = cipher.doFinal(plainTextBytes);
    
                // 打印加密后的密文(通常以十六进制或Base64形式表示)
                System.out.println("Encrypted text: " + bytesToHex(encryptedBytes));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        // 将字节数组转换为十六进制字符串
        private static String bytesToHex(byte[] bytes) {
            StringBuilder hexString = new StringBuilder();
            for (byte b : bytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    注意事项

    • 密钥管理是加密过程中的一个重要环节,密钥应该安全地生成、存储和分发。

    • 国密算法的使用需要遵守相关的法律法规和标准。

    5、 RSA 加密

    适用场景

    使用场景:

    1. 安全电子邮件:使用 RSA 对邮件内容进行加密,确保邮件传输过程中的安全性。

    2. SSL/TLS:在 SSL/TLS 协议中,RSA 用于加密交换对称密钥,以建立安全通信。

    3. 数字签名:RSA 用于生成数字签名,验证软件或文档的完整性和来源。

    4. 身份验证:用于身份验证过程,确保通信双方的身份。

    功能特性

    • 非对称加密:使用一对密钥,公钥加密,私钥解密。

    • 安全性:难以破解,安全性高。

    • 密钥长度:通常使用 1024 位、2048 位或更长的密钥,以提高安全性。

    原理及流程图

    例如,明文 “hello” 加密解密过程如下:

    1. 明文 "hello"
      |
      |(转换为数值 m)
      V
    2. 使用公钥 (e, n) 加密
      |___________|
      |           |
      |  m^e mod n|
      |___________|
      |
      V
    3. 得到密文 c
      |
      |(使用私钥 (d, n) 解密)
      V
      |___________|
      |           |
      |  c^d mod n|
      |___________|
      |
      V
    4. 恢复明文 m
      |
      V
    5. 明文 "hello"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    程序实现

    使用 Java 实现 RSA 加密和解密的简单示例:

    import javax.crypto.Cipher;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Base64;
    
    public class RSAExample {
    
        public static void main(String[] args) throws Exception {
            // 生成密钥对
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
    
            // 公钥和私钥
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();
    
            // 明文
            String plainText = "hello";
            byte[] data = plainText.getBytes();
    
            // 加密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] encryptedData = cipher.doFinal(data);
            System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encryptedData));
    
            // 解密
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] decryptedData = cipher.doFinal(encryptedData);
            String decryptedText = new String(decryptedData);
            System.out.println("Decrypted: " + decryptedText);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    注意事项

    • 密钥长度:推荐使用 2048 位或更长的密钥以确保安全性。

    • 密钥管理:公钥可以公开,但私钥必须保密,防止泄露。

    • 性能:RSA 加密和解密的速度相对较慢,不适合加密大量数据。

    总结

    综上,实际使用中,常常根据自身系统特征选择。比如:执行效率、数据量、安全合规要求等,这里给出上述简易版整理。

    加密算法名称有效长度特性是否加密解密优点缺点
    MD5MD5 散列算法128 位散列函数不可逆速度快,简单安全性低,易受碰撞攻击
    AESAES 加密算法128/192/256 位对称加密安全性高,效率高无严重弱点
    DESDES 加密算法56 位对称加密速度快,曾广泛使用密钥短,安全性低
    国密 SM4SM4 加密算法128 位对称加密符合国内标准,安全性好使用不如 AES 广泛
    RSARSA 加密算法1024/2048 位非对称加密非对称加密,适合数字签名计算量大,速度慢
  • 相关阅读:
    Pytorch笔记之分类
    2009(408)数据结构有关链表代码题
    项目——boost搜索引擎
    Mysql004:用户管理
    python切分字符串
    SpringBoot集成MyBatis-Plus + MyBatis-Plus代码生成器[MP系列] - 第490篇
    Qt编程,TCP编程、数据库
    Vue中 引入使用 element-resize-detector 监听 Dom 元素 宽度、高度 变化
    Spring源码解析——@Transactional注解的声明式事物介绍
    stream中map相关方法
  • 原文地址:https://blog.csdn.net/agonie201218/article/details/138065676