常用的算法介紹
常用的算法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關注"保密"(如數據加密)