浅谈几种常见的加密算法

本是古典 何须时尚 2023-06-10 08:27 27阅读 0赞

文章目录

  • 一、编码格式 (这个按道理来讲是算不上加密的,但是比较常用)
  • 二、消息摘要算法 (这个按道理来讲是算不上加密的,但是比较常用)
  • 三、对称加密
  • 四、非对称加密
  • 在线加密测试工具
  • 参考相关文章

下面所有代码都是基于 jdk8

所有基于Apache的实现都需要引入下面这个包:

  1. <!-- apache.codec:编码方法的工具类包 -->
  2. <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
  3. <dependency>
  4. <groupId>commons-codec</groupId>
  5. <artifactId>commons-codec</artifactId>
  6. <version>1.11</version>
  7. </dependency>

一、编码格式 (这个按道理来讲是算不上加密的,但是比较常用)

编码格式算法

二、消息摘要算法 (这个按道理来讲是算不上加密的,但是比较常用)

消息摘要算法

基于上面的 编码格式算法消息摘要算法 写了一个基础加密工具,对称加密非对称加密有单独的工具类,往下看就知道了。

  1. package com.blog.www.util.coder.base;
  2. import lombok.AccessLevel;
  3. import lombok.NoArgsConstructor;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.apache.commons.codec.digest.DigestUtils;
  6. import org.apache.commons.codec.digest.HmacAlgorithms;
  7. import org.apache.commons.codec.digest.HmacUtils;
  8. import org.springframework.util.Base64Utils;
  9. import javax.crypto.KeyGenerator;
  10. import javax.crypto.SecretKey;
  11. import java.net.URLDecoder;
  12. import java.net.URLEncoder;
  13. import java.nio.charset.StandardCharsets;
  14. import java.security.NoSuchAlgorithmException;
  15. import java.util.Objects;
  16. import java.util.Random;
  17. /** * 基础编码工具类 * <br/> * 包含以下几种加密: * <ul> * <li>Base64</li> * <li>URLEncoder、URLDecoder</li> * <li>MD5</li> * <li>MD5加随机盐</li> * <li>SHA</li> * <li>MAC</li> * </ul> * <p> * 注意: <br> * Base64加密可逆,一般用来编码信息发送,甚至可以把图片转换成字符串发送到前端显示。注意不要用来发送机密信息! <br> * MD5、SHA、MAC这三种加密算法,是不可逆加密,我们通常只把他们作为加密的基础。单纯的以上三种的加密并不可靠。 * <p> * 创建人:leigq <br> * 创建时间:2017年10月23日 下午10:39:06 <br> */
  18. @Slf4j
  19. @NoArgsConstructor(access = AccessLevel.PRIVATE)
  20. public final class BaseCoderUtils {
  21. /* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ BASE64 编码、解码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
  22. /** * BASE64加密 * <br/> * * @param binaryData 待加密二进制数据 * @return 加密后字符串 */
  23. public static String encryptBase64(final byte[] binaryData) {
  24. // 安卓自带实现,因为安卓用不了Apache的实现,所以只能用自带的实现。注意,Base64.CRLF才对应Apache的默认模式!
  25. // return Base64.encodeToString(key, Base64.CRLF);
  26. return Base64Utils.encodeToString(binaryData);
  27. }
  28. /** * BASE64解密 * <br/> * * @param base64String 加密后字符串 * @return 原始二进制数据 */
  29. public static byte[] decryptBase64(final String base64String) {
  30. // 安卓自带实现
  31. // return Base64.decode(key, Base64.CRLF);
  32. return Base64Utils.decodeFromString(base64String);
  33. }
  34. /* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ BASE64 编码、解码 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */
  35. /* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ URL 编码、解码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
  36. /** * 将 URL 编码 */
  37. public static String encodeURL(final String data) {
  38. String target;
  39. try {
  40. target = URLEncoder.encode(data, StandardCharsets.UTF_8.name());
  41. } catch (Exception e) {
  42. log.error("编码出错!", e);
  43. throw new RuntimeException(e);
  44. }
  45. return target;
  46. }
  47. /** * 将 URL 解码 */
  48. public static String decodeURL(final String data) {
  49. String target;
  50. try {
  51. target = URLDecoder.decode(data, StandardCharsets.UTF_8.name());
  52. } catch (Exception e) {
  53. log.error("解码出错!", e);
  54. throw new RuntimeException(e);
  55. }
  56. return target;
  57. }
  58. /* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ URL 编码、解码 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */
  59. /* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ MD5加密相关 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
  60. /** * MD5加密 * * @param data * @return 大写 */
  61. public static String encryptMD5(final byte[] data) {
  62. return DigestUtils.md5Hex(data).toUpperCase();
  63. }
  64. /** * MD5加密,字符串到字符串 * * @param data * @return 大写 */
  65. public static String encryptMD5(final String data) {
  66. return encryptMD5(data.getBytes());
  67. }
  68. /** * 3次MD5加密,字符串到字符串 * * @param data * @return 大写 */
  69. public static String encryptTriMD5(final String data) {
  70. int count = 3;
  71. String md5 = data;
  72. for (int i = 0; i < count; i++) {
  73. md5 = encryptMD5(md5);
  74. }
  75. return md5;
  76. }
  77. /** * 生成含有随机盐的加密字符串 * * @param data 待加密的字符 * @return 加密后的字符(含 16 位随机盐),大写 */
  78. public static String encryptMD5WithRandomSalt(final String data) {
  79. return encryptMd5WithRandomSalt(data);
  80. }
  81. /** * 校验密码是否正确 * * @param data 待验证的字符(明文) * @param md5StringWithSalt 加密后的字符(含 16 位随机盐) * @return 验证结果 */
  82. public static boolean verifyMD5WithRandomSalt(final String data, final String md5StringWithSalt) {
  83. return verifyMd5WithRandomSalt(data, md5StringWithSalt);
  84. }
  85. /* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ MD5加密相关 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */
  86. /* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ SHA 加密 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
  87. /** * 默认使用 SHA-1 20字节 160位 * 其他还有: * SHA-224 32字节 224位 * SHA-256 32字节 256位 * SHA-384 48字节 384位 * SHA-512 64字节 512位 * 由于它产生的数据摘要的长度更长,因此更难以发生碰撞,因此较之MD5更为安全,它是未来数据摘要算法的发展方向。 * 由于SHA系列算法的数据摘要长度较长,因此其运算速度与MD5相比,也相对较慢。 */
  88. /** * SHA 加密 * * @param data * @return */
  89. public static String encryptSHA(final byte[] data) {
  90. return DigestUtils.sha1Hex(data).toUpperCase();
  91. }
  92. /** * SHA 加密,字符串到字符串 <br> * <br> * * @param data * @return */
  93. public static String encryptSHA(final String data) {
  94. return DigestUtils.sha1Hex(data).toUpperCase();
  95. }
  96. /* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ SHA 加密 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */
  97. /* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ MAC加密相关 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
  98. /** * 默认使用 HmacMD5 加密。 * 其他还有: * HmacSHA1 * HmacSHA256 * HmacSHA384 * HmacSHA512 */
  99. /** * 初始化 MAC 密钥 * * @return MAC 密钥 * @throws NoSuchAlgorithmException */
  100. public static String initMacKey() throws NoSuchAlgorithmException {
  101. KeyGenerator keyGenerator = KeyGenerator.getInstance(HmacAlgorithms.HMAC_MD5.getName());
  102. SecretKey secretKey = keyGenerator.generateKey();
  103. return encryptBase64(secretKey.getEncoded());
  104. }
  105. /** * MAC 加密 * * @param data 待加密数据 * @param key 密钥,可用 initMacKey() 方法生成,也可自定义 * @return 加密后数据 */
  106. public static String encryptHMAC(final byte[] data, final String key) {
  107. HmacUtils hmacMd5 = new HmacUtils(HmacAlgorithms.HMAC_MD5, key);
  108. return hmacMd5.hmacHex(data).toUpperCase();
  109. }
  110. /* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ MAC加密相关 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */
  111. /** * 生成含有随机盐的加密字符串 * * @param data 待加密的字符 * @return 加密后的字符(含 16 位随机盐),大写 */
  112. private static String encryptMd5WithRandomSalt(String data) {
  113. Random r = new Random();
  114. StringBuilder sb = new StringBuilder(16);
  115. sb.append(r.nextInt(99999999))
  116. .append(r.nextInt(99999999));
  117. int len = sb.length();
  118. if (len < 16) {
  119. for (int i = 0; i < 16 - len; i++) {
  120. sb.append("0");
  121. }
  122. }
  123. String salt = sb.toString();
  124. String md5WithSaltStr = DigestUtils.md5Hex(data + salt);
  125. char[] cs = new char[48];
  126. for (int i = 0; i < 48; i += 3) {
  127. cs[i] = md5WithSaltStr.charAt(i / 3 * 2);
  128. char c = salt.charAt(i / 3);
  129. cs[i + 1] = c;
  130. cs[i + 2] = md5WithSaltStr.charAt(i / 3 * 2 + 1);
  131. }
  132. return new String(cs).toUpperCase();
  133. }
  134. /** * 校验密码是否正确 * * @param data 待验证的字符(明文) * @param md5StrContainRandomSalt 加密后的字符(含 16 位随机盐) * @return 验证结果 */
  135. private static boolean verifyMd5WithRandomSalt(String data, String md5StrContainRandomSalt) {
  136. // 32 位加密字符(不含盐)
  137. char[] cs1 = new char[32];
  138. // 16 位的随机盐
  139. char[] cs2 = new char[16];
  140. for (int i = 0; i < 48; i += 3) {
  141. cs1[i / 3 * 2] = md5StrContainRandomSalt.charAt(i);
  142. cs1[i / 3 * 2 + 1] = md5StrContainRandomSalt.charAt(i + 2);
  143. cs2[i / 3] = md5StrContainRandomSalt.charAt(i + 1);
  144. }
  145. String salt = new String(cs2);
  146. return Objects.equals(DigestUtils.md5Hex(data + salt).toUpperCase(), new String(cs1));
  147. }
  148. }

