ToB企服应用市场:ToB评测及商务社交产业平台

标题: 【利用 Commons Codec 实现 MD5、RSA、AES 加密】 [打印本页]

作者: 麻花痒    时间: 2024-11-6 19:44
标题: 【利用 Commons Codec 实现 MD5、RSA、AES 加密】

一、MD5 加密算法

1. 什么是 MD5?

MD5(Message Digest Algorithm 5)是一种广泛利用的哈希函数,由 Ronald Rivest 在 1991 年计划。它的主要用途是将恣意长度的输入数据(称为消息)转换为固定长度的散列值(称为消息摘要)。MD5 生成的摘要长度为 128 位,即 16 字节。由于其生成的散列值长度固定,即使输入数据发生微小变化,输出也会明显变化,这使得 MD5 适用于数据完备性校验,如文件校验和、密码加密(虽然不推荐用于密码存储)等。
MD5 的主要特点包括:

2. 利用 Commons Codec 实现 MD5

  1. import org.apache.commons.codec.digest.DigestUtils;
  2. import java.io.UnsupportedEncodingException;
  3. /**
  4. * MD5加密工具类
  5. * MD5,全称为“Message-Digest Algorithm 5”,中文名“消息摘要算法5”,是一种单向加密算法。
  6. * 加密特点:1.不可逆;2.不可还原;3.相同内容加密后的结果相同;4.不同内容加密后的结果不同。
  7. * 应用场景:1.密码加密;2.文件完整性校验;3.数字签名。
  8. * 步骤:1.初始化MD5;2.更新MD5;3.计算MD5;4.输出MD5。
  9. * 优点:1.压缩性;2.容易计算;3.抗修改性;4.强抗碰撞。
  10. * 缺点:1.不可逆;2.碰撞攻击。
  11. * 安全性:1.碰撞攻击;2.彩虹表攻击。
  12. */
  13. public abstract class MD5Util {
  14.         /**
  15.          * 对content进行MD5加密
  16.          * @param content  需要加密的内容
  17.          * @param salt   盐值
  18.          * @param charset  字符编码
  19.          * @return  加密后的内容
  20.          */
  21.         public static String sign(String content, String salt, String charset) {
  22.                 content = content + salt;
  23.                 return DigestUtils.md5Hex(getContentBytes(content, charset));  // 使用MD5加密算法对content进行加密
  24.         }
  25.         /**
  26.          * 验证签名
  27.          * @param content  需要加密的内容
  28.          * @param sign  签名
  29.          * @param salt  盐值
  30.          * @param charset  字符编码
  31.          * @return  是否验证通过
  32.          */
  33.         public static boolean verify(String content, String sign, String salt, String charset) {
  34.                 content = content + salt;
  35.                 String mySign = DigestUtils.md5Hex(getContentBytes(content, charset));  // 使用MD5加密算法对content进行加密
  36.                 return mySign.equals(sign);  // 判断mySign和sign是否相等
  37.         }
  38.         /**
  39.          * 将content转换为字节数组
  40.          * @param content  需要转换的内容
  41.          * @param charset  字符编码
  42.          * @return  字节数组
  43.          */
  44.         private static byte[] getContentBytes(String content, String charset) {
  45.                 if (charset == null || "".equals(charset)) {
  46.                         return content.getBytes();
  47.                 }
  48.                 try {
  49.                         return content.getBytes(charset);
  50.                 } catch (UnsupportedEncodingException e) {
  51.                         throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
  52.                 }
  53.         }
  54.         public static void main(String[] args) {
  55.                 String content = "123456";  // 需要加密的内容
  56.                 String salt = "abc";  // 盐值
  57.                 String charset = "utf-8";  // 字符编码
  58.                 String sign = sign(content, salt, charset);  // 对content进行MD5加密,并返回加密后的内容
  59.                 System.out.println("加密后的内容: " + sign);  // 输出加密后的内容
  60.                 boolean verify = verify(content, sign, salt, charset);  // 验证签名
  61.                 System.out.println("验证签名: " + verify);  // 输出验证签名
  62.         }
  63. }
