什麼是密碼學?
密碼學是保護信息安全的科學,它通過加密技術將可讀的信息(明文)轉換為不可讀的形式(密文),只有授權方才能解密恢復原始內容。就像給信息上了一把"數字鎖",只有擁有正確"鑰匙"的人才能打開。
一、古典密碼學:密碼學的起源
古典密碼學主要靠 “替換” 和 “移位”,原理簡單,適合手動計算,常見於戰爭、書信保密。
1.1 核心原理
① 替換法 - 用固定規則替換原文中的字符
示例:bee
b → w, e → p
密文:wpp
分類:
單表替換:所有字符使用同一張替換表
原始:abcde
替換:swtrp
缺點:容易被破解 —— 比如英文中 “e” 出現頻率最高,只要統計密文中哪個字符出現最多,大概率就是 “e” 的替換。
多表替換:使用多張替換表,按密鑰輪換使用
表1:abcde → swtrp
表2:abcde → chfhk
表3:abcde → jftou
原文:bee
密鑰:312(表示用表3、表1、表2)
密文:fpk
優點:比單表安全,破解難度高很多。
② 移位法 - 按字母表位置移動字符
把字母表按固定位數 “平移”,最經典的是 “凱撒加密”(凱撒大帝用來給軍隊發命令)。
凱撒加密示例:
原始:abcde
後移2位:cdefg
"hello" → "jgnnq"
缺點:移位位數有限(最多 25 位),暴力嘗試幾次就能破解。
1.2 古典密碼的破解
頻率分析法:利用字母出現的統計規律
- 英文中’e’出現頻率最高(約12.7%)
- ‘t’, ‘a’, 'o’等也有明顯特徵
- 通過分析密文字母頻率推測替換規則
歷史名機:恩尼格瑪密碼機(二戰時期德國使用,後被圖靈破解)
二、現代密碼學三大支柱
現代密碼學不再靠人工 / 簡單機器,而是靠數學算法,能應對海量數據、高併發場景,核心分 3 類:散列函數、對稱加密、非對稱加密。
2.1 散列函數(哈希函數):“不可逆的指紋”
散列函數能把任意長度的明文,變成固定長度、不可逆的密文(叫 “哈希值” 或 “消息摘要”),就像給信息蓋 “唯一指紋”。
核心特點:
- 不可逆:知道哈希值,無法反推明文(比如知道 “123” 的 MD5 是 “202cb962ac59075b964b07152d234b70”,沒法反推 “123”);
- 唯一性:不同明文(除非刻意構造 “碰撞”)的哈希值一定不同;
- 固定長度:不管明文是 1 字節還是 1GB,哈希值長度固定(比如 MD5 是 32 位十六進制,SHA-256 是 64 位十六進制)。
常見算法及用途:
|
算法
|
哈希值長度
|
用途
|
例子(明文 “123”)
|
|
MD5 |
32 位十六進制
|
文件校驗、密碼存儲(已逐漸被淘汰,易碰撞)
|
202cb962ac59075b964b07152d234b70
|
|
SHA-1(Secure Hash Algorithm) |
40 位十六進制
|
早期 Git 版本控制(已淘汰)
|
40bd001563085fc35165329ea1ff5c5ecbdbbeef
|
|
SHA-256 |
64 位十六進制
|
現在主流(文件校驗、區塊鏈、密碼存儲)
|
a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3
|
實戰場景:
- 網站存密碼:不會存明文 “123456”,而是存它的 SHA-256 哈希值,登錄時比對哈希值(即使數據庫泄露,黑客也拿不到明文密碼);
- 下載軟件校驗:官方給出安裝包的 SHA-256 值,你下載後算一遍,如果一致,説明沒被篡改。
Java 代碼示例(計算 MD5):
import java.security.MessageDigest;
public class HashDemo {
public static void main(String[] args) throws Exception {
String input = "123"; // 明文
// 1. 獲取MD5算法實例
MessageDigest md = MessageDigest.getInstance("MD5");
// 2. 計算哈希值(字節數組)
byte[] hashBytes = md.digest(input.getBytes());
// 3. 轉成16進制字符串(方便查看)
StringBuilder sb = new StringBuilder();
for (byte b : hashBytes) {
sb.append(String.format("%02x", b)); // %02x表示補0成2位十六進制
}
System.out.println("MD5哈希值:" + sb.toString()); // 輸出:202cb962ac59075b964b07152d234b70
}
}
2.2 對稱加密:同一把鑰匙
加密和解密用同一把密鑰,就像你家的門,鑰匙既能鎖門也能開門。特點是 “快”,適合加密大量數據。
(1)常見算法對比:
|
算法
|
密鑰長度
|
特點
|
用途
|
|
DES
|
8 字節(64 位,含 1 位校驗)
|
早期算法,安全性低(已淘汰)
|
舊系統兼容
|
|
3DES
|
24 字節(3 個 DES 密鑰)
|
對 DES 三次加密,安全性提高,但速度慢
|
舊金融系統
|
|
AES
|
16/192/256 字節(推薦 16 字節)
|
現在主流,速度快、安全性高
|
手機支付、文件加密、HTTPS 數據傳輸
|
技術分類:
- 流加密:逐位加密,如RC4
123456789 → 先加密1,再加密2,再加密3… - 塊加密:分組加密,如AES
12345678 → 分成[1234]和[5678]分別加密
特點:
- ✅ 加密速度快
- ✅ 適合大數據量加密
- ❌ 密鑰分發和管理困難
- ❌ 無法實現數字簽名
(2)關鍵概念:加密模式 + 填充模式
對稱加密按 “塊” 處理數據(比如 AES 每次處理 16 字節),需要解決 “數據不夠塊長” 和 “相同明文出相同密文” 的問題:
① 加密模式:決定怎麼處理多塊數據
|
模式
|
特點
|
優點
|
缺點
|
|
ECB
|
每塊獨立加密,相同明文塊出相同密文塊
|
並行處理,速度快
|
不安全(容易被破解規律)
|
|
CBC
|
每塊先和前一塊密文 “異或”,再加密
|
相同明文出不同密文,安全
|
串行處理,速度稍慢(需要初始向量 IV)
|
例子:加密 “abcabcabc”(AES-16 字節,ECB vs CBC)
ECB:兩個 “abc” 塊加密後密文相同;CBC:第一個 “abc” 用 IV 加密,第二個 “abc” 和第一個密文異或後加密,密文不同。
推薦:用 CBC 模式,更安全。
② 填充模式:解決 “數據不夠塊長”
如果數據長度不是塊長的整數倍(比如 AES-16 字節,數據只有 10 字節),需要 “補滿”:
NoPadding:不填充,要求數據必須是塊長的整數倍(否則報錯);PKCS5Padding:缺 n 字節就補 n 個 “n”(比如缺 6 字節,補 6 個 “\x06”),最常用。
(3)實戰注意:結合 Base64
對稱加密的密文是 “字節數組”(比如[65, -12, 34]),直接傳輸會亂碼,所以通常用Base64 編碼轉成字符串(比如 “QT4i”)。
⚠️ 注意:Base64 是編碼不是加密,目的是 “方便傳輸”,不是 “保密”!
(4)Java 代碼示例(AES-CBC 加密):
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class AesDemo {
// AES密鑰(16字節)、初始向量IV(16字節,CBC模式必須)
private static final String KEY = "1234567890abcdef";
private static final String IV = "abcdef1234567890";
// 加密:明文→密文(Base64字符串)
public static String encrypt(String plaintext) throws Exception {
// 1. 生成密鑰和IV
SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes());
// 2. 初始化Cipher(CBC模式+PKCS5Padding)
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
// 3. 加密→Base64編碼
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes());
return Base64.getEncoder().encodeToString(cipherBytes);
}
// 解密:密文(Base64字符串)→明文
public static String decrypt(String ciphertext) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
// 4. Base64解碼→解密
byte[] plainBytes = cipher.doFinal(Base64.getDecoder().decode(ciphertext));
return new String(plainBytes);
}
public static void main(String[] args) throws Exception {
String plaintext = "我是秘密消息";
// 加密
String ciphertext = encrypt(plaintext);
System.out.println("加密後(Base64):" + ciphertext); // 比如:xY+...(長字符串)
// 解密
String decrypted = decrypt(ciphertext);
System.out.println("解密後:" + decrypted); // 輸出:我是秘密消息
}
}
3. 非對稱加密:“公鑰加密,私鑰解密”
用一對密鑰(公鑰 + 私鑰):公鑰可以公開(像地址一樣分享給別人),私鑰自己保存(絕對不能泄露)。特點是 “安全”,但速度慢,適合加密少量數據(比如密鑰)。
(1)核心規則:
- 公鑰加密的密文,只有對應的私鑰能解密;
- 私鑰加密的密文(叫 “數字簽名”),只有對應的公鑰能解密;
- 公鑰由私鑰生成,無法從公鑰反推私鑰。
(2)常見算法對比:
|
算法
|
密鑰長度
|
特點
|
用途
|
|
|
1024/2048/4096 位(推薦 2048 位)
|
兼容性好,應用廣
|
數字簽名、密鑰交換(HTTPS)
|
|
|
160/256 位
|
相同安全級下,密鑰更短、速度更快
|
移動端加密、區塊鏈(比特幣用 ECC)
|
|
|
1024 位
|
只用於數字簽名,不能加密數據
|
身份驗證
|
(3)實戰場景:HTTPS 的 “密鑰交換”**
HTTPS 為什麼安全?
因為它結合了 “對稱 + 非對稱” 加密:
- 瀏覽器向服務器要 “公鑰”;
- 瀏覽器用公鑰加密 “對稱密鑰”(比如 AES 密鑰),發給服務器;
- 服務器用私鑰解密,拿到對稱密鑰;
- 後續數據傳輸,都用對稱密鑰加密(快)。
—— 既解決了對稱加密 “密鑰難傳輸” 的問題,又解決了非對稱加密 “慢” 的問題。
(4)Java 代碼示例(RSA 生成密鑰對 + 加密):
import javax.crypto.Cipher;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
public class RsaDemo {
public static void main(String[] args) throws Exception {
String algorithm = "RSA";
String plaintext = "要傳輸的AES密鑰:1234567890abcdef";
// 1. 生成RSA密鑰對(公鑰+私鑰)
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(algorithm);
keyPairGen.initialize(2048); // 密鑰長度2048位
KeyPair keyPair = keyPairGen.generateKeyPair();
PublicKey publicKey = keyPair.getPublic(); // 公鑰(可公開)
PrivateKey privateKey = keyPair.getPrivate(); // 私鑰(自己存)
// 2. 打印公鑰和私鑰(Base64編碼,方便查看)
System.out.println("公鑰(Base64):" + Base64.getEncoder().encodeToString(publicKey.getEncoded()));
System.out.println("私鑰(Base64):" + Base64.getEncoder().encodeToString(privateKey.getEncoded()));
// 3. 公鑰加密(加密少量數據,比如對稱密鑰)
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes());
String encrypted = Base64.getEncoder().encodeToString(encryptedBytes);
System.out.println("公鑰加密後:" + encrypted);
// 4. 私鑰解密
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encrypted));
String decrypted = new String(decryptedBytes);
System.out.println("私鑰解密後:" + decrypted); // 輸出:要傳輸的AES密鑰:1234567890abcdef
}
}
三、密碼學實戰指南
3.1 對稱 vs 非對稱:如何選擇?
|
特性
|
對稱加密
|
非對稱加密
|
|
速度
|
快(適合大數據)
|
慢(適合小數據)
|
|
密鑰管理
|
複雜(密鑰分發難)
|
簡單(公鑰可公開)
|
|
簽名功能
|
不支持
|
支持
|
|
典型應用
|
文件加密、數據庫加密
|
密鑰交換、數字簽名
|
最佳實踐: 結合兩者優勢
- 用非對稱加密安全傳輸對稱加密的密鑰
- 用對稱加密快速加密實際數據
3.2 密鑰長度建議
- RSA:至少2048位(1024位已不安全)
- ECC:256位(相當於RSA 3072位安全性)
- AES:128位(平衡安全與性能)
密鑰越長越安全?
不一定!AES-128 位已經足夠安全(破解需要的算力遠超全球總和),更長的密鑰(如 256 位)會增加性能消耗,沒必要。
3.3 Base64:不是加密的編碼
重要認知: Base64不是加密算法!它只是 “字節→字符串” 的編碼方式,目的是讓二進制數據能夠用文本形式安全傳輸,“避免傳輸亂碼”。
原理: 每3個字節(24位)轉換為4個6位的Base64字符
- 1 字節 = 8 位,3 字節 = 24 位;
- 把 24 位分成 4 組,每組 6 位;
- 6 位最大是 63(2^6-1),對應 64 個字符(A-Z、a-z、0-9、+、/);
- 如果不足 3 字節,缺 1 字節補 1 個 “=”,缺 2 字節補 2 個 “=”。
例子:編碼 “ab”(2 字節 = 16 位)
- 16 位→補 8 位 0→24 位,分成 4 組 6 位;
- 對應 Base64 字符:Y、W、I、=;
- 最終編碼結果:“YWI=”。
與Base58區別:
Base58(Base64 的 “簡化版”):Base58 去掉了容易混淆的字符(0、O、1、l)和特殊符號(+、/),適合手寫或肉眼識別,比如比特幣地址用 Base58 編碼。
3.4 數字簽名:網絡世界的"手寫簽名"
數字簽名用 “私鑰簽名,公鑰驗證”,解決 “信息被篡改” 和 “發件人抵賴” 的問題
作用:
- 身份認證:證明消息發送者的身份
- 完整性驗證:確保消息未被篡改
- 不可否認:發送者不能否認發送過的消息
實現過程:
- 對消息計算哈希值
- 用私鑰加密哈希值(這就是數字簽名)
- 接收方用公鑰解密並驗證哈希值
比如軟件發佈:
- 軟件開發者用私鑰對 “軟件哈希值” 簽名(生成簽名文件);
- 用户下載軟件後,算軟件的哈希值,並用開發者的公鑰驗證簽名;
- 如果驗證通過,説明軟件沒被篡改,且確實是開發者發佈的。
四、實際開發注意事項
4.1 字符串處理陷阱
加密解密後,一定要用**new String()**,別用toString()!
// ❌ 錯誤方式 - 會輸出哈希值而不是實際內容
byte[] data = "hello".getBytes();
System.out.println(data.toString()); // 輸出: [B@1540e19d
// ✅ 正確方式 - 使用明確的字符編碼
System.out.println(new String(data, "UTF-8")); // 輸出: hello
4.2 現代密碼學發展趨勢
- 後量子密碼學:抵抗量子計算機攻擊的新算法
- 同態加密:在加密狀態下直接進行計算
- 國密算法:中國自主研發的密碼算法體系(SM2, SM3, SM4)
五、總結:現代密碼學核心用法表
|
需求
|
推薦技術
|
關鍵點
|
|
密碼存儲、文件校驗
|
SHA-256(散列函數)
|
不可逆,固定長度
|
|
大量數據加密(文件、傳輸)
|
AES-CBC(對稱加密)+ Base64
|
密鑰 16 字節,用 CBC 模式 + PKCS5Padding
|
|
密鑰交換、數字簽名
|
RSA-2048/ECC-256(非對稱加密)
|
公鑰公開,私鑰保密
|
|
避免傳輸亂碼
|
Base64
|
不是加密,是編碼
|
密碼學就像網絡世界的"安全衞士",從簡單的字母替換髮展到今天覆雜的數學算法。它的核心不是 “搞懂複雜算法”,而是 “選對工具”—— 比如加密文件用 AES,存密碼用 SHA-256,傳輸密鑰用 RSA。
記住黃金法則:沒有絕對的安全,只有相對的安全。 持續學習、及時更新加密方案才是真正的安全保障。