三、对称加密

对称加密

四、非对称加密

先来看看这两篇文章,帮助理解 非对称加密数字签名,写得挺好的。

  • RSA算法原理(一)
  • RSA算法原理(二)
  • 数字签名是什么?

非对称加密

在线加密测试工具

在线加密解密工具

参考相关文章

  • Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC
  • Java加密技术(二)——对称加密算法DES&AES
  • 【JAVA】AES加密 简单实现 AES-128/ECB/PKCS5Padding
  • java加解密之DES多种使用方式
  • 3DES加密算法
  • Java加密技术(四)——非对称加密算法RSA
  • RSA加密解密及数字签名Java实现
  • AES apache commons-crypto 对称加密

发表评论

表情:
评论列表 (有 0 条评论,27人围观)

还没有评论,来说两句吧...

相关阅读

    相关 常见加密算法

     一、概念       [数据加密][Link 1]的基本过程就是对原来为明文的文件或数据按某种[算法][Link 2]进行处理,使其成为不可读的一段代码为“密文”,使其

    相关 Java中随机数

    摘要:众所周知,随机数是任何一种编程语言最基本的特征之一。而生成随机数的基本方式也是相同的:产生一个0到1之间的随机数。看似简单,但有时我们也会忽略了一些有趣的功能。 众所周