常用的算法介绍
常用的算法JAVA实现
jce及其它开源包介绍、对比
传送门
数据安全系列1:开篇
数据安全系列2:单向散列函数概念
数据安全系列3:密码技术概述
时代有浪潮,就有退去的时候
在我的博客文章里面,其中绝大多数都是专注于技术探讨,间或一些设计或项目管理的分享。极少有关于个人看法、感悟之类。不过在上一篇数据安全系列3:密码技术概述里面谈到了如何应对工作的压力:
打工的终极目标是跳槽或者变成合伙人
所以这里就想再写几句,权当"吐槽"几句!
这是最好的时代,也是最坏的时代
“这是最好的时代,也是最坏的时代”,英国文学家狄更斯曾这样描述工业革命发生后的世界。这句话放在现在亦不为过,彼时彼刻恰如此时此刻!记得14年住在杭州出租屋的时候,偶然看到同学买的《浪潮之巅》被序里面的几句话所吸引:
因为,虽然对于一个公司来讲,赶上一次浪潮不能保证它长盛不衰;但是,对于一个人来讲,一生赶上这样一次浪潮就足够了。对于一个弄潮的年轻人来讲,最幸运的莫过于赶上一波大潮。
--------引自《浪潮之巅》
里面的内容:微软、google、IBM这些超一流公司的前世今生介绍;浏览器大战,客厅争夺、微机之争商战风起云涌;还有对于投资银行、华尔街、硅谷的角色解读;关于亚太地区,尤其是阿里巴巴的精准预测,深深打动了当时那个年轻人,迷茫又坚定的投入了软件开发行业!在后续的几年中也确实赶上了移动互联网这个浪潮。
近一百多年来,总有一些公司很幸运地、有意识或者无意识地站在技术革命的浪尖之上。
一旦处在了那个位置,即使不做任何事,也可以随着波浪顺顺当当地向前漂个十年甚至更长
的时间。在这十几年间,它们代表着科技的浪潮,直到下一波浪潮的来临。--------也引自《浪潮之巅》
诚如作者所说,浪潮袭来整个行业生机勃勃、浪尖之上一切看起来皆有可为。但是浪潮退祛之后到底是继续繁荣、还是平稳衰退作者却并为给出预测。甚至哀鸿遍野都殊为可知,而且一切并非妄语!做为身在其中的从业者感受更是提前感受到了"寒冬"
经济的冲击
俗话说“春江水暖鸭告知”。首当其冲的是大家普遍会觉得找工作变难了,大家也不敢随便跳槽了:
- 很多公司都开始裁员了,无论是所谓的老牌BAT、新晋的PATB这些互联网;还是国企所属
- 很多公司都严查考勤了,包括宣称"不打卡"的互联网;也开始到期不续约了,变相裁员
- 更重要的是降薪,不论是砍福利、通过绩效手段劝退、还是整体降薪
而这一切其实最终都是经济这只大手带来的影响,企业打响了"降本增效"的大旗,砍向了里面的每一个人。被迫离开的人有的找工作时间普遍变长了,GAP几个月屡见不鲜;还有的人可能就真的彻底告别这个行业了,离职=失业不再是一句自我调侃。
一个在阿里呆了5年的同事,怀着"闯一番"的念头主动离职,加入了做在线教育的创业公司,没过多久由于众所周知的原因失业了,从此在本地再也找不到合适的工作,最后异地去了苏州上班。
AI的冲击
除了外部环境冲击,行业内也在悄然起了变化。这2年AI的兴起其实对IT行业也有影响,这点不得不承认。比如我感觉AI对话的很多问题,就算是计算机专业领域,也回答的非常合理甚至更为全面(请放心这里不是打广告也不卖课...)。等哪一天AI真的能写业务逻辑,那就是真正的程序员革命,公司也不需要招这么多程序员了,这与前2年挂羊头狗肉的低代码有本质区别,意味着AI可能真的要来临了!
山重水复疑无路,柳暗花明又一村
十年前我刚加入这一行的时候,就听过35岁危机,当时大家对这种观点更多的是一种自嘲。时过境迁再回首人已中年。不过借用一句古话,天踏下来还有高个子顶着,就不要再散播焦虑,让我们言归正传,看看常用的密码算法吧
密码学家的工具箱
章节名称的由来
前面推荐了作为一本入门书的《图解密码技术_百度百科 》,里面提出了密码学家的工具箱这个说法,也通过讨论得到了下面这个图:
常见的密码算法
有一点要明确下来的就是所讨论的加密算法最终目的,是为了解决信息安全所面临的问题:
机密性
我们为了保证信息的机密性,也就是不让别人看到信息或者看到了也"看不懂"所以引入了加密的这种方法,而出于安全性与性能的区别,又有很多不同的加密算法。其中最常见的就是对称加密!
对称加密算法
对称加密基本概念
对称加密是指加密和解密使用相同密钥的加密算法。发送方使用密钥将明文加密成密文,接收方使用相同的密钥将密文解密回明文。对称加密算法通常计算效率高,适合大量数据的加密。
加密过程
解密过程
DES
先来看看DES算法:
DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。需要注意的是,在某些文献中,作为算法的DES称为数据加密算法(Data Encryption Algorithm,DEA),已与作为标准的DES区分开来。
----------------------引自百度百科DES
它出现的时期比较早,由于现在计算机技术的发展已不再推荐使用,因为可以被暴力破解了。它的加密过程如下:

