什么是密码学?
密码学是保护信息安全的科学,它通过加密技术将可读的信息(明文)转换为不可读的形式(密文),只有授权方才能解密恢复原始内容。就像给信息上了一把"数字锁",只有拥有正确"钥匙"的人才能打开。
一、古典密码学:密码学的起源
古典密码学主要靠 “替换” 和 “移位”,原理简单,适合手动计算,常见于战争、书信保密。
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):
importjava.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) |
- ECB:Electronic Codebook,电子密码本
- CBC:Cipher Block Chaining,密码块链接
例子:加密 “abcabc”(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 加密):
importjavax.crypto.Cipher;importjavax.crypto.spec.IvParameterSpec;importjavax.crypto.spec.SecretKeySpec;importjava.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());returnBase64.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));returnnew 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)常见算法对比:
| 算法 | 密钥长度 | 特点 | 用途 |
|---|---|---|---|
RSA | 1024/2048/4096 位(推荐 2048 位) | 兼容性好,应用广 | 数字签名、密钥交换(HTTPS) |
ECC | 160/256 位 | 相同安全级下,密钥更短、速度更快 | 移动端加密、区块链(比特币用 ECC) |
DSA | 1024 位 | 只用于数字签名,不能加密数据 | 身份验证 |
(3)实战场景:HTTPS 的 “密钥交换”**
HTTPS 为什么安全?
因为它结合了 “对称 + 非对称” 加密:
- 浏览器向服务器要 “公钥”;
- 浏览器用公钥加密 “对称密钥”(比如 AES 密钥),发给服务器;
- 服务器用私钥解密,拿到对称密钥;
- 后续数据传输,都用对称密钥加密(快)。
—— 既解决了对称加密 “密钥难传输” 的问题,又解决了非对称加密 “慢” 的问题。
(4)Java 代码示例(RSA 生成密钥对 + 加密):
importjavax.crypto.Cipher;importjava.security.KeyPair;importjava.security.KeyPairGenerator;importjava.security.PrivateKey;importjava.security.PublicKey;importjava.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"));// 输出: hello4.2 现代密码学发展趋势
- 后量子密码学:抵抗量子计算机攻击的新算法
- 同态加密:在加密状态下直接进行计算
- 国密算法:中国自主研发的密码算法体系(SM2, SM3, SM4)
五、总结:现代密码学核心用法表
| 需求 | 推荐技术 | 关键点 |
|---|---|---|
| 密码存储、文件校验 | SHA-256(散列函数) | 不可逆,固定长度 |
| 大量数据加密(文件、传输) | AES-CBC(对称加密)+ Base64 | 密钥 16 字节,用 CBC 模式 + PKCS5Padding |
| 密钥交换、数字签名 | RSA-2048/ECC-256(非对称加密) | 公钥公开,私钥保密 |
| 避免传输乱码 | Base64 | 不是加密,是编码 |
密码学就像网络世界的"安全卫士",从简单的字母替换发展到今天复杂的数学算法。它的核心不是 “搞懂复杂算法”,而是 “选对工具”—— 比如加密文件用 AES,存密码用 SHA-256,传输密钥用 RSA。
记住黄金法则:没有绝对的安全,只有相对的安全。 持续学习、及时更新加密方案才是真正的安全保障。