复制代码
3. 注意事项

MD5 算法不适用于安全性要求高的场景,由于其存在碰撞漏洞和被暴力破解的风险。

二、RSA 加密算法

1. 什么是 RSA?

RSA 是一种非对称加密算法,由 Ron Rivest、Adi Shamir 和 Leonard Adleman 于 1977 年提出。RSA 算法基于大整数因数分解的数学困难,其安全性依赖于大数分解的困难性。与对称加密差异,RSA 利用一对密钥:公钥和私钥。公钥用于加密数据,私钥用于解密数据。RSA 可以用于加密和数字签名,其广泛应用于 SSL/TLS 协议、电子邮件加密和数字签名等领域。
RSA 的主要特点包括:

尽管 RSA 安全性较高,但其加密速率较慢,不得当加密大数据量。在实际应用中,通常结合对称加密算法,如 AES,来加密数据内容,而 RSA 用于加密对称密钥。
2. 利用 Commons Codec 实现 RSA

  1. import org.apache.commons.codec.binary.Base64;
  2. import javax.crypto.Cipher;
  3. import java.io.ByteArrayOutputStream;
  4. import java.security.*;
  5. import java.security.spec.PKCS8EncodedKeySpec;
  6. import java.security.spec.X509EncodedKeySpec;
  7. /**
  8. * RSA加密解密工具类
  9. * RSA,全称为“Rivest-Shamir-Adleman”,中文名“RSA算法”,是一种非对称加密算法。
  10. * RSA加密解密的过程中,密钥长度越长,加密强度越大,但是加密解密速度越慢。
  11. * 加密特点:1.公钥加密,私钥解密;2.私钥签名,公钥验签;3.加密解密速度慢;4.适合对少量数据进行加密解密。
  12. * 应用场景:1.数字签名;2.加密解密;3.密钥协商。
  13. * 步骤:1.生成密钥对;2.加密;3.解密;4.签名;5.验签。
  14. * 优点:1.安全性高;2.密钥管理方便。
  15. * 缺点:1.加密解密速度慢;2.适合对少量数据进行加密解密。
  16. * 安全性:1.公钥加密,私钥解密;2.私钥签名,公钥验签。
  17. */
  18. public class RSAUtil {
  19.     /**
  20.      * RSA最大加密明文大小
  21.      */
  22.     private static final int MAX_ENCRYPT_BLOCK = 117;
  23.     /**
  24.      * RSA最大解密密文大小
  25.      */
  26.     private static final int MAX_DECRYPT_BLOCK = 128;
  27.     /**
  28.      * 获取密钥对
  29.      * @return 密钥对
  30.      */
  31.     public static KeyPair getKeyPair() throws Exception {
  32.         // 获取密钥对生成器,指定算法为RSA
  33.         KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
  34.         // 设置密钥长度为1024位
  35.         generator.initialize(1024);
  36.         return generator.generateKeyPair();  // 生成密钥对
  37.     }
  38.     /**
  39.      * 获取私钥
  40.      * @param privateKey 私钥字符串
  41.      * @return 私钥
  42.      */
  43.     public static PrivateKey getPrivateKey(String privateKey) throws Exception {
  44.         // 获取密钥工厂,指定算法为RSA
  45.         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  46.         // 使用base64解码私钥字符串
  47.         byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
  48.         // 获取私钥对象
  49.         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
  50.         return keyFactory.generatePrivate(keySpec); // 生成私钥
  51.     }
  52.     /**
  53.      * 获取公钥
  54.      * @param publicKey 公钥字符串
  55.      * @return 公钥
  56.      */
  57.     public static PublicKey getPublicKey(String publicKey) throws Exception {
  58.         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  59.         byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
  60.         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
  61.         return keyFactory.generatePublic(keySpec);
  62.     }
  63.     /**
  64.      * RSA加密
  65.      * @param data      待加密数据
  66.      * @param publicKey 公钥
  67.      * @return 加密后的数据
  68.      */
  69.     public static String encrypt(String data, PublicKey publicKey) throws Exception {
  70.         Cipher cipher = Cipher.getInstance("RSA");
  71.         cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  72.         int inputLen = data.getBytes().length;
  73.         ByteArrayOutputStream out = new ByteArrayOutputStream();
  74.         int offset = 0;
  75.         byte[] cache;
  76.         int i = 0;
  77.         // 对数据分段加密
  78.         while (inputLen - offset > 0) {
  79.             if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
  80.                 cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
  81.             } else {
  82.                 cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
  83.             }
  84.             out.write(cache, 0, cache.length);
  85.             i++;
  86.             offset = i * MAX_ENCRYPT_BLOCK;
  87.         }
  88.         byte[] encryptedData = out.toByteArray();
  89.         out.close();
  90.         // 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
  91.         // 加密后的字符串
  92.         return new String(Base64.encodeBase64String(encryptedData));
  93.     }
  94.     /**
  95.      * RSA解密
  96.      * @param data       待解密数据
  97.      * @param privateKey 私钥
  98.      * @return 解密后的数据
  99.      */
  100.     public static String decrypt(String data, PrivateKey privateKey) throws Exception {
  101.         Cipher cipher = Cipher.getInstance("RSA");
  102.         cipher.init(Cipher.DECRYPT_MODE, privateKey);
  103.         byte[] dataBytes = Base64.decodeBase64(data);
  104.         int inputLen = dataBytes.length;
  105.         ByteArrayOutputStream out = new ByteArrayOutputStream();
  106.         int offset = 0;
  107.         byte[] cache;
  108.         int i = 0;
  109.         // 对数据分段解密
  110.         while (inputLen - offset > 0) {
  111.             if (inputLen - offset > MAX_DECRYPT_BLOCK) {
  112.                 cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
  113.             } else {
  114.                 cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
  115.             }
  116.             out.write(cache, 0, cache.length);
  117.             i++;
  118.             offset = i * MAX_DECRYPT_BLOCK;
  119.         }
  120.         byte[] decryptedData = out.toByteArray();
  121.         out.close();
  122.         // 解密后的内容
  123.         return new String(decryptedData, "UTF-8");
  124.     }
  125.     /**
  126.      * 签名
  127.      * @param data       待签名数据
  128.      * @param privateKey 私钥
  129.      * @return 签名
  130.      */
  131.     public static String sign(String data, PrivateKey privateKey) throws Exception {
  132.         byte[] keyBytes = privateKey.getEncoded();
  133.         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
  134.         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  135.         PrivateKey key = keyFactory.generatePrivate(keySpec);
  136.         Signature signature = Signature.getInstance("MD5withRSA");
  137.         signature.initSign(key);
  138.         signature.update(data.getBytes());
  139.         return new String(Base64.encodeBase64(signature.sign()));
  140.     }
  141.     /**
  142.      * 验签
  143.      * @param srcData   原始字符串
  144.      * @param publicKey 公钥
  145.      * @param sign      签名
  146.      * @return 是否验签通过
  147.      */
  148.     public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
  149.         byte[] keyBytes = publicKey.getEncoded();
  150.         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
  151.         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  152.         PublicKey key = keyFactory.generatePublic(keySpec);
  153.         Signature signature = Signature.getInstance("MD5withRSA");
  154.         signature.initVerify(key);
  155.         signature.update(srcData.getBytes());
  156.         return signature.verify(Base64.decodeBase64(sign.getBytes()));
  157.     }
  158.     public static void main(String[] args) {
  159.         try {
  160.             // 生成密钥对,其中的公钥私钥是唯一对应的
  161.             KeyPair keyPair = getKeyPair();
  162.             String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
  163.             String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
  164.             System.out.println("私钥:" + privateKey);
  165.             System.out.println("公钥:" + publicKey);
  166.             // RSA加密
  167.             String data = "test";
  168.             String encryptData = encrypt(data, getPublicKey(publicKey));
  169.             System.out.println("加密后内容:" + encryptData);
  170.             // RSA解密
  171.             String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
  172.             System.out.println("解密后内容:" + decryptData);
  173.             // RSA签名
  174.             String sign = sign(data, getPrivateKey(privateKey));
  175.             // RSA验签
  176.             boolean result = verify(data, getPublicKey(publicKey), sign);
  177.             System.out.print("验签结果:" + result);
  178.         } catch (Exception e) {
  179.             e.printStackTrace();
  180.             System.out.print("加解密异常");
  181.         }
  182.     }
  183. }
