面试官:说一下你常用的加密算法

 [[335623]]

加密算法我们整体可以分为:可逆加密和不可逆加密,可逆加密又可以分为:对称加密和非对称加密。

一、不可逆加密

常见的不可逆加密算法有MD5,HMAC,SHA1、SHA-224、SHA-256、SHA-384,和SHA-512,其中SHA-224、SHA-256、SHA-384,和SHA-512我们可以统称为SHA2加密算法,SHA加密算法的安全性要比MD5更高,而SHA2加密算法比SHA1的要高。其中SHA后面的数字表示的是加密后的字符串长度,SHA1默认会产生一个160位的信息摘要。

不可逆加密算法最大的特点就是密钥,但是HMAC是需要密钥的【手动狗头】。

由于这些加密都是不可逆的,因此比较常用的场景就是用户密码加密,其验证过程就是通过比较两个加密后的字符串是否一样来确认身份的。网上也有很多自称是可以破解MD5密码的网站,其原理也是一样,就是有一个巨大的资源库,存放了许多字符串及对应的MD5加密后的字符串,通过你输入的MD5加密串来进行比较,如果过你的密码复杂度比较低,还是有很大机率验证出来的。

1.1 MD5

MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。

MD5算法有以下特点:

1、压缩性:无论数据长度是多少,计算出来的MD5值长度相同

2、容易计算性:由原数据容易计算出MD5值

3、抗修改性:即便修改一个字节,计算出来的MD5值也会巨大差异

