密码学入门:从古典加密到现代网络安全
什么是密码学密码学是保护信息安全的科学它通过加密技术将可读的信息明文转换为不可读的形式密文只有授权方才能解密恢复原始内容。就像给信息上了一把数字锁只有拥有正确钥匙的人才能打开。一、古典密码学密码学的起源古典密码学主要靠 “替换” 和 “移位”原理简单适合手动计算常见于战争、书信保密。1.1 核心原理① 替换法 - 用固定规则替换原文中的字符示例bee b → w, e → p 密文wpp分类单表替换所有字符使用同一张替换表原始abcde 替换swtrp缺点容易被破解 —— 比如英文中 “e” 出现频率最高只要统计密文中哪个字符出现最多大概率就是 “e” 的替换。多表替换使用多张替换表按密钥轮换使用表1abcde → swtrp 表2abcde → chfhk 表3abcde → 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”MD532 位十六进制文件校验、密码存储已逐渐被淘汰易碰撞202cb962ac59075b964b07152d234b70SHA-1(Secure Hash Algorithm)40 位十六进制早期 Git 版本控制已淘汰40bd001563085fc35165329ea1ff5c5ecbdbbeefSHA-25664 位十六进制现在主流文件校验、区块链、密码存储a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3实战场景网站存密码不会存明文 “123456”而是存它的 SHA-256 哈希值登录时比对哈希值即使数据库泄露黑客也拿不到明文密码下载软件校验官方给出安装包的 SHA-256 值你下载后算一遍如果一致说明没被篡改。Java 代码示例计算 MD5importjava.security.MessageDigest;public class HashDemo{public static void main(String[]args)throws Exception{String input123;// 明文 //1. 获取MD5算法实例 MessageDigest mdMessageDigest.getInstance(MD5);//2. 计算哈希值字节数组 byte[]hashBytesmd.digest(input.getBytes());//3. 转成16进制字符串方便查看 StringBuilder sbnew StringBuilder();for(byte b:hashBytes){sb.append(String.format(%02x, b));// %02x表示补0成2位十六进制}System.out.println(MD5哈希值 sb.toString());// 输出202cb962ac59075b964b07152d234b70}}2.2 对称加密同一把钥匙加密和解密用同一把密钥就像你家的门钥匙既能锁门也能开门。特点是 “快”适合加密大量数据。1常见算法对比算法密钥长度特点用途DES8 字节64 位含 1 位校验早期算法安全性低已淘汰旧系统兼容3DES24 字节3 个 DES 密钥对 DES 三次加密安全性提高但速度慢旧金融系统AES16/192/256 字节推荐 16 字节现在主流速度快、安全性高手机支付、文件加密、HTTPS 数据传输技术分类流加密逐位加密如RC4123456789 → 先加密1再加密2再加密3…块加密分组加密如AES12345678 → 分成[1234]和[5678]分别加密特点✅ 加密速度快✅ 适合大数据量加密❌ 密钥分发和管理困难❌ 无法实现数字签名2关键概念加密模式 填充模式对称加密按 “块” 处理数据比如 AES 每次处理 16 字节需要解决 “数据不够块长” 和 “相同明文出相同密文” 的问题① 加密模式决定怎么处理多块数据模式特点优点缺点ECB每块独立加密相同明文块出相同密文块并行处理速度快不安全容易被破解规律CBC每块先和前一块密文 “异或”再加密相同明文出不同密文安全串行处理速度稍慢需要初始向量 IVECBElectronic Codebook电子密码本CBCCipher Block Chaining密码块链接例子加密 “abcabc”AES-16 字节ECB vs CBCECB两个 “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 是编码不是加密目的是 “方便传输”不是 “保密”4Java 代码示例AES-CBC 加密importjavax.crypto.Cipher;importjavax.crypto.spec.IvParameterSpec;importjavax.crypto.spec.SecretKeySpec;importjava.util.Base64;public class AesDemo{// AES密钥16字节、初始向量IV16字节CBC模式必须 private static final String KEY1234567890abcdef;private static final String IVabcdef1234567890;// 加密明文→密文Base64字符串 public static String encrypt(String plaintext)throws Exception{//1. 生成密钥和IV SecretKeySpec keySpecnew SecretKeySpec(KEY.getBytes(),AES);IvParameterSpec ivSpecnew IvParameterSpec(IV.getBytes());//2. 初始化CipherCBC模式PKCS5Padding Cipher cipherCipher.getInstance(AES/CBC/PKCS5Padding);cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);//3. 加密→Base64编码 byte[]cipherBytescipher.doFinal(plaintext.getBytes());returnBase64.getEncoder().encodeToString(cipherBytes);}// 解密密文Base64字符串→明文 public static String decrypt(String ciphertext)throws Exception{SecretKeySpec keySpecnew SecretKeySpec(KEY.getBytes(),AES);IvParameterSpec ivSpecnew IvParameterSpec(IV.getBytes());Cipher cipherCipher.getInstance(AES/CBC/PKCS5Padding);cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);//4. Base64解码→解密 byte[]plainBytescipher.doFinal(Base64.getDecoder().decode(ciphertext));returnnew String(plainBytes);}public static void main(String[]args)throws Exception{String plaintext我是秘密消息;// 加密 String ciphertextencrypt(plaintext);System.out.println(加密后Base64 ciphertext);// 比如xY...长字符串 // 解密 String decrypteddecrypt(ciphertext);System.out.println(解密后 decrypted);// 输出我是秘密消息}}3. 非对称加密“公钥加密私钥解密”用一对密钥公钥 私钥公钥可以公开像地址一样分享给别人私钥自己保存绝对不能泄露。特点是 “安全”但速度慢适合加密少量数据比如密钥。1核心规则公钥加密的密文只有对应的私钥能解密私钥加密的密文叫 “数字签名”只有对应的公钥能解密公钥由私钥生成无法从公钥反推私钥。2常见算法对比算法密钥长度特点用途RSA1024/2048/4096 位推荐 2048 位兼容性好应用广数字签名、密钥交换HTTPSECC160/256 位相同安全级下密钥更短、速度更快移动端加密、区块链比特币用 ECCDSA1024 位只用于数字签名不能加密数据身份验证3实战场景HTTPS 的 “密钥交换”**HTTPS 为什么安全因为它结合了 “对称 非对称” 加密浏览器向服务器要 “公钥”浏览器用公钥加密 “对称密钥”比如 AES 密钥发给服务器服务器用私钥解密拿到对称密钥后续数据传输都用对称密钥加密快。—— 既解决了对称加密 “密钥难传输” 的问题又解决了非对称加密 “慢” 的问题。4Java 代码示例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 algorithmRSA;String plaintext要传输的AES密钥1234567890abcdef;//1. 生成RSA密钥对公钥私钥 KeyPairGenerator keyPairGenKeyPairGenerator.getInstance(algorithm);keyPairGen.initialize(2048);// 密钥长度2048位 KeyPair keyPairkeyPairGen.generateKeyPair();PublicKey publicKeykeyPair.getPublic();// 公钥可公开 PrivateKey privateKeykeyPair.getPrivate();// 私钥自己存 //2. 打印公钥和私钥Base64编码方便查看 System.out.println(公钥Base64 Base64.getEncoder().encodeToString(publicKey.getEncoded()));System.out.println(私钥Base64 Base64.getEncoder().encodeToString(privateKey.getEncoded()));//3. 公钥加密加密少量数据比如对称密钥 Cipher cipherCipher.getInstance(algorithm);cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[]encryptedBytescipher.doFinal(plaintext.getBytes());String encryptedBase64.getEncoder().encodeToString(encryptedBytes);System.out.println(公钥加密后 encrypted);//4. 私钥解密 cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[]decryptedBytescipher.doFinal(Base64.getDecoder().decode(encrypted));String decryptednew String(decryptedBytes);System.out.println(私钥解密后 decrypted);// 输出要传输的AES密钥1234567890abcdef}}三、密码学实战指南3.1 对称 vs 非对称如何选择特性对称加密非对称加密速度快适合大数据慢适合小数据密钥管理复杂密钥分发难简单公钥可公开签名功能不支持支持典型应用文件加密、数据库加密密钥交换、数字签名最佳实践 结合两者优势用非对称加密安全传输对称加密的密钥用对称加密快速加密实际数据3.2 密钥长度建议RSA至少2048位1024位已不安全ECC256位相当于RSA 3072位安全性AES128位平衡安全与性能密钥越长越安全不一定AES-128 位已经足够安全破解需要的算力远超全球总和更长的密钥如 256 位会增加性能消耗没必要。3.3 Base64不是加密的编码重要认知 Base64不是加密算法它只是 “字节→字符串” 的编码方式目的是让二进制数据能够用文本形式安全传输“避免传输乱码”。原理 每3个字节24位转换为4个6位的Base64字符1 字节 8 位3 字节 24 位把 24 位分成 4 组每组 6 位6 位最大是 632^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区别Base58Base64 的 “简化版”Base58 去掉了容易混淆的字符0、O、1、l和特殊符号、/适合手写或肉眼识别比如比特币地址用 Base58 编码。3.4 数字签名网络世界的手写签名数字签名用 “私钥签名公钥验证”解决 “信息被篡改” 和 “发件人抵赖” 的问题作用身份认证证明消息发送者的身份完整性验证确保消息未被篡改不可否认发送者不能否认发送过的消息实现过程对消息计算哈希值用私钥加密哈希值这就是数字签名接收方用公钥解密并验证哈希值比如软件发布软件开发者用私钥对 “软件哈希值” 签名生成签名文件用户下载软件后算软件的哈希值并用开发者的公钥验证签名如果验证通过说明软件没被篡改且确实是开发者发布的。四、实际开发注意事项4.1 字符串处理陷阱加密解密后一定要用**new String()**别用toString()// ❌ 错误方式 - 会输出哈希值而不是实际内容 byte[]datahello.getBytes();System.out.println(data.toString());// 输出:[B1540e19d // ✅ 正确方式 - 使用明确的字符编码 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。记住黄金法则没有绝对的安全只有相对的安全。 持续学习、及时更新加密方案才是真正的安全保障。