看一个用JAVA生成的例子:
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;public class DESExample {private static final String ALGORITHM = "DES";public static String encrypt(String key, String value) throws Exception {// DES需要8字节的密钥if (key.length() < 8) {throw new IllegalArgumentException("Key must be at least 8 characters for DES");}SecretKeySpec secretKey = new SecretKeySpec(key.substring(0, 8).getBytes("UTF-8"), ALGORITHM);Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, secretKey);byte[] encryptedBytes = cipher.doFinal(value.getBytes());return Base64.getEncoder().encodeToString(encryptedBytes);}public static String decrypt(String key, String encryptedValue) throws Exception {SecretKeySpec secretKey = new SecretKeySpec(key.substring(0, 8).getBytes("UTF-8"), ALGORITHM);Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, secretKey);byte[] decodedBytes = Base64.getDecoder().decode(encryptedValue);byte[] decryptedBytes = cipher.doFinal(decodedBytes);return new String(decryptedBytes);}public static void main(String[] args) {try {String key = "mySecret"; // 8字节的密钥String original = "Hello, World!";String encrypted = encrypt(key, original);System.out.println("Encrypted: " + encrypted);String decrypted = decrypt(key, encrypted);System.out.println("Decrypted: " + decrypted);} catch (Exception e) {e.printStackTrace();}}
}
上面的示例代码可以完整的展现DES的加解密过程,但是要强调几点:
- DES 已被 NIST 淘汰(2005 年),切勿用于新项目
- 密钥为什么需要 8 字节?DES 算法要求密钥必须是 8 字节(64 位)(实际有效密钥为 56 位,8 位用于奇偶校验)
3DES
接着看看看看3DES算法:
3DES(即Triple DES)是DES向AES过渡的加密算法,它使用3条56位的密钥对数据进行三次加密。是DES的一个更安全的变形。它以DES为基本模块,通过组合分组方法设计出分组加密算法。比起最初的DES,3DES更为安全。
现在由于DES已经可以在限时的时间内破解,因此三重DES就是开发出来替代DES的一种分组密码。它的加密过程如下:

看一个用JAVA生成的例子:
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;public class TripleDESExample {private static final String ALGORITHM = "DESede";public static String encrypt(String key, String value) throws Exception {// 3DES需要24字节的密钥if (key.length() < 24) {throw new IllegalArgumentException("Key must be at least 24 characters for 3DES");}SecretKeySpec secretKey = new SecretKeySpec(key.substring(0, 24).getBytes("UTF-8"), ALGORITHM);Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, secretKey);byte[] encryptedBytes = cipher.doFinal(value.getBytes());return Base64.getEncoder().encodeToString(encryptedBytes);}public static String decrypt(String key, String encryptedValue) throws Exception {SecretKeySpec secretKey = new SecretKeySpec(key.substring(0, 24).getBytes("UTF-8"), ALGORITHM);Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, secretKey);byte[] decodedBytes = Base64.getDecoder().decode(encryptedValue);byte[] decryptedBytes = cipher.doFinal(decodedBytes);return new String(decryptedBytes);}public static void main(String[] args) {try {String key = "mySecretKey12345678901234"; // 24字节的密钥String original = "Hello, World!";String encrypted = encrypt(key, original);System.out.println("Encrypted: " + encrypted);String decrypted = decrypt(key, encrypted);System.out.println("Decrypted: " + decrypted);} catch (Exception e) {e.printStackTrace();}}
}
AES
接着看看AES算法:
密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。
这个标准用来替代原先的DES(Data Encryption Standard),已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院 (NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一
----------------------引自百度百科AES
由于AES的设计目标就是要解决DES的安全性的问题,所以在没有特殊的要求场景(比如旧程序兼容性问题)都建议使用AES。它的加密过程如下:

看一个用JAVA生成的例子:
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;public class AESUtil {private static final String ALGORITHM = "AES";private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";private static final int IV_SIZE = 16; // 128位IV/*** AES加密(使用CBC模式)*/public static String encrypt(String key, String value) throws Exception {// 生成随机IVbyte[] iv = new byte[IV_SIZE];new SecureRandom().nextBytes(iv);SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), ALGORITHM);IvParameterSpec ivSpec = new IvParameterSpec(iv);Cipher cipher = Cipher.getInstance(TRANSFORMATION);cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);byte[] encrypted = cipher.doFinal(value.getBytes());// 将IV和加密数据合并byte[] encryptedIVAndText = new byte[iv.length + encrypted.length];System.arraycopy(iv, 0, encryptedIVAndText, 0, iv.length);System.arraycopy(encrypted, 0, encryptedIVAndText, iv.length, encrypted.length);return Base64.getEncoder().encodeToString(encryptedIVAndText);}/*** AES解密*/public static String decrypt(String key, String encryptedValue) throws Exception {byte[] ivAndEncrypted = Base64.getDecoder().decode(encryptedValue);// 提取IVbyte[] iv = new byte[IV_SIZE];System.arraycopy(ivAndEncrypted, 0, iv, 0, iv.length);// 提取加密数据byte[] encrypted = new byte[ivAndEncrypted.length - IV_SIZE];System.arraycopy(ivAndEncrypted, IV_SIZE, encrypted, 0, encrypted.length);SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), ALGORITHM);IvParameterSpec ivSpec = new IvParameterSpec(iv);Cipher cipher = Cipher.getInstance(TRANSFORMATION);cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);byte[] decrypted = cipher.doFinal(encrypted);return new String(decrypted);}public static void main(String[] args) {try {String key = "MySecretKey12345"; // 16字节用于AES-128String original = "敏感数据需要加密";String encrypted = encrypt(key, original);System.out.println("加密结果: " + encrypted);String decrypted = decrypt(key, encrypted);System.out.println("解密结果: " + decrypted);} catch (Exception e) {e.printStackTrace();}}
}
SM4
SM4(原名SMS4)是中国国家密码管理局发布的商用密码算法标准(GB/T 37033-2018),属于对称分组密码算法。其分组长度和密钥长度均为128位,与AES(Advanced Encryption Standard)类似,但属于中国自主知识产权的加密算法。以下是SM4的基本原理及Java实现的详细说明。
SM4属于国密范畴,它有其自身的特点,尤其是在信创的大背景下,使得它的应用会越来越广泛:
一、SM4算法概述
- 分组长度:128位(16字节)
- 密钥长度:128位(16字节)
- 加密轮数:32轮
- 工作模式:支持ECB(电子密码本)、CBC(密码块链接)、CFB(反馈模式)、OFB(输出反馈模式)等。
- 应用场景:适用于需要国密合规的场景,如金融、政务、物联网等。
Java标准库(JCE)默认不支持SM4,需通过第三方库(如 Bouncy Castle)实现。
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.70</version> <!-- 使用最新版本 -->
</dependency>
看一个用JAVA生成的例子:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;public class SM4Example {static {// 注册Bouncy Castle提供者Security.addProvider(new BouncyCastleProvider());}// SM4加密public static byte[] encrypt(byte[] data, byte[] key) throws Exception {SecretKey secretKey = new SecretKeySpec(key, "SM4");Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, secretKey);return cipher.doFinal(data);}// SM4解密public static byte[] decrypt(byte[] cipherText, byte[] key) throws Exception {SecretKey secretKey = new SecretKeySpec(key, "SM4");Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, secretKey);return cipher.doFinal(cipherText);}public static void main(String[] args) throws Exception {String plainText = "Hello, SM4!";byte[] key = "1234567890abcdef".getBytes(); // 16字节密钥// 加密byte[] encrypted = encrypt(plainText.getBytes(), key);System.out.println("加密结果(Base64): " + java.util.Base64.getEncoder().encodeToString(encrypted));// 解密byte[] decrypted = decrypt(encrypted, key);System.out.println("解密结果: " + new String(decrypted));}
}
分析对比
上面介绍了几种常用、主流的算法,下面表格列出了相应的特点:
算法 | 密钥长度 | 块大小 | 状态 | 特点 |
---|---|---|---|---|
DES | 56位 | 64位 | 已淘汰 | 早期标准,易被暴力破解 |
3DES | 112/168位 | 64位 | 逐渐淘汰 | DES的三重应用,安全性提高但效率低 |
AES | 128/192/256位 | 128位 | 推荐使用 | 目前最广泛使用的标准,安全高效 |
SM4 | 128位 | 128位 | 推荐使用 | 适用于需要国密合规的场景,如金融、政务等 |
除此以外还一些不是很常用的算法:
Blowfish | 32-448位 | 64位 | 可用 | 速度快,但块大小较小 |
RC4 | 40-2048位 | 流密码 | 不推荐 | 曾广泛使用,现发现多处漏洞 |
这里就不展开了,有兴趣的可以直接链接查看。
还有一个值得关注的算法是Gooble开发的ChaCha20:
ChaCha20-Poly1305是Google所采用的一种新式加密算法,性能强大,在CPU为精简指令集的ARM平台上尤为显著(ARM v8前效果较明显),在同等配置的手机中表现是AES的4倍(ARM v8之后加入了AES指令,所以在这些平台上的设备,AES方式反而比chacha20-Poly1305方式更快,性能更好),可减少加密解密所产生的数据量进而可以改善用户体验,减少等待时间,节省电池寿命等。
ChaCha20-Poly1305是由ChaCha20流密码和Poly1305消息认证码(MAC)结合的一种应用在互联网安全协议中的认证加密算法,由Google公司率先在Andriod移动平台中的Chrome中代替RC4使用。
由于其算法精简、安全性强、兼容性强等特点,目前Google致力于全面将其在移动端推广
模式介绍
从上面的对比讨论可以看出,现在推荐的加密算法要么是AES、要么是SM4这两种。它们的代码也极其类似:
// AES
private static final String ALGORITHM = "AES";private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";private static final int IV_SIZE = 16; // 128位IVSecretKey secretKey = new SecretKeySpec(key.getBytes("UTF-8"), ALGORITHM);IvParameterSpec ivSpec = new IvParameterSpec(iv);Cipher cipher = Cipher.getInstance(TRANSFORMATION);cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
// SM4
SecretKey secretKey = new SecretKeySpec(key, "SM4");Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, secretKey);
这里的格式:AES/CBC/PKCS5Padding是指定算法的参数格式,表示为
算法/工作模式/填充模式
工作模式

这里列个表格来对比看看:
模式 | 全称 | 特点 | 安全性 | 推荐使用 |
---|---|---|---|---|
ECB | Electronic Codebook | 相同明文→相同密文 | ❌ 极不安全 | 绝不使用 |
CBC | Cipher Block Chaining | 需要IV,错误传播 | ⚠️ 需谨慎实现 | 传统系统可用 |
CTR | Counter | 类似流密码,可并行 | ✅ 良好 | 适合流式处理 |
GCM | Galois/Counter Mode | 认证加密,带完整性 | ✅ 最佳 | 现代系统首选 |
写在最后
关于数据安全虽然整理了好几篇文章。不过说实话,我觉得对于算法还是没有入门,最多是使用上初窥门径(尝试看了一下算法源码,就是看不懂。。。),所以建议大家有兴趣还是先看看作为一本入门书的《图解密码技术_百度百科 》虽然看了第2遍了,还是常看常新!
至于非对称算法,我们下篇文章再来仔细讨论
附录:JCA与JCE关系
因为它们底层都是使用的同一个加密算法框架Java Cryptography Architecture (JCA) :
JCA是Java平台的加密体系基础架构,它是一个框架性设计而非具体实现:
- 本质:一套服务提供者接口(SPI)和应用程序接口(API)的集合
- 核心包:
java.security
、java.security.cert
、java.security.interfaces
- 设计目标:
- 提供统一的加密服务访问方式
- 支持算法独立性(应用程序不依赖特定算法)
- 支持Provider机制(可插拔的加密实现)
- 遵循"一次编写,到处运行"的Java原则
而它对应的代码就在jce.jar包里面,是对jca的扩展:
JCE是JCA的官方扩展,专注于提供对称加密、非对称加密和密钥协商功能:
- 本质:JCA框架的扩展规范
- 核心包:
javax.crypto
、javax.crypto.interfaces
、javax.crypto.spec
- 关键类:
Cipher
、KeyGenerator
、SecretKeyFactory
、Mac
3. jce.jar
jce.jar是JCE规范的具体实现文件:
- 位置:
$JAVA_HOME/jre/lib/jce.jar
- 内容:SunJCE Provider的实现代码
- 作用:提供JCE API的具体算法实现
- 历史:最初是独立下载的扩展包,现已成为标准JDK的一部分
详细关系解析
JCA是基础架构,JCE是其扩展
JCA:提供基础加密服务框架,包括:
- 消息摘要(MD5, SHA)
- 数字签名(DSA, RSA)
- 密钥生成(KeyPairGenerator)
- 安全随机数生成(SecureRandom)
JCE:在JCA基础上扩展了:
- 对称加密(AES, DES, 3DES)
- 非对称加密(RSA加密/解密)
- 密钥协商(Diffie-Hellman)
- 消息认证码(HMAC)
关键区别:JCA主要关注"验证"(如数字签名),而JCE关注"保密"(如数据加密)