4、抗碰撞性:知道数据和MD5值,很小概率找到相同MD5值相同的原数据。

  1. public static String md5(String text) { 
  2.    MessageDigest messageDigest = null
  3.     try { 
  4.          messageDigest = MessageDigest.getInstance("MD5"); 
  5.      } catch (NoSuchAlgorithmException e) { 
  6.          e.printStackTrace(); 
  7.      } 
  8.      byte[] bytes = messageDigest.digest(text.getBytes()); 
  9.      return Hex.encodeHexString(bytes);  

1.2 SHA系列

安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。

2005年8月17日的CRYPTO会议尾声中王小云、姚期智、姚储枫再度发表更有效率的SHA-1攻击法,能在2的63次方个计算复杂度内找到碰撞。

也就是说SHA-1加密算法有碰撞的可能性,虽然很小。

  1. public static String sha256(String text) { 
  2.     MessageDigest messageDigest = null
  3.     try { 
  4.         messageDigest = MessageDigest.getInstance("SHA-256"); 
  5.     } catch (NoSuchAlgorithmException e) { 
  6.         e.printStackTrace(); 
  7.     } 
  8.     byte[] bytes = messageDigest.digest(text.getBytes());  
  9.     return Hex.encodeHexString(bytes);  

1.3 HMAC系列

HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code)的缩写,由H.Krawezyk,M.Bellare,R.Canetti于1996年提出的一种基于Hash函数和密钥进行消息认证的方法,并于1997年作为RFC2104被公布,并在IPSec和其他网络协议(如SSL)中得以广泛应用,现在已经成为事实上的Internet安全标准。它可以与任何迭代散列函数捆绑使用。

HMAC算法更像是一种加密算法,它引入了密钥,其安全性已经不完全依赖于所使用的Hash算法

  1. public static String hmacSha256(String text, SecretKeySpec sk) { 
  2.     Mac mac = null
  3.     try { 
  4.         mac = Mac.getInstance("HmacSHA256"); 
  5.     } catch (NoSuchAlgorithmException e) { 
  6.         e.printStackTrace(); 
  7.     } 
  8.     try { 
  9.         mac.init(sk); 
  10.     } catch (InvalidKeyException e) { 
  11.         e.printStackTrace(); 
  12.     } 
  13.     byte[] rawHmac = mac.doFinal(text.getBytes()); 
  14.     return new String(Base64.encodeBase64(rawHmac)); 

如果要使用不可逆加密,推荐使用SHA256、SHA384、SHA512以及HMAC-SHA256、HMAC-SHA384、HMAC-SHA512这几种算法。

二、对称加密算法

对称加密算法是应用比较早的算法,在数据加密和解密的时用的都是同一个密钥,这就造成了密钥管理困难的问题。常见的对称加密算法有DES、3DES、AES128、AES192、AES256 (默认安装的 JDK 尚不支持 AES256,需要安装对应的 jce 补丁进行升级 jce1.7,jce1.8)。其中AES后面的数字代表的是密钥长度。对称加密算法的安全性相对较低,比较适用的场景就是内网环境中的加解密。

2.1 DES

DES是对称加密算法领域中的典型算法,其密钥默认长度为56位。

  1. / 加密 
  2.  public static String encrypt(byte[] dataSource, String password){ 
  3.       try { 
  4.           SecureRandom random = new SecureRandom(); 
  5.           DESKeySpec desKeySpec = new DESKeySpec(password.getBytes()); 
  6.           //创建一个密匙工厂,然后用它把DESKeySpec转换成  
  7.           SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");  
  8.           SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);  
  9.           //Cipher对象实际完成加密操作  
  10.          Cipher cipher = Cipher.getInstance("DES");  
  11.          //用密匙初始化Cipher对象  
  12.          cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);  
  13.          //正式执行加密操作  
  14.          return Base64.encodeBase64String(cipher.doFinal(dataSource));  
  15.      } catch (Throwable e) {  
  16.          e.printStackTrace();  
  17.      } return null;  
  18.  }  
  19. // 解密 
  20. public static String decrypt(String src, String password) throws Exception{  
  21.     // DES算法要求有一个可信任的随机数源  
  22.     SecureRandom random = new SecureRandom();  
  23.     // 创建一个DESKeySpec对象  
  24.     DESKeySpec desKeySpec = new DESKeySpec(password.getBytes());  
  25.     // 创建一个密匙工厂  
  26.     SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
  27.     // 将DESKeySpec对象转换成SecretKey对象  
  28.     SecretKey secretKey = keyFactory.generateSecret(desKeySpec);  
  29.     // Cipher对象实际完成解密操作  
  30.     Cipher cipher = Cipher.getInstance("DES");  
  31.     // 用密匙初始化Cipher对象  
  32.     cipher.init(Cipher.DECRYPT_MODE, secretKey, random);  
  33.     // 真正开始解密操作  
  34.     return new String(cipher.doFinal(Base64.decodeBase64(src)));  

2.2 3DES

3DES(即Triple DES)是DES向AES过渡的加密算法,它使用3条56位的密钥对数据进行三次加密。是DES的一个更安全的变形。它以DES为基本模块,通过组合分组方法设计出分组加密算法。比起最初的DES,3DES更为安全。密钥长度默认为168位,还可以选择128位。

  1. public static String encryptThreeDESECB(String src, String key) { 
  2.      try{ 
  3.          DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8")); 
  4.          SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede"); 
  5.          SecretKey securekey = keyFactory.generateSecret(dks); 
  6.   
  7.          Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); 
  8.          cipher.init(Cipher.ENCRYPT_MODE, securekey); 
  9.          byte[] b = cipher.doFinal(src.getBytes("UTF-8")); 
  10.  
  11.         String ss = new String(Base64.encodeBase64(b)); 
  12.         ss = ss.replaceAll("\\+""-"); 
  13.         ss = ss.replaceAll("/""_"); 
  14.         return ss; 
  15.     } catch(Exception ex){ 
  16.         ex.printStackTrace(); 
  17.         return src; 
  18.     } 
  19.  
  20. public static String decryptThreeDESECB(String src, String key) { 
  21.     try{ 
  22.         src = src.replaceAll("-""+"); 
  23.         src = src.replaceAll("_""/"); 
  24.         byte[] bytesrc = Base64.decodeBase64(src.getBytes("UTF-8")); 
  25.         // --解密的key 
  26.         DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8")); 
  27.         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede"); 
  28.         SecretKey securekey = keyFactory.generateSecret(dks); 
  29.  
  30.         // --Chipher对象解密 
  31.         Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); 
  32.         cipher.init(Cipher.DECRYPT_MODE, securekey); 
  33.         byte[] retByte = cipher.doFinal(bytesrc); 
  34.  
  35.         return new String(retByte, "UTF-8"); 
  36.     } catch(Exception ex){ 
  37.         ex.printStackTrace(); 
  38.         return src; 
  39.     } 

2.3 AES

AES 高级数据加密标准,能够有效抵御已知的针对DES算法的所有攻击,默认密钥长度为128位,还可以供选择192位,256位。这里顺便提一句这个位指的是bit。

  1. private static final String defaultCharset = "UTF-8"
  2. private static final String KEY_AES = "AES"
  3. private static final String KEY_MD5 = "MD5"
  4. private static MessageDigest md5Digest; 
  5. static { 
  6.     try { 
  7.         md5Digest = MessageDigest.getInstance(KEY_MD5); 
  8.     } catch (NoSuchAlgorithmException e) { 
  9.  
  10.     } 
  11. /** 
  12.   * 加密 
  13.   */ 
  14. public static String encrypt(String data, String key) { 
  15.     return doAES(data, key, Cipher.ENCRYPT_MODE); 
  16. /** 
  17.   * 解密 
  18.   */ 
  19. public static String decrypt(String data, String key) { 
  20.     return doAES(data, key, Cipher.DECRYPT_MODE); 
  21.  
  22.  
  23. /** 
  24.   * 加解密 
  25.   */ 
  26. private static String doAES(String data, String keyint mode) { 
  27.     try { 
  28.         boolean encrypt = mode == Cipher.ENCRYPT_MODE; 
  29.         byte[] content; 
  30.         if (encrypt) { 
  31.             content = data.getBytes(defaultCharset); 
  32.         } else { 
  33.             content = Base64.decodeBase64(data.getBytes()); 
  34.         } 
  35.         SecretKeySpec keySpec = new SecretKeySpec(md5Digest.digest(key.getBytes(defaultCharset)) 
  36.                                                   , KEY_AES); 
  37.         Cipher cipher = Cipher.getInstance(KEY_AES);// 创建密码器 
  38.         cipher.init(mode, keySpec);// 初始化 
  39.         byte[] result = cipher.doFinal(content); 
  40.         if (encrypt) { 
  41.             return new String(Base64.encodeBase64(result)); 
  42.         } else { 
  43.             return new String(result, defaultCharset); 
  44.         } 
  45.     } catch (Exception e) { 
  46.     } 
  47.     return null

推荐使用对称加密算法有:AES128、AES192、AES256。

三、非对称加密算法

非对称加密算法有两个密钥,这两个密钥完全不同但又完全匹配。只有使用匹配的一对公钥和私钥,才能完成对明文的加密和解密过程。常见的非对称加密有RSA、SM2等。

3.1 RSA

RSA密钥至少为500位长,一般推荐使用1024位。

  1. //非对称密钥算法 
  2.   public static final String KEY_ALGORITHM = "RSA"
  3.    
  4.   /** 
  5.     * 密钥长度,DH算法的默认密钥长度是1024 
  6.     * 密钥长度必须是64的倍数,在512到65536位之间 
  7.     */ 
  8.   private static final int KEY_SIZE = 1024; 
  9.   //公钥 
  10. private static final String PUBLIC_KEY = "RSAPublicKey"
  11. //私钥 
  12. private static final String PRIVATE_KEY = "RSAPrivateKey"
  13. /** 
  14.   * 初始化密钥对 
  15.   * 
  16.   * @return Map 甲方密钥的Map 
  17.   */ 
  18. public static Map<String, Object> initKey() throws Exception { 
  19.     //实例化密钥生成器 
  20.     KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); 
  21.     //初始化密钥生成器 
  22.     keyPairGenerator.initialize(KEY_SIZE); 
  23.     //生成密钥对 
  24.     KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
  25.     //甲方公钥 
  26.     RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); 
  27.     //甲方私钥 
  28.     RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 
  29.     //将密钥存储在map中 
  30.     Map<String, Object> keyMap = new HashMap<String, Object>(); 
  31.     keyMap.put(PUBLIC_KEY, publicKey); 
  32.     keyMap.put(PRIVATE_KEY, privateKey); 
  33.     return keyMap; 
  34. /** 
  35.   * 私钥加密 
  36.   * 
  37.   * @param data 待加密数据 
  38.   * @param key  密钥 
  39.   * @return byte[] 加密数据 
  40.   */ 
  41. public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception { 
  42.  
  43.     //取得私钥 
  44.     PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key); 
  45.     KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
  46.     //生成私钥 
  47.     PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec); 
  48.     //数据加密 
  49.     Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 
  50.     cipher.init(Cipher.ENCRYPT_MODE, privateKey); 
  51.     return cipher.doFinal(data); 
  52.  
  53. /** 
  54.   * 公钥加密 
  55.   * 
  56.   * @param data 待加密数据 
  57.   * @param key  密钥 
  58.   * @return byte[] 加密数据 
  59.   */ 
  60. public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception { 
  61.  
  62.     //实例化密钥工厂 
  63.     KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
  64.     //初始化公钥 
  65.     //密钥材料转换 
  66.     X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key); 
  67.     //产生公钥 
  68.     PublicKey pubKey = keyFactory.generatePublic(x509KeySpec); 
  69.     //数据加密 
  70.     Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 
  71.     cipher.init(Cipher.ENCRYPT_MODE, pubKey); 
  72.     return cipher.doFinal(data); 
  73.  
  74. /** 
  75.   * 私钥解密 
  76.   * 
  77.   * @param data 待解密数据 
  78.   * @param key  密钥 
  79.   * @return byte[] 解密数据 
  80.   */ 
  81. public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception { 
  82.     //取得私钥 
  83.     PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key); 
  84.     KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
  85.     //生成私钥 
  86.     PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec); 
  87.     //数据解密 
  88.     Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 
  89.     cipher.init(Cipher.DECRYPT_MODE, privateKey); 
  90.     return cipher.doFinal(data); 
  91.  
  92. /** 
  93.   * 公钥解密 
  94.   * 
  95.   * @param data 待解密数据 
  96.   * @param key  密钥 
  97.   * @return byte[] 解密数据 
  98.   */ 
  99. public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception { 
  100.  
  101.     //实例化密钥工厂 
  102.     KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
  103.     //初始化公钥 
  104.     //密钥材料转换 
  105.     X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key); 
  106.     //产生公钥 
  107.     PublicKey pubKey = keyFactory.generatePublic(x509KeySpec); 
  108.     //数据解密 
  109.     Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 
  110.     cipher.init(Cipher.DECRYPT_MODE, pubKey); 
  111.     return cipher.doFinal(data); 
  112.  
  113. /** 
  114.   * 取得私钥 
  115.   * 
  116.   * @param keyMap 密钥map 
  117.   * @return byte[] 私钥 
  118.   */ 
  119. public static byte[] getPrivateKey(Map<String, Object> keyMap) { 
  120.     Key key = (Key) keyMap.get(PRIVATE_KEY); 
  121.     return key.getEncoded(); 
  122.  
  123. /** 
  124.   * 取得公钥 
  125.   * 
  126.   * @param keyMap 密钥map 
  127.   * @return byte[] 公钥 
  128.   */ 
  129. public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception { 
  130.     Key key = (Key) keyMap.get(PUBLIC_KEY); 
  131.     return key.getEncoded(); 

四、加密盐

加密盐也是比较常听到的一个概念,盐就是一个随机字符串用来和我们的加密串拼接后进行加密。加盐主要是为了提供加密字符串的安全性。假如有一个加盐后的加密串,黑客通过一定手段这个加密串,他拿到的明文,并不是我们加密前的字符串,而是加密前的字符串和盐组合的字符串,这样相对来说又增加了字符串的安全性。

文中的一些算法来源于网络,可直接复制使用。

比较推荐的几个加密算法有:

  • 不可逆加密:SHA256、SHA384、SHA512以及HMAC-SHA256、HMAC-SHA384、HMAC-SHA512
  • 对称加密算法:AES、3DES
  • 非对称加密算法:RSA

本文转载自微信公众号「 Java旅途」,可以通过以下二维码关注。转载本文请联系 Java旅途公众号。

 

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/150870.html<

(0)
运维的头像运维
上一篇2025-03-13 06:55
下一篇 2025-03-13 06:56

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注