0


【使用 Commons Codec 实现 MD5、RSA、AES 加密】

文章目录


一、MD5 加密算法

1. 什么是 MD5?

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

MD5 的主要特点包括:

  • 固定输出长度:无论输入数据大小如何,输出的摘要长度都是 128 位。
  • 不可逆性:从散列值不能反推出原始数据。
  • 强抗碰撞性:理论上不应出现不同的输入生成相同的散列值(然而实际中已被破解)。

2. 使用 Commons Codec 实现 MD5

  1. importorg.apache.commons.codec.digest.DigestUtils;importjava.io.UnsupportedEncodingException;/**
  2. * MD5加密工具类
  3. * MD5,全称为“Message-Digest Algorithm 5”,中文名“消息摘要算法5”,是一种单向加密算法。
  4. * 加密特点:1.不可逆;2.不可还原;3.相同内容加密后的结果相同;4.不同内容加密后的结果不同。
  5. * 应用场景:1.密码加密;2.文件完整性校验;3.数字签名。
  6. * 步骤:1.初始化MD5;2.更新MD5;3.计算MD5;4.输出MD5。
  7. * 优点:1.压缩性;2.容易计算;3.抗修改性;4.强抗碰撞。
  8. * 缺点:1.不可逆;2.碰撞攻击。
  9. * 安全性:1.碰撞攻击;2.彩虹表攻击。
  10. */publicabstractclassMD5Util{/**
  11. * 对content进行MD5加密
  12. * @param content 需要加密的内容
  13. * @param salt 盐值
  14. * @param charset 字符编码
  15. * @return 加密后的内容
  16. */publicstaticStringsign(String content,String salt,String charset){
  17. content = content + salt;returnDigestUtils.md5Hex(getContentBytes(content, charset));// 使用MD5加密算法对content进行加密}/**
  18. * 验证签名
  19. * @param content 需要加密的内容
  20. * @param sign 签名
  21. * @param salt 盐值
  22. * @param charset 字符编码
  23. * @return 是否验证通过
  24. */publicstaticbooleanverify(String content,String sign,String salt,String charset){
  25. content = content + salt;String mySign =DigestUtils.md5Hex(getContentBytes(content, charset));// 使用MD5加密算法对content进行加密return mySign.equals(sign);// 判断mySign和sign是否相等}/**
  26. * content转换为字节数组
  27. * @param content 需要转换的内容
  28. * @param charset 字符编码
  29. * @return 字节数组
  30. */privatestaticbyte[]getContentBytes(String content,String charset){if(charset ==null||"".equals(charset)){return content.getBytes();}try{return content.getBytes(charset);}catch(UnsupportedEncodingException e){thrownewRuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:"+ charset);}}publicstaticvoidmain(String[] args){String content ="123456";// 需要加密的内容String salt ="abc";// 盐值String charset ="utf-8";// 字符编码String sign =sign(content, salt, charset);// 对content进行MD5加密,并返回加密后的内容System.out.println("加密后的内容: "+ sign);// 输出加密后的内容boolean verify =verify(content, sign, salt, charset);// 验证签名System.out.println("验证签名: "+ verify);// 输出验证签名}}

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. importorg.apache.commons.codec.binary.Base64;importjavax.crypto.Cipher;importjava.io.ByteArrayOutputStream;importjava.security.*;importjava.security.spec.PKCS8EncodedKeySpec;importjava.security.spec.X509EncodedKeySpec;/**
  2. * RSA加密解密工具类
  3. * RSA,全称为“Rivest-Shamir-Adleman”,中文名“RSA算法”,是一种非对称加密算法。
  4. * RSA加密解密的过程中,密钥长度越长,加密强度越大,但是加密解密速度越慢。
  5. * 加密特点:1.公钥加密,私钥解密;2.私钥签名,公钥验签;3.加密解密速度慢;4.适合对少量数据进行加密解密。
  6. * 应用场景:1.数字签名;2.加密解密;3.密钥协商。
  7. * 步骤:1.生成密钥对;2.加密;3.解密;4.签名;5.验签。
  8. * 优点:1.安全性高;2.密钥管理方便。
  9. * 缺点:1.加密解密速度慢;2.适合对少量数据进行加密解密。
  10. * 安全性:1.公钥加密,私钥解密;2.私钥签名,公钥验签。
  11. */publicclassRSAUtil{/**
  12. * RSA最大加密明文大小
  13. */privatestaticfinalintMAX_ENCRYPT_BLOCK=117;/**
  14. * RSA最大解密密文大小
  15. */privatestaticfinalintMAX_DECRYPT_BLOCK=128;/**
  16. * 获取密钥对
  17. * @return 密钥对
  18. */publicstaticKeyPairgetKeyPair()throwsException{// 获取密钥对生成器,指定算法为RSAKeyPairGenerator generator =KeyPairGenerator.getInstance("RSA");// 设置密钥长度为1024位
  19. generator.initialize(1024);return generator.generateKeyPair();// 生成密钥对}/**
  20. * 获取私钥
  21. * @param privateKey 私钥字符串
  22. * @return 私钥
  23. */publicstaticPrivateKeygetPrivateKey(String privateKey)throwsException{// 获取密钥工厂,指定算法为RSAKeyFactory keyFactory =KeyFactory.getInstance("RSA");// 使用base64解码私钥字符串byte[] decodedKey =Base64.decodeBase64(privateKey.getBytes());// 获取私钥对象PKCS8EncodedKeySpec keySpec =newPKCS8EncodedKeySpec(decodedKey);return keyFactory.generatePrivate(keySpec);// 生成私钥}/**
  24. * 获取公钥
  25. * @param publicKey 公钥字符串
  26. * @return 公钥
  27. */publicstaticPublicKeygetPublicKey(String publicKey)throwsException{KeyFactory keyFactory =KeyFactory.getInstance("RSA");byte[] decodedKey =Base64.decodeBase64(publicKey.getBytes());X509EncodedKeySpec keySpec =newX509EncodedKeySpec(decodedKey);return keyFactory.generatePublic(keySpec);}/**
  28. * RSA加密
  29. * @param data 待加密数据
  30. * @param publicKey 公钥
  31. * @return 加密后的数据
  32. */publicstaticStringencrypt(String data,PublicKey publicKey)throwsException{Cipher cipher =Cipher.getInstance("RSA");
  33. cipher.init(Cipher.ENCRYPT_MODE, publicKey);int inputLen = data.getBytes().length;ByteArrayOutputStream out =newByteArrayOutputStream();int offset =0;byte[] cache;int i =0;// 对数据分段加密while(inputLen - offset >0){if(inputLen - offset >MAX_ENCRYPT_BLOCK){
  34. cache = cipher.doFinal(data.getBytes(), offset,MAX_ENCRYPT_BLOCK);}else{
  35. cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);}
  36. out.write(cache,0, cache.length);
  37. i++;
  38. offset = i *MAX_ENCRYPT_BLOCK;}byte[] encryptedData = out.toByteArray();
  39. out.close();// 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串// 加密后的字符串returnnewString(Base64.encodeBase64String(encryptedData));}/**
  40. * RSA解密
  41. * @param data 待解密数据
  42. * @param privateKey 私钥
  43. * @return 解密后的数据
  44. */publicstaticStringdecrypt(String data,PrivateKey privateKey)throwsException{Cipher cipher =Cipher.getInstance("RSA");
  45. cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] dataBytes =Base64.decodeBase64(data);int inputLen = dataBytes.length;ByteArrayOutputStream out =newByteArrayOutputStream();int offset =0;byte[] cache;int i =0;// 对数据分段解密while(inputLen - offset >0){if(inputLen - offset >MAX_DECRYPT_BLOCK){
  46. cache = cipher.doFinal(dataBytes, offset,MAX_DECRYPT_BLOCK);}else{
  47. cache = cipher.doFinal(dataBytes, offset, inputLen - offset);}
  48. out.write(cache,0, cache.length);
  49. i++;
  50. offset = i *MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();
  51. out.close();// 解密后的内容returnnewString(decryptedData,"UTF-8");}/**
  52. * 签名
  53. * @param data 待签名数据
  54. * @param privateKey 私钥
  55. * @return 签名
  56. */publicstaticStringsign(String data,PrivateKey privateKey)throwsException{byte[] keyBytes = privateKey.getEncoded();PKCS8EncodedKeySpec keySpec =newPKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory =KeyFactory.getInstance("RSA");PrivateKey key = keyFactory.generatePrivate(keySpec);Signature signature =Signature.getInstance("MD5withRSA");
  57. signature.initSign(key);
  58. signature.update(data.getBytes());returnnewString(Base64.encodeBase64(signature.sign()));}/**
  59. * 验签
  60. * @param srcData 原始字符串
  61. * @param publicKey 公钥
  62. * @param sign 签名
  63. * @return 是否验签通过
  64. */publicstaticbooleanverify(String srcData,PublicKey publicKey,String sign)throwsException{byte[] keyBytes = publicKey.getEncoded();X509EncodedKeySpec keySpec =newX509EncodedKeySpec(keyBytes);KeyFactory keyFactory =KeyFactory.getInstance("RSA");PublicKey key = keyFactory.generatePublic(keySpec);Signature signature =Signature.getInstance("MD5withRSA");
  65. signature.initVerify(key);
  66. signature.update(srcData.getBytes());return signature.verify(Base64.decodeBase64(sign.getBytes()));}publicstaticvoidmain(String[] args){try{// 生成密钥对,其中的公钥私钥是唯一对应的KeyPair keyPair =getKeyPair();String privateKey =newString(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));String publicKey =newString(Base64.encodeBase64(keyPair.getPublic().getEncoded()));System.out.println("私钥:"+ privateKey);System.out.println("公钥:"+ publicKey);// RSA加密String data ="test";String encryptData =encrypt(data,getPublicKey(publicKey));System.out.println("加密后内容:"+ encryptData);// RSA解密String decryptData =decrypt(encryptData,getPrivateKey(privateKey));System.out.println("解密后内容:"+ decryptData);// RSA签名String sign =sign(data,getPrivateKey(privateKey));// RSA验签boolean result =verify(data,getPublicKey(publicKey), sign);System.out.print("验签结果:"+ result);}catch(Exception e){
  67. e.printStackTrace();System.out.print("加解密异常");}}}

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 处理固定大小(128 位)的数据块。
  • 高安全性和效率:AES 被广泛认为是目前最安全和高效的对称加密算法之一,适合用于保护大数据量的传输。

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

2. 使用 Commons Codec 实现 AES

  1. importjavax.crypto.Cipher;importjavax.crypto.KeyGenerator;importjavax.crypto.SecretKey;importjavax.crypto.spec.SecretKeySpec;importjava.security.NoSuchAlgorithmException;importjava.security.SecureRandom;/**
  2. * AES加密解密工具类
  3. * AES,全称为“Advanced Encryption Standard”,中文名“高级加密标准”,是一种对称加密算法。
  4. * AES加密解密的过程中,密钥长度越长,加密强度越大,但是加密解密速度越慢。
  5. * 加密特点:1.密钥长度可变;2.加密解密速度快;3.适合对大量数据进行加密解密。
  6. * 应用场景:1.文件加密;2.数据传输加密;3.数据库加密。
  7. * 步骤:1.生成密钥;2.加密;3.解密。
  8. * 优点:1.加密解密速度快;2.适合对大量数据进行加密解密。
  9. * 缺点:1.密钥管理不方便;2.适合对大量数据进行加密解密。
  10. * 安全性:1.密钥长度可变;2.加密解密速度快。
  11. */publicclassAESUtil{privatestaticfinalStringKEY_AES="AES";// 算法privatestaticfinalintKEY_SIZE=128;// 密钥长度(位)/**
  12. * 生成随机AES密钥
  13. *
  14. * @return 随机生成的AES密钥
  15. * @throws NoSuchAlgorithmException
  16. */publicstaticStringgenerateRandomKey()throwsNoSuchAlgorithmException{KeyGenerator keyGen =KeyGenerator.getInstance(KEY_AES);
  17. keyGen.init(KEY_SIZE,newSecureRandom());// AES密钥长度SecretKey secretKey = keyGen.generateKey();returnbyte2hex(secretKey.getEncoded());}/**
  18. * 加密
  19. *
  20. * @param src 需要加密的内容
  21. * @param keyHex 十六进制表示的加密密钥
  22. * @return 加密后的内容
  23. * @throws Exception
  24. */publicstaticStringencrypt(String src,String keyHex)throwsException{if(isValidKey(keyHex)){thrownewException("key不满足条件");}byte[] raw =hex2byte(keyHex);SecretKeySpec skeySpec =newSecretKeySpec(raw,KEY_AES);Cipher cipher =Cipher.getInstance(KEY_AES);
  25. cipher.init(Cipher.ENCRYPT_MODE, skeySpec);byte[] encrypted = cipher.doFinal(src.getBytes());returnbyte2hex(encrypted);}/**
  26. * 解密
  27. *
  28. * @param src 需要解密的内容
  29. * @param keyHex 十六进制表示的解密密钥
  30. * @return 解密后的内容
  31. * @throws Exception
  32. */publicstaticStringdecrypt(String src,String keyHex)throwsException{if(isValidKey(keyHex)){thrownewException("key不满足条件");}byte[] raw =hex2byte(keyHex);SecretKeySpec skeySpec =newSecretKeySpec(raw,KEY_AES);Cipher cipher =Cipher.getInstance(KEY_AES);
  33. cipher.init(Cipher.DECRYPT_MODE, skeySpec);byte[] encrypted1 =hex2byte(src);byte[] original = cipher.doFinal(encrypted1);returnnewString(original);}/**
  34. * 验证密钥是否有效
  35. *
  36. * @param keyHex 十六进制表示的密钥
  37. * @return 是否有效
  38. */privatestaticbooleanisValidKey(String keyHex){return keyHex ==null|| keyHex.length()!=(KEY_SIZE/4);}/**
  39. * 将16进制转换为二进制
  40. *
  41. * @param strhex 16进制字符串
  42. * @return 二进制字节数组
  43. */publicstaticbyte[]hex2byte(String strhex){if(strhex ==null){returnnull;}int l = strhex.length();if(l %2==1){returnnull;}byte[] b =newbyte[l /2];for(int i =0; i != l /2; i++){
  44. b[i]=(byte)Integer.parseInt(strhex.substring(i *2, i *2+2),16);}return b;}/**
  45. * 将二进制转换为16进制
  46. *
  47. * @param b 二进制字节数组
  48. * @return 16进制字符串
  49. */publicstaticStringbyte2hex(byte[] b){StringBuilder hs =newStringBuilder();String stmp;for(byte value : b){
  50. stmp =Integer.toHexString(value &0XFF);if(stmp.length()==1){
  51. hs.append("0").append(stmp);}else{
  52. hs.append(stmp);}}return hs.toString().toUpperCase();}publicstaticvoidmain(String[] args){try{// 生成随机密钥String randomKey =generateRandomKey();System.out.println("随机生成的密钥:"+ randomKey);String[] dataArr ={"hello","hello world","12345678901234567890"};for(String data : dataArr){System.out.println("加密前:"+ data);// 加密String encrypt =encrypt(data, randomKey);System.out.println("加密后:"+ encrypt +" 长度:"+ encrypt.length());// 解密String decrypt =decrypt(encrypt, randomKey);System.out.println("解密后:"+ decrypt);System.out.println();}}catch(Exception e){
  53. e.printStackTrace();}}}

3. 注意事项

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

标签: 算法 安全

本文转载自: https://blog.csdn.net/qq_66726657/article/details/140752662
版权归原作者 武帝为此 所有, 如有侵权,请联系我们删除。

“【使用 Commons Codec 实现 MD5、RSA、AES 加密】”的评论:

还没有评论