复制代码
3. 注意事项

RSA 加密算法适用于安全性要求高的场景,但运算速率较慢,得当加密较小数据量。

三、AES 加密算法

1. 什么是 AES?

AES(Advanced Encryption Standard)是美国国家尺度与技术研究院(NIST)于 2001 年发布的对称加密算法尺度,由比利时密码学家 Joan Daemen 和 Vincent Rijmen 计划。AES 是替换原有 DES(Data Encryption Standard)的新尺度,旨在提供更强的安全性和更高的效率。AES 支持多种密钥长度,包括 128 位、192 位和 256 位,密钥长度越长,安全性越高。
AES 的主要特点包括:

AES 在很多领域得到广泛应用,包括 SSL/TLS 协议、无线安全(如 WPA2)、文件加密、虚拟专用网络(VPN)等。其高效的加密和解密性能使其成为现代数据安全的首选方案。
2. 利用 Commons Codec 实现 AES

  1. import javax.crypto.Cipher;
  2. import javax.crypto.KeyGenerator;
  3. import javax.crypto.SecretKey;
  4. import javax.crypto.spec.SecretKeySpec;
  5. import java.security.NoSuchAlgorithmException;
  6. import java.security.SecureRandom;
  7. /**
  8. * AES加密解密工具类
  9. * AES,全称为“Advanced Encryption Standard”,中文名“高级加密标准”,是一种对称加密算法。
  10. * AES加密解密的过程中,密钥长度越长,加密强度越大,但是加密解密速度越慢。
  11. * 加密特点:1.密钥长度可变;2.加密解密速度快;3.适合对大量数据进行加密解密。
  12. * 应用场景:1.文件加密;2.数据传输加密;3.数据库加密。
  13. * 步骤:1.生成密钥;2.加密;3.解密。
  14. * 优点:1.加密解密速度快;2.适合对大量数据进行加密解密。
  15. * 缺点:1.密钥管理不方便;2.适合对大量数据进行加密解密。
  16. * 安全性:1.密钥长度可变;2.加密解密速度快。
  17. */
  18. public class AESUtil {
  19.     private static final String KEY_AES = "AES";  // 算法
  20.     private static final int KEY_SIZE = 128;  // 密钥长度(位)
  21.     /**
  22.      * 生成随机AES密钥
  23.      *
  24.      * @return 随机生成的AES密钥
  25.      * @throws NoSuchAlgorithmException
  26.      */
  27.     public static String generateRandomKey() throws NoSuchAlgorithmException {
  28.         KeyGenerator keyGen = KeyGenerator.getInstance(KEY_AES);
  29.         keyGen.init(KEY_SIZE, new SecureRandom()); // AES密钥长度
  30.         SecretKey secretKey = keyGen.generateKey();
  31.         return byte2hex(secretKey.getEncoded());
  32.     }
  33.     /**
  34.      * 加密
  35.      *
  36.      * @param src    需要加密的内容
  37.      * @param keyHex 十六进制表示的加密密钥
  38.      * @return 加密后的内容
  39.      * @throws Exception
  40.      */
  41.     public static String encrypt(String src, String keyHex) throws Exception {
  42.         if (isValidKey(keyHex)) {
  43.             throw new Exception("key不满足条件");
  44.         }
  45.         byte[] raw = hex2byte(keyHex);
  46.         SecretKeySpec skeySpec = new SecretKeySpec(raw, KEY_AES);
  47.         Cipher cipher = Cipher.getInstance(KEY_AES);
  48.         cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
  49.         byte[] encrypted = cipher.doFinal(src.getBytes());
  50.         return byte2hex(encrypted);
  51.     }
  52.     /**
  53.      * 解密
  54.      *
  55.      * @param src    需要解密的内容
  56.      * @param keyHex 十六进制表示的解密密钥
  57.      * @return 解密后的内容
  58.      * @throws Exception
  59.      */
  60.     public static String decrypt(String src, String keyHex) throws Exception {
  61.         if (isValidKey(keyHex)) {
  62.             throw new Exception("key不满足条件");
  63.         }
  64.         byte[] raw = hex2byte(keyHex);
  65.         SecretKeySpec skeySpec = new SecretKeySpec(raw, KEY_AES);
  66.         Cipher cipher = Cipher.getInstance(KEY_AES);
  67.         cipher.init(Cipher.DECRYPT_MODE, skeySpec);
  68.         byte[] encrypted1 = hex2byte(src);
  69.         byte[] original = cipher.doFinal(encrypted1);
  70.         return new String(original);
  71.     }
  72.     /**
  73.      * 验证密钥是否有效
  74.      *
  75.      * @param keyHex 十六进制表示的密钥
  76.      * @return 是否有效
  77.      */
  78.     private static boolean isValidKey(String keyHex) {
  79.         return keyHex == null || keyHex.length() != (KEY_SIZE / 4);
  80.     }
  81.     /**
  82.      * 将16进制转换为二进制
  83.      *
  84.      * @param strhex 16进制字符串
  85.      * @return 二进制字节数组
  86.      */
  87.     public static byte[] hex2byte(String strhex) {
  88.         if (strhex == null) {
  89.             return null;
  90.         }
  91.         int l = strhex.length();
  92.         if (l % 2 == 1) {
  93.             return null;
  94.         }
  95.         byte[] b = new byte[l / 2];
  96.         for (int i = 0; i != l / 2; i++) {
  97.             b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2), 16);
  98.         }
  99.         return b;
  100.     }
  101.     /**
  102.      * 将二进制转换为16进制
  103.      *
  104.      * @param b 二进制字节数组
  105.      * @return 16进制字符串
  106.      */
  107.     public static String byte2hex(byte[] b) {
  108.         StringBuilder hs = new StringBuilder();
  109.         String stmp;
  110.         for (byte value : b) {
  111.             stmp = Integer.toHexString(value & 0XFF);
  112.             if (stmp.length() == 1) {
  113.                 hs.append("0").append(stmp);
  114.             } else {
  115.                 hs.append(stmp);
  116.             }
  117.         }
  118.         return hs.toString().toUpperCase();
  119.     }
  120.     public static void main(String[] args) {
  121.         try {
  122.             // 生成随机密钥
  123.             String randomKey = generateRandomKey();
  124.             System.out.println("随机生成的密钥:" + randomKey);
  125.             String[] dataArr = {"hello", "hello world", "12345678901234567890"};
  126.             for (String data : dataArr) {
  127.                 System.out.println("加密前:" + data);
  128.                 // 加密
  129.                 String encrypt = encrypt(data, randomKey);
  130.                 System.out.println("加密后:" + encrypt + " 长度:" + encrypt.length());
  131.                 // 解密
  132.                 String decrypt = decrypt(encrypt, randomKey);
  133.                 System.out.println("解密后:" + decrypt);
  134.                 System.out.println();
  135.             }
  136.         } catch (Exception e) {
  137.             e.printStackTrace();
  138.         }
  139.     }
  140. }
复制代码
3. 注意事项

AES 加密算法适用于对称加密场景,速率快,得当加密大数据量。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4