密码学完全指南:从基础到实战

密码学完全指南:从基础到实战


目录

  1. 密码学发展历程
  2. 密码学基础概念
  3. 对称加密:AES
  4. 非对称加密:RSA
  5. 椭圆曲线密码学:ECC
  6. [哈希算法:SHA 家族](#哈希算法:SHA 家族)
  7. 传输层安全:TLS
  8. 公钥基础设施:PKI
  9. 数字签名
  10. 混合加密体系
  11. 后量子密码学
  12. 密码学安全最佳实践
  13. 算法对比速查表
  14. 参考资源

1. 密码学发展历程

1.1 古典密码学时代(公元前 ~ 19世纪)

时期 事件 说明
约公元前1900年 古埃及象形文字替换 已知最早的密码术实践
公元前5世纪 斯巴达密码棒(Scytale) 最早的转置密码工具
公元前50年 凯撒密码 字母表偏移替换,Julius Caesar 用于军事通信
9世纪 Al-Kindi 的频率分析 阿拉伯学者提出破解替换密码的系统方法
15世纪 Vigenère 密码 多表替换密码,被誉为"不可破译的密码"(后被 Kasiski 破解)
1883年 Kerckhoffs 原则 "密码系统的安全性应仅依赖于密钥的保密性"

1.2 机电密码时代(20世纪前半叶)

时期 事件 说明
1918年 Enigma 机器发明 德国 Arthur Scherbius 发明转子密码机
1932-1939年 波兰数学家破解 Enigma Rejewski、Różycki 和 Zygalski 的开创性工作
1939-1945年 布莱切利庄园 Alan Turing 等人利用 Bombe 机器系统性破解 Enigma
1945年 Shannon 发表《保密系统的通信理论》 奠定现代密码学的数学基础,引入信息论

1.3 现代密码学时代(1970年代至今)

年份 里程碑 说明
1973 IBM 提出 Lucifer 算法 对称分组密码的先驱
1976 DES(数据加密标准)发布 首个被广泛采用的标准化加密算法,密钥长度 56 位
1976 Diffie-Hellman 密钥交换 首次提出公钥密码学概念,Whitfield Diffie 和 Martin Hellman
1977 RSA 算法发明 Rivest、Shamir、Adleman 提出基于大数因式分解的非对称加密
1985 椭圆曲线密码学(ECC) Neal Koblitz 和 Victor Miller 独立提出
1991 PGP(Pretty Good Privacy) Phil Zimmermann 发布,使加密走向大众
1994 SSL 1.0/2.0 Netscape 开发,用于保护 Web 通信
1995 SHA-1 发布 NIST 标准化的安全哈希算法(现已不推荐使用)
1999 TLS 1.0(RFC 2246) 替代 SSL,成为互联网安全通信标准
2001 AES 标准发布 Rijndael 算法胜出 NIST 竞赛,取代 DES
2001 SHA-2 家族发布 包含 SHA-224/256/384/512
2006 TLS 1.1 发布 增加对 CBC 攻击的防护
2008 TLS 1.2(RFC 5246) 支持 AEAD 密码套件和可协商的哈希/签名算法
2012 SHA-3(Keccak)标准化 基于海绵结构的全新哈希算法家族
2015 Let's Encrypt 成立 免费自动化证书颁发,推动 HTTPS 普及
2018 TLS 1.3(RFC 8446) 简化握手、移除不安全算法、强制前向保密
2022 NIST 后量子密码标准候选 CRYSTALS-Kyber、CRYSTALS-Dilithium、FALCON、SPHINCS+
2024 NIST 正式发布 PQC 标准 FIPS 203 (ML-KEM)、FIPS 204 (ML-DSA)、FIPS 205 (SLH-DSA)

2. 密码学基础概念

2.1 三大支柱

  • 机密性(Confidentiality):确保数据仅对授权方可见,通过加密实现
  • 完整性(Integrity):确保数据未被篡改,通过哈希/MAC 实现
  • 认证性(Authentication):确认通信方的身份,通过数字签名/证书实现

附加目标还包括不可否认性(Non-repudiation)------发送方无法否认其发送的消息。

2.2 对称加密 vs 非对称加密

特性 对称加密 非对称加密
密钥数量 1 个共享密钥 公钥 + 私钥 对
速度 快(适合大数据) 慢(适合小数据/密钥交换)
密钥分发 困难(需安全通道) 简便(公钥可公开)
代表算法 AES、ChaCha20、3DES RSA、ECC、ElGamal
典型用途 数据加密、磁盘加密 密钥交换、数字签名、身份认证

2.3 实际系统中的混合模式

现代安全系统几乎都采用混合加密模式:非对称加密(RSA 或 ECC)用于安全交换会话密钥,对称加密(AES)用于高速加密实际数据。TLS、HTTPS、VPN 等协议均采用此方式。


3. 对称加密:AES

3.1 概述

AES(Advanced Encryption Standard,高级加密标准)由比利时密码学家 Joan Daemen 和 Vincent Rijmen 设计(原名 Rijndael),2001 年被 NIST 选定为联邦信息处理标准(FIPS 197),替代老旧的 DES。

核心参数:

参数
分组大小 128 位(16 字节)
密钥长度 128 / 192 / 256 位
加密轮数 10 / 12 / 14 轮(对应不同密钥长度)
结构 替代-置换网络(SPN)

3.2 AES 工作原理

每一轮包含四个操作:

  1. SubBytes(字节替换):通过 S-Box 非线性替换每个字节
  2. ShiftRows(行移位):对状态矩阵的每行循环左移不同偏移量
  3. MixColumns(列混合):对每列进行矩阵乘法变换(最后一轮省略)
  4. AddRoundKey(轮密钥加):将当前状态与该轮子密钥进行 XOR

3.3 AES 工作模式

模式 全称 特点 推荐度
ECB Electronic Codebook 相同明文产生相同密文,不安全 ❌ 不推荐
CBC Cipher Block Chaining 需要 IV,支持并行解密 ⚠️ 可用但有 Padding Oracle 风险
CTR Counter 将分组密码变为流密码,支持并行 ✅ 推荐
GCM Galois/Counter Mode CTR + GMAC 认证,AEAD 模式 ✅✅ 强烈推荐
CCM Counter with CBC-MAC 类似 GCM,用于资源受限环境 ✅ 推荐

最佳实践:优先使用 AES-256-GCM,它同时提供加密和完整性认证(AEAD)。

3.4 Java 实现:AES-256-GCM

java 复制代码
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

public class AesGcmExample {

    private static final int GCM_IV_LENGTH = 12;   // 推荐 12 字节
    private static final int GCM_TAG_LENGTH = 128;  // 128 位认证标签

    // 生成 AES-256 密钥
    public static SecretKey generateKey() throws Exception {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(256, new SecureRandom());
        return keyGen.generateKey();
    }

    // 加密
    public static byte[] encrypt(byte[] plaintext, SecretKey key, byte[] iv,
                                  byte[] aad) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, spec);
        if (aad != null) {
            cipher.updateAAD(aad);  // 附加认证数据(明文传输但受完整性保护)
        }
        return cipher.doFinal(plaintext);
    }

    // 解密
    public static byte[] decrypt(byte[] ciphertext, SecretKey key, byte[] iv,
                                  byte[] aad) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.DECRYPT_MODE, key, spec);
        if (aad != null) {
            cipher.updateAAD(aad);
        }
        return cipher.doFinal(ciphertext);
    }

    public static void main(String[] args) throws Exception {
        // 1. 生成密钥
        SecretKey key = generateKey();
        System.out.println("AES Key (Base64): "
            + Base64.getEncoder().encodeToString(key.getEncoded()));

        // 2. 生成随机 IV(每次加密必须不同!)
        byte[] iv = new byte[GCM_IV_LENGTH];
        new SecureRandom().nextBytes(iv);

        // 3. 附加认证数据(可选,用于验证上下文信息)
        byte[] aad = "metadata:user=alice,action=transfer".getBytes();

        // 4. 加密
        String message = "这是一条需要加密的敏感消息。Hello, Cryptography!";
        byte[] ciphertext = encrypt(message.getBytes("UTF-8"), key, iv, aad);
        System.out.println("密文 (Base64): "
            + Base64.getEncoder().encodeToString(ciphertext));

        // 5. 解密
        byte[] decrypted = decrypt(ciphertext, key, iv, aad);
        System.out.println("解密结果: " + new String(decrypted, "UTF-8"));
    }
}

3.5 Python 实现:AES-256-GCM

python 复制代码
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
import base64

def aes_gcm_demo():
    # 1. 生成 256 位密钥
    key = AESGCM.generate_key(bit_length=256)
    print(f"AES Key (Base64): {base64.b64encode(key).decode()}")

    # 2. 创建 AESGCM 实例
    aesgcm = AESGCM(key)

    # 3. 生成随机 nonce(12 字节,每次加密必须唯一)
    nonce = os.urandom(12)

    # 4. 附加认证数据(可选)
    aad = b"metadata:user=alice,action=transfer"

    # 5. 加密
    message = "这是一条需要加密的敏感消息。Hello, Cryptography!"
    plaintext = message.encode("utf-8")
    ciphertext = aesgcm.encrypt(nonce, plaintext, aad)
    print(f"密文 (Base64): {base64.b64encode(ciphertext).decode()}")

    # 6. 解密
    decrypted = aesgcm.decrypt(nonce, ciphertext, aad)
    print(f"解密结果: {decrypted.decode('utf-8')}")

    # 7. 篡改演示:修改密文后解密将失败
    try:
        tampered = bytearray(ciphertext)
        tampered[0] ^= 0xFF
        aesgcm.decrypt(nonce, bytes(tampered), aad)
    except Exception as e:
        print(f"篡改检测成功!错误: {e}")

if __name__ == "__main__":
    aes_gcm_demo()

3.6 基于密码的密钥派生(PBKDF2 + AES)

在实际应用中,用户提供的是密码而非密钥,需要通过密钥派生函数将密码转换为加密密钥。

Python 示例:

python 复制代码
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os, base64

def password_based_encryption(password: str, plaintext: str):
    # 从密码派生密钥
    salt = os.urandom(16)
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=32,            # 256 位密钥
        salt=salt,
        iterations=600_000,   # OWASP 推荐 >= 600,000 次迭代
    )
    key = kdf.derive(password.encode())

    # AES-GCM 加密
    nonce = os.urandom(12)
    aesgcm = AESGCM(key)
    ciphertext = aesgcm.encrypt(nonce, plaintext.encode(), None)

    # 存储时需保存 salt + nonce + ciphertext
    stored = salt + nonce + ciphertext
    print(f"加密数据 (Base64): {base64.b64encode(stored).decode()}")
    return stored

def password_based_decryption(password: str, stored: bytes):
    # 解析各部分
    salt = stored[:16]
    nonce = stored[16:28]
    ciphertext = stored[28:]

    # 重新派生密钥
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(), length=32,
        salt=salt, iterations=600_000,
    )
    key = kdf.derive(password.encode())

    # 解密
    aesgcm = AESGCM(key)
    plaintext = aesgcm.decrypt(nonce, ciphertext, None)
    return plaintext.decode()

# 使用示例
stored = password_based_encryption("MyStr0ngP@ssw0rd!", "机密文件内容")
result = password_based_decryption("MyStr0ngP@ssw0rd!", stored)
print(f"解密结果: {result}")

4. 非对称加密:RSA

4.1 概述

RSA(Rivest-Shamir-Adleman)于 1977 年由 MIT 的三位科学家提出,是第一个实用的公钥加密算法。其安全性基于大整数因式分解问题的计算困难性。

核心参数:

参数 推荐值
密钥长度 ≥ 2048 位(推荐 3072 或 4096 位)
填充方案 OAEP(加密)/ PSS(签名)
哈希算法 SHA-256 或 SHA-384

4.2 RSA 数学原理

  1. 选择两个大素数 p 和 q,计算 n = p × q
  2. 计算欧拉函数 φ(n) = (p-1)(q-1)
  3. 选择公钥指数 e(常用 65537),满足 gcd(e, φ(n)) = 1
  4. 计算私钥指数 d,满足 e × d ≡ 1 (mod φ(n))
  5. 公钥 = (n, e),私钥 = (n, d)
  6. 加密:C = M^e mod n;解密:M = C^d mod n

4.3 Java 实现:RSA 加密/解密 + 数字签名

java 复制代码
import java.security.*;
import java.security.spec.*;
import javax.crypto.Cipher;
import java.util.Base64;

public class RsaExample {

    // ========== RSA 密钥对生成 ==========
    public static KeyPair generateKeyPair(int keySize) throws Exception {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(keySize, new SecureRandom());
        return kpg.generateKeyPair();
    }

    // ========== RSA-OAEP 加密 ==========
    public static byte[] encrypt(byte[] plaintext, PublicKey publicKey)
            throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(plaintext);
    }

    // ========== RSA-OAEP 解密 ==========
    public static byte[] decrypt(byte[] ciphertext, PrivateKey privateKey)
            throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(ciphertext);
    }

    // ========== RSA-PSS 签名 ==========
    public static byte[] sign(byte[] data, PrivateKey privateKey)
            throws Exception {
        Signature sig = Signature.getInstance("RSASSA-PSS");
        PSSParameterSpec pssSpec = new PSSParameterSpec(
            "SHA-256", "MGF1",
            MGF1ParameterSpec.SHA256, 32, 1
        );
        sig.setParameter(pssSpec);
        sig.initSign(privateKey);
        sig.update(data);
        return sig.sign();
    }

    // ========== RSA-PSS 验签 ==========
    public static boolean verify(byte[] data, byte[] signature,
                                  PublicKey publicKey) throws Exception {
        Signature sig = Signature.getInstance("RSASSA-PSS");
        PSSParameterSpec pssSpec = new PSSParameterSpec(
            "SHA-256", "MGF1",
            MGF1ParameterSpec.SHA256, 32, 1
        );
        sig.setParameter(pssSpec);
        sig.initVerify(publicKey);
        sig.update(data);
        return sig.verify(signature);
    }

    public static void main(String[] args) throws Exception {
        // 生成 3072 位密钥对
        KeyPair kp = generateKeyPair(3072);
        System.out.println("RSA 密钥对已生成 (3072 位)");

        // --- 加密/解密演示 ---
        String message = "RSA 加密消息:转账 100 万到账户 A";
        byte[] ciphertext = encrypt(message.getBytes("UTF-8"), kp.getPublic());
        System.out.println("密文 (Base64): "
            + Base64.getEncoder().encodeToString(ciphertext));

        byte[] decrypted = decrypt(ciphertext, kp.getPrivate());
        System.out.println("解密: " + new String(decrypted, "UTF-8"));

        // --- 签名/验签演示 ---
        byte[] data = "这是需要签名的合同文件内容".getBytes("UTF-8");
        byte[] signature = sign(data, kp.getPrivate());
        System.out.println("签名 (Base64): "
            + Base64.getEncoder().encodeToString(signature));

        boolean valid = verify(data, signature, kp.getPublic());
        System.out.println("签名验证结果: " + valid);

        // 篡改数据后验签
        byte[] tampered = "这是被篡改的合同文件内容".getBytes("UTF-8");
        boolean tamperedValid = verify(tampered, signature, kp.getPublic());
        System.out.println("篡改数据验证结果: " + tamperedValid);
    }
}

4.4 Python 实现:RSA 完整示例

python 复制代码
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
import base64

def rsa_demo():
    # 1. 生成密钥对
    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=3072,
    )
    public_key = private_key.public_key()

    # 2. 导出 PEM 格式密钥(用于存储/传输)
    pem_private = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.BestAvailableEncryption(b"my-password"),
    )
    pem_public = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo,
    )
    print("公钥 PEM:")
    print(pem_public.decode())

    # 3. RSA-OAEP 加密
    message = "RSA 加密消息:转账 100 万到账户 A"
    ciphertext = public_key.encrypt(
        message.encode(),
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None,
        ),
    )
    print(f"密文 (Base64): {base64.b64encode(ciphertext).decode()}")

    # 4. 解密
    plaintext = private_key.decrypt(
        ciphertext,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None,
        ),
    )
    print(f"解密结果: {plaintext.decode()}")

    # 5. RSA-PSS 数字签名
    data = b"contract: payment of $1,000,000 to Account A"
    signature = private_key.sign(
        data,
        padding.PSS(
            mgf=padding.MGF1(hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH,
        ),
        hashes.SHA256(),
    )
    print(f"签名 (Base64): {base64.b64encode(signature).decode()}")

    # 6. 验签
    try:
        public_key.verify(
            signature, data,
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH,
            ),
            hashes.SHA256(),
        )
        print("✅ 签名验证通过")
    except Exception:
        print("❌ 签名验证失败")

if __name__ == "__main__":
    rsa_demo()

4.5 RSA 安全注意事项

  • 永远不要使用 PKCS#1 v1.5 填充进行加密,应使用 OAEP
  • 签名应使用 PSS 填充,而非 PKCS#1 v1.5
  • 密钥长度至少 2048 位,推荐 3072 位或以上
  • RSA 不适合加密大量数据,实际中用于加密对称密钥(密钥封装)
  • RSA 的加密速度远慢于 AES,解密更慢

5. 椭圆曲线密码学:ECC

5.1 概述

ECC(Elliptic Curve Cryptography)于 1985 年由 Neal Koblitz 和 Victor Miller 独立提出。其安全性基于椭圆曲线离散对数问题(ECDLP)。ECC 的核心优势在于用更短的密钥提供与 RSA 相当的安全性。

等效安全强度对比:

对称密钥 (AES) RSA 密钥 ECC 密钥 备注
128 位 3,072 位 256 位 当前推荐最低安全级别
192 位 7,680 位 384 位 高安全需求
256 位 15,360 位 521 位 最高安全级别

5.2 常用椭圆曲线

曲线名称 密钥长度 标准 说明
P-256 (secp256r1) 256 位 NIST 最广泛使用,TLS 默认
P-384 (secp384r1) 384 位 NIST 高安全场景
P-521 (secp521r1) 521 位 NIST 最高安全级别
Curve25519 255 位 Bernstein 高性能,用于 X25519 密钥交换
Ed25519 255 位 Bernstein 用于 EdDSA 签名,高性能
secp256k1 256 位 SEC Bitcoin 和以太坊使用

5.3 ECC 的三种核心应用

  1. ECDH(椭圆曲线 Diffie-Hellman):密钥协商
  2. ECDSA(椭圆曲线数字签名算法):数字签名
  3. ECIES(椭圆曲线集成加密方案):混合加密

5.4 Java 实现:ECDH 密钥交换 + ECDSA 签名

java 复制代码
import java.security.*;
import java.security.spec.*;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class EccExample {

    // ========== ECDH 密钥交换 ==========
    public static void ecdhDemo() throws Exception {
        System.out.println("=== ECDH 密钥交换 ===");

        // Alice 生成密钥对
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
        kpg.initialize(new ECGenParameterSpec("secp256r1"));
        KeyPair aliceKP = kpg.generateKeyPair();

        // Bob 生成密钥对
        KeyPair bobKP = kpg.generateKeyPair();

        // Alice 计算共享密钥
        KeyAgreement aliceKA = KeyAgreement.getInstance("ECDH");
        aliceKA.init(aliceKP.getPrivate());
        aliceKA.doPhase(bobKP.getPublic(), true);
        byte[] aliceShared = aliceKA.generateSecret();

        // Bob 计算共享密钥
        KeyAgreement bobKA = KeyAgreement.getInstance("ECDH");
        bobKA.init(bobKP.getPrivate());
        bobKA.doPhase(aliceKP.getPublic(), true);
        byte[] bobShared = bobKA.generateSecret();

        // 验证双方密钥一致
        System.out.println("Alice 共享密钥: "
            + Base64.getEncoder().encodeToString(aliceShared));
        System.out.println("Bob   共享密钥: "
            + Base64.getEncoder().encodeToString(bobShared));
        System.out.println("密钥一致: "
            + MessageDigest.isEqual(aliceShared, bobShared));

        // 从共享密钥派生 AES 密钥(使用 HKDF 更佳,此处简化为截取)
        SecretKey aesKey = new SecretKeySpec(aliceShared, 0, 32, "AES");
        System.out.println("派生 AES-256 密钥: "
            + Base64.getEncoder().encodeToString(aesKey.getEncoded()));
    }

    // ========== ECDSA 数字签名 ==========
    public static void ecdsaDemo() throws Exception {
        System.out.println("\n=== ECDSA 数字签名 ===");

        KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
        kpg.initialize(new ECGenParameterSpec("secp256r1"));
        KeyPair kp = kpg.generateKeyPair();

        byte[] data = "需要签名的交易数据: Alice -> Bob 100 BTC".getBytes("UTF-8");

        // 签名
        Signature sig = Signature.getInstance("SHA256withECDSA");
        sig.initSign(kp.getPrivate());
        sig.update(data);
        byte[] signature = sig.sign();
        System.out.println("ECDSA 签名 (Base64): "
            + Base64.getEncoder().encodeToString(signature));

        // 验签
        sig.initVerify(kp.getPublic());
        sig.update(data);
        boolean valid = sig.verify(signature);
        System.out.println("签名验证: " + valid);
    }

    public static void main(String[] args) throws Exception {
        ecdhDemo();
        ecdsaDemo();
    }
}

5.5 Python 实现:ECDH + ECDSA + X25519/Ed25519

python 复制代码
from cryptography.hazmat.primitives.asymmetric import ec, x25519, ed25519
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
import base64

def ecdh_demo():
    """ECDH 密钥交换(P-256)"""
    print("=== ECDH 密钥交换 (P-256) ===")

    # Alice 和 Bob 分别生成密钥对
    alice_private = ec.generate_private_key(ec.SECP256R1())
    bob_private = ec.generate_private_key(ec.SECP256R1())

    # 计算共享密钥
    alice_shared = alice_private.exchange(ec.ECDH(), bob_private.public_key())
    bob_shared = bob_private.exchange(ec.ECDH(), alice_private.public_key())

    print(f"共享密钥一致: {alice_shared == bob_shared}")

    # 通过 HKDF 派生 AES 密钥(正确做法)
    derived_key = HKDF(
        algorithm=hashes.SHA256(),
        length=32,
        salt=None,
        info=b"ecdh-aes-key",
    ).derive(alice_shared)
    print(f"派生 AES-256 密钥: {base64.b64encode(derived_key).decode()}")

def ecdsa_demo():
    """ECDSA 数字签名"""
    print("\n=== ECDSA 数字签名 (P-256) ===")

    private_key = ec.generate_private_key(ec.SECP256R1())
    data = b"Transaction: Alice -> Bob 100 BTC"

    # 签名
    signature = private_key.sign(data, ec.ECDSA(hashes.SHA256()))
    print(f"签名 (Base64): {base64.b64encode(signature).decode()}")

    # 验签
    try:
        private_key.public_key().verify(signature, data, ec.ECDSA(hashes.SHA256()))
        print("✅ 签名验证通过")
    except Exception:
        print("❌ 签名验证失败")

def x25519_demo():
    """X25519 密钥交换(现代高性能曲线)"""
    print("\n=== X25519 密钥交换 ===")

    alice_private = x25519.X25519PrivateKey.generate()
    bob_private = x25519.X25519PrivateKey.generate()

    alice_shared = alice_private.exchange(bob_private.public_key())
    bob_shared = bob_private.exchange(alice_private.public_key())

    print(f"共享密钥一致: {alice_shared == bob_shared}")

    derived = HKDF(
        algorithm=hashes.SHA256(), length=32,
        salt=None, info=b"x25519-session-key",
    ).derive(alice_shared)
    print(f"派生会话密钥: {base64.b64encode(derived).decode()}")

def ed25519_demo():
    """Ed25519 签名(现代高性能签名)"""
    print("\n=== Ed25519 数字签名 ===")

    private_key = ed25519.Ed25519PrivateKey.generate()
    data = b"Critical system configuration update v2.1"

    signature = private_key.sign(data)
    print(f"签名 (Base64): {base64.b64encode(signature).decode()}")
    print(f"签名长度: {len(signature)} 字节 (固定 64 字节)")

    try:
        private_key.public_key().verify(signature, data)
        print("✅ Ed25519 签名验证通过")
    except Exception:
        print("❌ 验证失败")

if __name__ == "__main__":
    ecdh_demo()
    ecdsa_demo()
    x25519_demo()
    ed25519_demo()

5.6 ECC vs RSA 性能对比

操作 RSA-3072 ECC-256 差距
密钥生成 ~600ms ~10ms ECC 快 ~60x
签名 ~5ms ~2ms ECC 快 ~2.5x
验签 ~0.3ms ~3ms RSA 验签更快
密钥大小 3072 位 256 位 ECC 小 ~12x
签名大小 384 字节 64 字节 ECC 小 ~6x

6. 哈希算法:SHA 家族

6.1 哈希函数的核心性质

  1. 确定性:相同输入永远产生相同输出
  2. 高效性:计算速度快
  3. 雪崩效应:输入微小变化导致输出巨大变化
  4. 抗原像性:给定哈希值,无法反推出原始输入
  5. 抗第二原像性:给定一个输入,无法找到产生相同哈希值的另一个输入
  6. 抗碰撞性:无法找到两个不同输入产生相同哈希值

6.2 SHA 家族演进

算法 输出长度 状态 说明
MD5 128 位 ❌ 已破解 2004 年发现实际碰撞
SHA-1 160 位 ❌ 已破解 2017 年 Google 证明碰撞(SHAttered)
SHA-224 224 位 ✅ 安全 SHA-2 家族成员
SHA-256 256 位 ✅✅ 推荐 最广泛使用的安全哈希
SHA-384 384 位 ✅✅ 推荐 高安全需求
SHA-512 512 位 ✅✅ 推荐 在 64 位系统上性能优于 SHA-256
SHA-3-256 256 位 ✅✅ 推荐 基于 Keccak 海绵结构,与 SHA-2 设计完全不同
SHA-3-512 512 位 ✅✅ 推荐 最高安全级别
BLAKE2 可变 ✅ 推荐 比 SHA-3 更快,广泛用于密码哈希
BLAKE3 256 位 ✅ 推荐 极高性能,支持并行计算

6.3 SHA-2 vs SHA-3 架构差异

特性 SHA-2 SHA-3
结构 Merkle-Damgård 海绵结构(Sponge)
设计者 NSA Guido Bertoni 等(Keccak 团队)
标准化年份 2001 2015(FIPS 202)
长度扩展攻击 易受影响 天然免疫
硬件效率 中等 优秀(适合硬件实现)
量子安全 256 位 → ~128 位有效安全 同上,但海绵结构提供额外防护

6.4 Java 实现:SHA 家族 + HMAC

java 复制代码
import java.security.MessageDigest;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.HexFormat;

public class ShaExample {

    // SHA-256 哈希
    public static String sha256(String input) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] hash = md.digest(input.getBytes("UTF-8"));
        return HexFormat.of().formatHex(hash);
    }

    // SHA-512 哈希
    public static String sha512(String input) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-512");
        byte[] hash = md.digest(input.getBytes("UTF-8"));
        return HexFormat.of().formatHex(hash);
    }

    // SHA3-256 哈希(Java 9+)
    public static String sha3_256(String input) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA3-256");
        byte[] hash = md.digest(input.getBytes("UTF-8"));
        return HexFormat.of().formatHex(hash);
    }

    // HMAC-SHA256(消息认证码)
    public static String hmacSha256(String data, byte[] key) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(key, "HmacSHA256"));
        byte[] result = mac.doFinal(data.getBytes("UTF-8"));
        return HexFormat.of().formatHex(result);
    }

    // 演示雪崩效应
    public static void avalancheDemo() throws Exception {
        String input1 = "Hello, World!";
        String input2 = "Hello, World?";  // 仅改变一个字符

        String hash1 = sha256(input1);
        String hash2 = sha256(input2);

        System.out.println("输入1: " + input1);
        System.out.println("SHA-256: " + hash1);
        System.out.println("输入2: " + input2);
        System.out.println("SHA-256: " + hash2);

        // 计算汉明距离(不同位数)
        int diffBits = 0;
        for (int i = 0; i < hash1.length(); i++) {
            int xor = Integer.parseInt(hash1.substring(i, i+1), 16)
                    ^ Integer.parseInt(hash2.substring(i, i+1), 16);
            diffBits += Integer.bitCount(xor);
        }
        System.out.printf("差异位数: %d / 256 (%.1f%%)\n",
            diffBits, diffBits * 100.0 / 256);
    }

    public static void main(String[] args) throws Exception {
        String msg = "密码学是信息安全的基石";

        System.out.println("=== 哈希算法对比 ===");
        System.out.println("SHA-256:  " + sha256(msg));
        System.out.println("SHA-512:  " + sha512(msg));
        System.out.println("SHA3-256: " + sha3_256(msg));

        System.out.println("\n=== HMAC-SHA256 ===");
        byte[] hmacKey = "my-secret-hmac-key-12345".getBytes();
        System.out.println("HMAC: " + hmacSha256(msg, hmacKey));

        System.out.println("\n=== 雪崩效应演示 ===");
        avalancheDemo();
    }
}

6.5 Python 实现:SHA 全家族 + HMAC

python 复制代码
import hashlib
import hmac

def hash_demo():
    msg = "密码学是信息安全的基石".encode("utf-8")

    print("=== SHA 家族哈希对比 ===")
    print(f"SHA-256:   {hashlib.sha256(msg).hexdigest()}")
    print(f"SHA-384:   {hashlib.sha384(msg).hexdigest()}")
    print(f"SHA-512:   {hashlib.sha512(msg).hexdigest()}")
    print(f"SHA3-256:  {hashlib.sha3_256(msg).hexdigest()}")
    print(f"SHA3-512:  {hashlib.sha3_512(msg).hexdigest()}")
    print(f"BLAKE2b:   {hashlib.blake2b(msg).hexdigest()}")
    print(f"BLAKE2s:   {hashlib.blake2s(msg).hexdigest()}")

    # HMAC
    key = b"my-secret-hmac-key-12345"
    mac = hmac.new(key, msg, hashlib.sha256).hexdigest()
    print(f"\nHMAC-SHA256: {mac}")

    # HMAC 验证
    mac2 = hmac.new(key, msg, hashlib.sha256).hexdigest()
    print(f"HMAC 验证: {hmac.compare_digest(mac, mac2)}")

def avalanche_demo():
    """雪崩效应演示"""
    print("\n=== 雪崩效应 ===")
    h1 = hashlib.sha256(b"Hello, World!").digest()
    h2 = hashlib.sha256(b"Hello, World?").digest()

    diff = sum(bin(a ^ b).count('1') for a, b in zip(h1, h2))
    print(f"输入仅差 1 个字符")
    print(f"SHA-256 输出差异: {diff} / 256 位 ({diff*100/256:.1f}%)")

def file_hash(filepath: str):
    """文件哈希(流式处理,支持大文件)"""
    sha256 = hashlib.sha256()
    with open(filepath, "rb") as f:
        for chunk in iter(lambda: f.read(8192), b""):
            sha256.update(chunk)
    return sha256.hexdigest()

if __name__ == "__main__":
    hash_demo()
    avalanche_demo()

6.6 密码哈希(Password Hashing)

注意:SHA-256 等通用哈希不适合直接用于密码存储!应使用专用的密码哈希函数。

算法 推荐度 说明
bcrypt ✅ 推荐 经典选择,内置盐和工作因子
scrypt ✅ 推荐 内存密集型,抗 GPU/ASIC
Argon2id ✅✅ 强烈推荐 2015 年密码哈希竞赛冠军,当前最佳选择
PBKDF2 ⚠️ 可用 迭代次数需足够大(≥600,000)

Python Argon2 示例:

python 复制代码
from argon2 import PasswordHasher

ph = PasswordHasher(
    time_cost=3,        # 迭代次数
    memory_cost=65536,  # 内存使用 64MB
    parallelism=4,      # 并行线程数
)

# 哈希密码
password_hash = ph.hash("MySecureP@ssword123")
print(f"Argon2id Hash: {password_hash}")

# 验证密码
try:
    ph.verify(password_hash, "MySecureP@ssword123")
    print("✅ 密码验证通过")
except Exception:
    print("❌ 密码验证失败")

7. 传输层安全:TLS

7.1 概述

TLS(Transport Layer Security)是保护互联网通信安全的核心协议,用于 HTTPS、安全邮件、VPN 等场景。TLS 1.3(RFC 8446,2018年发布)是当前最新版本。

TLS 版本演进:

版本 年份 状态 说明
SSL 2.0 1995 ❌ 已废弃 存在严重安全漏洞
SSL 3.0 1996 ❌ 已废弃 POODLE 攻击
TLS 1.0 1999 ❌ 已废弃 BEAST 攻击
TLS 1.1 2006 ❌ 已废弃 安全性不足
TLS 1.2 2008 ⚠️ 仍可用 支持 AEAD,但配置复杂
TLS 1.3 2018 ✅✅ 推荐 简化握手、强制前向保密、移除不安全算法

7.2 TLS 1.3 握手流程

TLS 1.3 将握手从 2-RTT 缩减为 1-RTT,大幅降低延迟:

复制代码
客户端                                        服务器
  │                                              │
  │── ClientHello ──────────────────────────────→│
  │   · 支持的密码套件                              │
  │   · 支持的 TLS 版本(在 supported_versions 扩展中)│
  │   · 密钥共享参数(key_share)                    │
  │   · 客户端随机数                                │
  │                                              │
  │←── ServerHello ──────────────────────────────│
  │    · 选定的密码套件                             │
  │    · 服务器密钥共享参数                          │
  │    · 服务器随机数                               │
  │                                              │
  │    ===== 此后所有通信均已加密 =====              │
  │                                              │
  │←── {EncryptedExtensions} ────────────────────│
  │←── {Certificate} ───────────────────────────│
  │←── {CertificateVerify} ─────────────────────│
  │←── {Finished} ──────────────────────────────│
  │                                              │
  │── {Finished} ──────────────────────────────→│
  │                                              │
  │←==========  应用数据传输  ==========→│

7.3 TLS 1.3 vs TLS 1.2 关键区别

特性 TLS 1.2 TLS 1.3
握手往返 2-RTT 1-RTT(支持 0-RTT 恢复)
密钥交换 RSA、DHE、ECDHE 仅 (EC)DHE
密码套件数量 ~37 种 5 种 AEAD 套件
前向保密 可选 强制
静态 RSA 密钥交换 支持 已移除
压缩 支持 已移除(防 CRIME 攻击)
ServerHello 后 明文 加密
0-RTT 不支持 支持(会话恢复)

7.4 TLS 1.3 支持的密码套件

复制代码
TLS_AES_128_GCM_SHA256         (0x1301)
TLS_AES_256_GCM_SHA384         (0x1302)
TLS_CHACHA20_POLY1305_SHA256   (0x1303)
TLS_AES_128_CCM_SHA256         (0x1304)
TLS_AES_128_CCM_8_SHA256       (0x1305)

7.5 Java 实现:TLS 服务器与客户端

java 复制代码
import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;

// ===== TLS 服务器 =====
public class TlsServer {
    public static void main(String[] args) throws Exception {
        // 加载密钥库(包含服务器证书和私钥)
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(new FileInputStream("server.p12"), "password".toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, "password".toCharArray());

        SSLContext ctx = SSLContext.getInstance("TLSv1.3");
        ctx.init(kmf.getKeyManagers(), null, null);

        SSLServerSocketFactory ssf = ctx.getServerSocketFactory();
        SSLServerSocket serverSocket = (SSLServerSocket) ssf.createServerSocket(8443);

        // 限制协议和密码套件
        serverSocket.setEnabledProtocols(new String[]{"TLSv1.3"});
        serverSocket.setEnabledCipherSuites(new String[]{
            "TLS_AES_256_GCM_SHA384",
            "TLS_AES_128_GCM_SHA256"
        });

        System.out.println("TLS 1.3 服务器启动,监听端口 8443...");

        while (true) {
            SSLSocket client = (SSLSocket) serverSocket.accept();
            SSLSession session = client.getSession();
            System.out.println("客户端连接: " + client.getInetAddress());
            System.out.println("协议: " + session.getProtocol());
            System.out.println("密码套件: " + session.getCipherSuite());

            // 读写数据
            BufferedReader in = new BufferedReader(
                new InputStreamReader(client.getInputStream()));
            PrintWriter out = new PrintWriter(client.getOutputStream(), true);

            String line = in.readLine();
            System.out.println("收到: " + line);
            out.println("服务器回复: " + line);
            client.close();
        }
    }
}
java 复制代码
// ===== TLS 客户端 =====
public class TlsClient {
    public static void main(String[] args) throws Exception {
        SSLContext ctx = SSLContext.getInstance("TLSv1.3");
        ctx.init(null, null, null);  // 使用默认信任库

        SSLSocketFactory sf = ctx.getSocketFactory();
        SSLSocket socket = (SSLSocket) sf.createSocket("localhost", 8443);
        socket.setEnabledProtocols(new String[]{"TLSv1.3"});

        // 发送数据
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        BufferedReader in = new BufferedReader(
            new InputStreamReader(socket.getInputStream()));

        out.println("Hello, TLS 1.3!");
        System.out.println("服务器回复: " + in.readLine());

        // 显示会话信息
        SSLSession session = socket.getSession();
        System.out.println("协议: " + session.getProtocol());
        System.out.println("密码套件: " + session.getCipherSuite());

        socket.close();
    }
}

7.6 Python 实现:TLS 连接与证书验证

python 复制代码
import ssl
import socket
import pprint

def inspect_tls_connection(hostname: str, port: int = 443):
    """检查目标站点的 TLS 配置"""
    context = ssl.create_default_context()

    with socket.create_connection((hostname, port)) as sock:
        with context.wrap_socket(sock, server_hostname=hostname) as ssock:
            print(f"=== {hostname}:{port} TLS 信息 ===")
            print(f"TLS 版本: {ssock.version()}")
            print(f"密码套件: {ssock.cipher()}")

            cert = ssock.getpeercert()
            print(f"\n证书主题: {dict(x[0] for x in cert['subject'])}")
            print(f"颁发者:   {dict(x[0] for x in cert['issuer'])}")
            print(f"有效期至: {cert['notAfter']}")
            print(f"SAN:")
            for san_type, san_value in cert.get('subjectAltName', []):
                print(f"  {san_type}: {san_value}")

def create_tls_server(certfile: str, keyfile: str, port: int = 8443):
    """创建 TLS 1.3 服务器"""
    context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
    context.minimum_version = ssl.TLSVersion.TLSv1_3
    context.load_cert_chain(certfile, keyfile)

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.bind(('0.0.0.0', port))
        sock.listen(5)
        with context.wrap_socket(sock, server_side=True) as ssock:
            print(f"TLS 1.3 服务器监听端口 {port}")
            conn, addr = ssock.accept()
            print(f"连接来自: {addr}, 协议: {conn.version()}")
            data = conn.recv(1024)
            conn.send(b"Hello from TLS 1.3 server!")
            conn.close()

if __name__ == "__main__":
    # 检查知名网站的 TLS 配置
    for site in ["www.google.com", "github.com", "www.cloudflare.com"]:
        try:
            inspect_tls_connection(site)
            print()
        except Exception as e:
            print(f"{site}: {e}\n")

8. 公钥基础设施:PKI

8.1 概述

PKI(Public Key Infrastructure)是一套用于创建、管理、分发、使用、存储和撤销数字证书的体系。它为公钥加密提供信任框架,是 HTTPS、安全邮件、VPN、代码签名等技术的基础。

8.2 PKI 核心组件

组件 说明
CA(证书颁发机构) 签发、存储和签署数字证书的可信实体
RA(注册机构) 验证证书申请者的身份
数字证书 将公钥与实体身份绑定的电子凭证(X.509 标准)
证书库 存储证书及其元数据的数据库
CRL(证书吊销列表) 列出在到期前被吊销的证书
OCSP(在线证书状态协议) 实时查询证书是否被吊销

8.3 证书信任链

复制代码
Root CA(根证书颁发机构)
  │  自签名证书,离线存储
  │  内置于操作系统和浏览器的信任库中
  │
  ├── Intermediate CA(中间 CA)
  │     │  由 Root CA 签发
  │     │
  │     ├── End Entity Certificate(终端实体证书)
  │     │     用于 www.example.com 的 TLS 证书
  │     │
  │     └── End Entity Certificate
  │           用于 mail.example.com 的 TLS 证书
  │
  └── Intermediate CA 2
        │
        └── End Entity Certificate
              代码签名证书

验证过程:浏览器从终端实体证书开始,沿信任链逐级向上验证签名,直到到达已信任的根 CA。

8.4 X.509 证书结构

复制代码
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 04:00:00:00:00:01:15:4b:5a:c3:94
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=BE, O=GlobalSign, CN=GlobalSign Root CA
        Validity:
            Not Before: Sep  1 00:00:00 2014 GMT
            Not After : Jan 28 12:00:00 2028 GMT
        Subject: C=US, ST=California, O=Example Inc, CN=www.example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (2048 bit)
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:www.example.com, DNS:example.com
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            X509v3 CRL Distribution Points:
                URI:http://crl.globalsign.com/root.crl
    Signature Algorithm: sha256WithRSAEncryption
        [签名数据]

8.5 Java 实现:证书生成与验证

java 复制代码
import java.security.*;
import java.security.cert.*;
import java.math.BigInteger;
import java.util.Date;
import java.io.*;

// 使用 Bouncy Castle 库生成自签名证书
// 依赖: org.bouncycastle:bcprov-jdk18on:1.78
// 依赖: org.bouncycastle:bcpkix-jdk18on:1.78

import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.cert.*;
import org.bouncycastle.cert.jcajce.*;
import org.bouncycastle.operator.*;
import org.bouncycastle.operator.jcajce.*;

public class PkiExample {

    // 生成自签名 CA 证书
    public static X509Certificate generateCACert(KeyPair caKeyPair)
            throws Exception {
        X500Name issuer = new X500Name("CN=My Root CA, O=MyOrg, C=CN");
        BigInteger serial = BigInteger.valueOf(System.currentTimeMillis());
        Date notBefore = new Date();
        Date notAfter = new Date(System.currentTimeMillis()
            + 365L * 24 * 60 * 60 * 1000 * 10); // 10 年

        JcaX509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
            issuer, serial, notBefore, notAfter, issuer,
            caKeyPair.getPublic()
        );

        // 添加 CA 扩展
        builder.addExtension(Extension.basicConstraints, true,
            new BasicConstraints(true));
        builder.addExtension(Extension.keyUsage, true,
            new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign));

        ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA")
            .build(caKeyPair.getPrivate());

        return new JcaX509CertificateConverter()
            .getCertificate(builder.build(signer));
    }

    // 使用 CA 签发终端实体证书
    public static X509Certificate generateEndEntityCert(
            KeyPair caKeyPair, X509Certificate caCert,
            KeyPair entityKeyPair, String cn) throws Exception {

        X500Name issuer = new X500Name(caCert.getSubjectX500Principal().getName());
        X500Name subject = new X500Name("CN=" + cn + ", O=MyOrg, C=CN");
        BigInteger serial = BigInteger.valueOf(System.currentTimeMillis());
        Date notBefore = new Date();
        Date notAfter = new Date(System.currentTimeMillis()
            + 365L * 24 * 60 * 60 * 1000); // 1 年

        JcaX509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
            issuer, serial, notBefore, notAfter, subject,
            entityKeyPair.getPublic()
        );

        // SAN 扩展
        GeneralNames sans = new GeneralNames(new GeneralName[]{
            new GeneralName(GeneralName.dNSName, cn),
            new GeneralName(GeneralName.dNSName, "www." + cn)
        });
        builder.addExtension(Extension.subjectAlternativeName, false, sans);
        builder.addExtension(Extension.keyUsage, true,
            new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment));

        ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA")
            .build(caKeyPair.getPrivate());

        return new JcaX509CertificateConverter()
            .getCertificate(builder.build(signer));
    }

    // 验证证书链
    public static void verifyCertificateChain(
            X509Certificate endEntity, X509Certificate caCert)
            throws Exception {
        // 1. 验证签名
        endEntity.verify(caCert.getPublicKey());
        System.out.println("✅ 签名验证通过");

        // 2. 检查有效期
        endEntity.checkValidity();
        System.out.println("✅ 证书在有效期内");

        // 3. 检查颁发者
        if (endEntity.getIssuerX500Principal()
                .equals(caCert.getSubjectX500Principal())) {
            System.out.println("✅ 颁发者匹配");
        }
    }

    public static void main(String[] args) throws Exception {
        Security.addProvider(
            new org.bouncycastle.jce.provider.BouncyCastleProvider());

        // 生成 CA 密钥对和证书
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(3072);
        KeyPair caKeyPair = kpg.generateKeyPair();
        X509Certificate caCert = generateCACert(caKeyPair);
        System.out.println("CA 证书: " + caCert.getSubjectX500Principal());

        // 生成终端实体证书
        KeyPair entityKP = kpg.generateKeyPair();
        X509Certificate entityCert = generateEndEntityCert(
            caKeyPair, caCert, entityKP, "example.com");
        System.out.println("实体证书: "
            + entityCert.getSubjectX500Principal());

        // 验证证书链
        System.out.println("\n=== 证书链验证 ===");
        verifyCertificateChain(entityCert, caCert);
    }
}

8.6 Python 实现:证书操作

python 复制代码
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
import datetime

def create_ca_certificate():
    """创建自签名 CA 根证书"""
    # 生成 CA 密钥对
    ca_key = rsa.generate_private_key(public_exponent=65537, key_size=3072)

    ca_name = x509.Name([
        x509.NameAttribute(NameOID.COUNTRY_NAME, "CN"),
        x509.NameAttribute(NameOID.ORGANIZATION_NAME, "My Organization"),
        x509.NameAttribute(NameOID.COMMON_NAME, "My Root CA"),
    ])

    ca_cert = (
        x509.CertificateBuilder()
        .subject_name(ca_name)
        .issuer_name(ca_name)  # 自签名
        .public_key(ca_key.public_key())
        .serial_number(x509.random_serial_number())
        .not_valid_before(datetime.datetime.now(datetime.timezone.utc))
        .not_valid_after(
            datetime.datetime.now(datetime.timezone.utc)
            + datetime.timedelta(days=3650)
        )
        .add_extension(
            x509.BasicConstraints(ca=True, path_length=None), critical=True
        )
        .add_extension(
            x509.KeyUsage(
                digital_signature=False, key_cert_sign=True,
                crl_sign=True, content_commitment=False,
                key_encipherment=False, data_encipherment=False,
                key_agreement=False, encipher_only=False,
                decipher_only=False,
            ),
            critical=True,
        )
        .sign(ca_key, hashes.SHA256())
    )

    print(f"CA 证书已创建: {ca_cert.subject}")
    return ca_key, ca_cert

def issue_server_certificate(ca_key, ca_cert, domain: str):
    """使用 CA 签发服务器证书"""
    server_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)

    subject = x509.Name([
        x509.NameAttribute(NameOID.COUNTRY_NAME, "CN"),
        x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Example Inc"),
        x509.NameAttribute(NameOID.COMMON_NAME, domain),
    ])

    server_cert = (
        x509.CertificateBuilder()
        .subject_name(subject)
        .issuer_name(ca_cert.subject)
        .public_key(server_key.public_key())
        .serial_number(x509.random_serial_number())
        .not_valid_before(datetime.datetime.now(datetime.timezone.utc))
        .not_valid_after(
            datetime.datetime.now(datetime.timezone.utc)
            + datetime.timedelta(days=365)
        )
        .add_extension(
            x509.SubjectAlternativeName([
                x509.DNSName(domain),
                x509.DNSName(f"www.{domain}"),
            ]),
            critical=False,
        )
        .add_extension(
            x509.KeyUsage(
                digital_signature=True, key_encipherment=True,
                key_cert_sign=False, crl_sign=False,
                content_commitment=False, data_encipherment=False,
                key_agreement=False, encipher_only=False,
                decipher_only=False,
            ),
            critical=True,
        )
        .add_extension(
            x509.ExtendedKeyUsage([x509.oid.ExtendedKeyUsageOID.SERVER_AUTH]),
            critical=False,
        )
        .sign(ca_key, hashes.SHA256())
    )

    print(f"服务器证书已签发: {server_cert.subject}")
    return server_key, server_cert

def verify_certificate(cert, ca_cert):
    """验证证书(简化版,生产中使用完整路径验证)"""
    print(f"\n=== 证书验证: {cert.subject} ===")
    print(f"颁发者: {cert.issuer}")
    print(f"有效期: {cert.not_valid_before_utc} ~ {cert.not_valid_after_utc}")
    print(f"序列号: {cert.serial_number}")

    # 验证签名
    try:
        ca_cert.public_key().verify(
            cert.signature,
            cert.tbs_certificate_bytes,
            padding.PKCS1v15(),
            cert.signature_hash_algorithm,
        )
        print("✅ CA 签名验证通过")
    except Exception as e:
        print(f"❌ 签名验证失败: {e}")

    # 检查有效期
    now = datetime.datetime.now(datetime.timezone.utc)
    if cert.not_valid_before_utc <= now <= cert.not_valid_after_utc:
        print("✅ 证书在有效期内")
    else:
        print("❌ 证书已过期或尚未生效")

    # 显示 SAN
    try:
        san = cert.extensions.get_extension_for_class(
            x509.SubjectAlternativeName)
        print(f"SAN: {san.value.get_values_for_type(x509.DNSName)}")
    except x509.ExtensionNotFound:
        pass

def save_artifacts(ca_key, ca_cert, server_key, server_cert):
    """保存证书和密钥到文件"""
    # CA 证书
    with open("ca.crt", "wb") as f:
        f.write(ca_cert.public_bytes(serialization.Encoding.PEM))

    # CA 私钥
    with open("ca.key", "wb") as f:
        f.write(ca_key.private_bytes(
            serialization.Encoding.PEM,
            serialization.PrivateFormat.PKCS8,
            serialization.BestAvailableEncryption(b"ca-password"),
        ))

    # 服务器证书
    with open("server.crt", "wb") as f:
        f.write(server_cert.public_bytes(serialization.Encoding.PEM))

    # 服务器私钥
    with open("server.key", "wb") as f:
        f.write(server_key.private_bytes(
            serialization.Encoding.PEM,
            serialization.PrivateFormat.PKCS8,
            serialization.NoEncryption(),
        ))
    print("\n所有证书和密钥已保存到文件")

if __name__ == "__main__":
    from cryptography.hazmat.primitives.asymmetric import padding

    ca_key, ca_cert = create_ca_certificate()
    server_key, server_cert = issue_server_certificate(
        ca_key, ca_cert, "example.com")
    verify_certificate(server_cert, ca_cert)
    save_artifacts(ca_key, ca_cert, server_key, server_cert)

9. 数字签名

9.1 签名原理

数字签名提供三个关键保障:身份认证 (确认消息来自声称的发送方)、完整性 (消息未被篡改)和不可否认性(发送方无法否认发送行为)。

签名流程:

  1. 对原始数据计算哈希摘要
  2. 用私钥加密哈希摘要 → 得到数字签名
  3. 将原始数据 + 数字签名一起发送

验签流程:

  1. 用公钥解密数字签名 → 得到原始哈希摘要
  2. 对收到的数据重新计算哈希摘要
  3. 比较两个摘要是否一致

9.2 常用签名算法

算法 基础 密钥大小 速度 推荐度
RSA-PSS 大整数分解 3072+ 位
ECDSA 椭圆曲线 256+ 位 ✅✅
EdDSA (Ed25519) 扭曲 Edwards 曲线 256 位 最快 ✅✅✅
ML-DSA (Dilithium) 格密码 ~2.5KB 中等 ✅ 后量子

9.3 完整 Java 签名工具类

java 复制代码
import java.security.*;
import java.security.spec.*;
import java.util.Base64;

public class DigitalSignatureUtil {

    // ====== RSA-PSS 签名 ======
    public static byte[] signRSA(byte[] data, PrivateKey key) throws Exception {
        Signature sig = Signature.getInstance("RSASSA-PSS");
        sig.setParameter(new PSSParameterSpec(
            "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1));
        sig.initSign(key);
        sig.update(data);
        return sig.sign();
    }

    public static boolean verifyRSA(byte[] data, byte[] signature,
                                     PublicKey key) throws Exception {
        Signature sig = Signature.getInstance("RSASSA-PSS");
        sig.setParameter(new PSSParameterSpec(
            "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1));
        sig.initVerify(key);
        sig.update(data);
        return sig.verify(signature);
    }

    // ====== ECDSA 签名 ======
    public static byte[] signECDSA(byte[] data, PrivateKey key)
            throws Exception {
        Signature sig = Signature.getInstance("SHA256withECDSA");
        sig.initSign(key);
        sig.update(data);
        return sig.sign();
    }

    public static boolean verifyECDSA(byte[] data, byte[] signature,
                                       PublicKey key) throws Exception {
        Signature sig = Signature.getInstance("SHA256withECDSA");
        sig.initVerify(key);
        sig.update(data);
        return sig.verify(signature);
    }

    // ====== Ed25519 签名 (Java 15+) ======
    public static byte[] signEd25519(byte[] data, PrivateKey key)
            throws Exception {
        Signature sig = Signature.getInstance("Ed25519");
        sig.initSign(key);
        sig.update(data);
        return sig.sign();
    }

    public static boolean verifyEd25519(byte[] data, byte[] signature,
                                         PublicKey key) throws Exception {
        Signature sig = Signature.getInstance("Ed25519");
        sig.initVerify(key);
        sig.update(data);
        return sig.verify(signature);
    }

    public static void main(String[] args) throws Exception {
        byte[] data = "重要合同文件 v3.2 final".getBytes("UTF-8");

        // RSA-PSS
        KeyPairGenerator rsaGen = KeyPairGenerator.getInstance("RSA");
        rsaGen.initialize(3072);
        KeyPair rsaKP = rsaGen.generateKeyPair();
        byte[] rsaSig = signRSA(data, rsaKP.getPrivate());
        System.out.println("RSA-PSS 签名长度: " + rsaSig.length + " 字节");
        System.out.println("RSA-PSS 验证: " + verifyRSA(data, rsaSig,
            rsaKP.getPublic()));

        // ECDSA
        KeyPairGenerator ecGen = KeyPairGenerator.getInstance("EC");
        ecGen.initialize(new ECGenParameterSpec("secp256r1"));
        KeyPair ecKP = ecGen.generateKeyPair();
        byte[] ecSig = signECDSA(data, ecKP.getPrivate());
        System.out.println("\nECDSA 签名长度: " + ecSig.length + " 字节");
        System.out.println("ECDSA 验证: " + verifyECDSA(data, ecSig,
            ecKP.getPublic()));

        // Ed25519 (Java 15+)
        KeyPairGenerator edGen = KeyPairGenerator.getInstance("Ed25519");
        KeyPair edKP = edGen.generateKeyPair();
        byte[] edSig = signEd25519(data, edKP.getPrivate());
        System.out.println("\nEd25519 签名长度: " + edSig.length + " 字节");
        System.out.println("Ed25519 验证: " + verifyEd25519(data, edSig,
            edKP.getPublic()));
    }
}

10. 混合加密体系

10.1 为什么需要混合加密

  • 对称加密(AES):速度快,但密钥分发困难
  • 非对称加密(RSA/ECC):密钥分发方便,但速度慢且不适合大数据

混合加密结合两者优势:用非对称加密安全传输对称密钥,再用对称密钥加密实际数据。

10.2 Java 实现:RSA + AES 混合加密

java 复制代码
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.util.Base64;

public class HybridEncryption {

    // 加密:生成 AES 密钥 → AES 加密数据 → RSA 加密 AES 密钥
    public static EncryptedPackage encrypt(byte[] plaintext,
                                            PublicKey recipientPublicKey)
            throws Exception {
        // 1. 生成随机 AES-256 密钥
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(256, new SecureRandom());
        SecretKey aesKey = keyGen.generateKey();

        // 2. AES-GCM 加密数据
        byte[] iv = new byte[12];
        new SecureRandom().nextBytes(iv);
        Cipher aesCipher = Cipher.getInstance("AES/GCM/NoPadding");
        aesCipher.init(Cipher.ENCRYPT_MODE, aesKey,
            new GCMParameterSpec(128, iv));
        byte[] ciphertext = aesCipher.doFinal(plaintext);

        // 3. RSA-OAEP 加密 AES 密钥
        Cipher rsaCipher = Cipher.getInstance(
            "RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        rsaCipher.init(Cipher.ENCRYPT_MODE, recipientPublicKey);
        byte[] encryptedKey = rsaCipher.doFinal(aesKey.getEncoded());

        return new EncryptedPackage(encryptedKey, iv, ciphertext);
    }

    // 解密:RSA 解密 AES 密钥 → AES 解密数据
    public static byte[] decrypt(EncryptedPackage pkg,
                                  PrivateKey recipientPrivateKey)
            throws Exception {
        // 1. RSA 解密 AES 密钥
        Cipher rsaCipher = Cipher.getInstance(
            "RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        rsaCipher.init(Cipher.DECRYPT_MODE, recipientPrivateKey);
        byte[] aesKeyBytes = rsaCipher.doFinal(pkg.encryptedKey);
        SecretKey aesKey = new SecretKeySpec(aesKeyBytes, "AES");

        // 2. AES-GCM 解密数据
        Cipher aesCipher = Cipher.getInstance("AES/GCM/NoPadding");
        aesCipher.init(Cipher.DECRYPT_MODE, aesKey,
            new GCMParameterSpec(128, pkg.iv));
        return aesCipher.doFinal(pkg.ciphertext);
    }

    // 封装加密结果
    static class EncryptedPackage {
        byte[] encryptedKey;  // RSA 加密的 AES 密钥
        byte[] iv;            // AES-GCM IV
        byte[] ciphertext;    // AES-GCM 密文(含认证标签)

        EncryptedPackage(byte[] ek, byte[] iv, byte[] ct) {
            this.encryptedKey = ek;
            this.iv = iv;
            this.ciphertext = ct;
        }
    }

    public static void main(String[] args) throws Exception {
        // 接收方生成 RSA 密钥对
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(3072);
        KeyPair kp = kpg.generateKeyPair();

        // 发送方加密
        String message = "这是一份机密报告,包含大量数据...".repeat(100);
        EncryptedPackage pkg = encrypt(
            message.getBytes("UTF-8"), kp.getPublic());

        System.out.println("原始大小: " + message.getBytes().length + " 字节");
        System.out.println("加密密钥大小: " + pkg.encryptedKey.length + " 字节");
        System.out.println("密文大小: " + pkg.ciphertext.length + " 字节");

        // 接收方解密
        byte[] decrypted = decrypt(pkg, kp.getPrivate());
        System.out.println("解密成功: " + new String(decrypted, "UTF-8")
            .equals(message));
    }
}

10.3 Python 实现:ECC + AES 混合加密

python 复制代码
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives import hashes, serialization
import os, base64

class HybridEncryption:
    """基于 ECIES 思想的 ECC + AES-GCM 混合加密"""

    @staticmethod
    def encrypt(plaintext: bytes, recipient_public_key) -> dict:
        # 1. 生成临时 ECC 密钥对
        ephemeral_key = ec.generate_private_key(ec.SECP256R1())

        # 2. ECDH 密钥协商
        shared_secret = ephemeral_key.exchange(
            ec.ECDH(), recipient_public_key)

        # 3. HKDF 派生 AES 密钥
        aes_key = HKDF(
            algorithm=hashes.SHA256(),
            length=32,
            salt=None,
            info=b"hybrid-encryption-v1",
        ).derive(shared_secret)

        # 4. AES-GCM 加密
        nonce = os.urandom(12)
        aesgcm = AESGCM(aes_key)
        ciphertext = aesgcm.encrypt(nonce, plaintext, None)

        # 5. 导出临时公钥(发送给接收方)
        ephemeral_pub_bytes = ephemeral_key.public_key().public_bytes(
            serialization.Encoding.X962,
            serialization.PublicFormat.CompressedPoint,
        )

        return {
            "ephemeral_public_key": ephemeral_pub_bytes,
            "nonce": nonce,
            "ciphertext": ciphertext,
        }

    @staticmethod
    def decrypt(encrypted: dict, recipient_private_key) -> bytes:
        # 1. 恢复临时公钥
        ephemeral_pub = ec.EllipticCurvePublicKey.from_encoded_point(
            ec.SECP256R1(), encrypted["ephemeral_public_key"])

        # 2. ECDH 密钥协商
        shared_secret = recipient_private_key.exchange(
            ec.ECDH(), ephemeral_pub)

        # 3. 派生相同的 AES 密钥
        aes_key = HKDF(
            algorithm=hashes.SHA256(),
            length=32,
            salt=None,
            info=b"hybrid-encryption-v1",
        ).derive(shared_secret)

        # 4. AES-GCM 解密
        aesgcm = AESGCM(aes_key)
        return aesgcm.decrypt(
            encrypted["nonce"], encrypted["ciphertext"], None)

# 使用示例
def hybrid_demo():
    # 接收方生成密钥对
    recipient_key = ec.generate_private_key(ec.SECP256R1())
    recipient_pub = recipient_key.public_key()

    # 发送方加密
    message = "机密数据:用户 Alice 的银行账户信息..." * 50
    encrypted = HybridEncryption.encrypt(
        message.encode(), recipient_pub)

    print(f"临时公钥大小: {len(encrypted['ephemeral_public_key'])} 字节")
    print(f"密文大小: {len(encrypted['ciphertext'])} 字节")

    # 接收方解密
    decrypted = HybridEncryption.decrypt(encrypted, recipient_key)
    print(f"解密成功: {decrypted.decode() == message}")

if __name__ == "__main__":
    hybrid_demo()

11. 后量子密码学

11.1 量子威胁

量子计算机通过两个关键算法威胁现有密码体系:

  • Shor 算法 :可在多项式时间内分解大整数和求解离散对数 → 彻底破解 RSA、DSA、ECDSA、ECDH、ElGamal
  • Grover 算法 :将暴力搜索复杂度降低为平方根 → 将 AES-128 降至 64 位有效安全,SHA-256 碰撞安全从 128 位降至约 85 位

11.2 各算法的量子抗性

算法类型 算法 量子安全性 应对策略
对称加密 AES-128 ⚠️ 降至 64 位 升级到 AES-256
对称加密 AES-256 ✅ 降至 128 位,仍安全 继续使用
哈希 SHA-256 ✅ 基本安全 推荐升级到 SHA-384+
哈希 SHA-512 ✅✅ 安全 继续使用
非对称 RSA ❌ 被 Shor 算法破解 迁移到 PQC
非对称 ECDSA/ECDH ❌ 被 Shor 算法破解 迁移到 PQC
签名 EdDSA ❌ 被 Shor 算法破解 迁移到 PQC

11.3 NIST 后量子密码标准(2024年发布)

标准 原名 用途 数学基础
FIPS 203 (ML-KEM) CRYSTALS-Kyber 密钥封装(密钥交换) 模格(Module Lattice)
FIPS 204 (ML-DSA) CRYSTALS-Dilithium 数字签名 模格
FIPS 205 (SLH-DSA) SPHINCS+ 数字签名(无状态哈希) 哈希函数

额外候选:FALCON(签名,基于 NTRU 格)、Classic McEliece(KEM,基于编码理论)。

11.4 CNSA 2.0 迁移时间表(美国 NSA)

用途 要求算法 迁移截止
软件/固件签名 ML-DSA 或 LMS/XMSS 2025 年起
Web 浏览器/服务器 ML-KEM + ML-DSA 2025 年起
传统网络 ML-KEM + ML-DSA 2030 年
操作系统 全面 PQC 支持 2030 年
哈希算法 SHA-384 或 SHA-512 立即
对称加密 AES-256 立即

11.5 过渡策略:混合模式

当前推荐的迁移策略是"混合"模式------同时使用传统算法和后量子算法,确保即使某一方被攻破,另一方仍能提供安全保障。

复制代码
混合密钥交换:X25519 + ML-KEM-768
混合数字签名:Ed25519 + ML-DSA-65

12. 密码学安全最佳实践

12.1 密钥管理

  1. 密钥生成:始终使用密码学安全的随机数生成器(CSPRNG)
  2. 密钥存储:使用 HSM(硬件安全模块)或密钥管理服务(KMS)
  3. 密钥轮换:定期更换密钥,建立轮换策略
  4. 密钥销毁:密钥不再需要时安全擦除
  5. 最小权限:仅授予必要的密钥访问权限

12.2 算法选择指南

用途 推荐算法 避免使用
数据加密 AES-256-GCM DES、3DES、RC4、AES-ECB
密钥交换 X25519、ECDH P-256 静态 RSA 密钥交换
数字签名 Ed25519、ECDSA P-256 RSA-1024、PKCS#1 v1.5
哈希 SHA-256、SHA-3、BLAKE2 MD5、SHA-1
密码哈希 Argon2id、bcrypt MD5、SHA-256 直接哈希
TLS 协议 TLS 1.3 SSL、TLS 1.0/1.1
密钥派生 HKDF、PBKDF2(≥600k 迭代) 简单哈希

12.3 常见安全陷阱

  1. 自己发明密码算法:永远不要。使用经过审查的标准算法。
  2. 复用 Nonce/IV:AES-GCM 中重复使用 nonce 会导致灾难性安全问题。
  3. 不验证 MAC/签名:先验证再处理(Encrypt-then-MAC,或使用 AEAD)。
  4. 使用 ECB 模式:相同明文产生相同密文,泄露数据模式。
  5. 硬编码密钥:密钥不应出现在源代码中。
  6. 忽略时序攻击:密码比较应使用常量时间函数。
  7. 不验证证书:禁用证书验证等于没有加密。

13. 算法对比速查表

13.1 安全等级对照

安全位数 AES RSA ECC SHA-2 SHA-3
80 --- 1024 160 --- ---
112 --- 2048 224 SHA-224 SHA3-224
128 AES-128 3072 256 SHA-256 SHA3-256
192 AES-192 7680 384 SHA-384 SHA3-384
256 AES-256 15360 521 SHA-512 SHA3-512

13.2 性能参考(典型硬件)

操作 AES-256-GCM RSA-3072 ECC P-256 Ed25519
加密/签名 ~1 GB/s ~5ms ~2ms ~0.5ms
解密/验签 ~1 GB/s ~100ms ~3ms ~1ms
密钥生成 即时 ~600ms ~10ms ~0.1ms
密钥大小 32 字节 ~384 字节 32 字节 32 字节

13.3 应用场景推荐

场景 推荐方案
HTTPS/Web 安全 TLS 1.3 + ECDHE + AES-256-GCM
文件加密 AES-256-GCM(密钥通过 PBKDF2/Argon2 派生)
数据库字段加密 AES-256-GCM + 密钥管理服务
API 认证 HMAC-SHA256 或 Ed25519 签名
代码签名 RSA-3072-PSS 或 ECDSA P-384
电子邮件加密 S/MIME(RSA/ECC + AES)
区块链 secp256k1 + SHA-256(Bitcoin)/ Keccak-256(Ethereum)
IoT 设备 ECC(资源受限)+ AES-128-CCM
长期存档 AES-256 + 考虑后量子迁移

14. 参考资源

官方标准与规范

  • NIST FIPS 197 --- AES 标准
  • NIST FIPS 186-5 --- 数字签名标准(DSS)
  • NIST FIPS 202 --- SHA-3 标准
  • RFC 8446 --- TLS 1.3
  • RFC 5280 --- X.509 PKI 证书和 CRL 规范
  • NIST SP 800-38D --- AES-GCM 推荐
  • NIST SP 800-56A --- 密钥协商方案
  • NIST PQC 项目 --- https://csrc.nist.gov/projects/post-quantum-cryptography

学习资源

  • 《密码编码学与网络安全》(William Stallings)
  • 《应用密码学》(Bruce Schneier)
  • 《Serious Cryptography》(Jean-Philippe Aumasson)
  • Practical Cryptography for Developers --- https://cryptobook.nakov.com
  • The Illustrated TLS 1.3 Connection --- https://tls13.xargs.org

开发库

  • Java: JCA/JCE (内置)、Bouncy Castle
  • Python: cryptography、PyCryptodome、hashlib(内置)
  • Go: crypto 标准库
  • Rust: ring、RustCrypto
  • C/C++: OpenSSL、libsodium、wolfSSL

相关推荐
weixin_402486343 小时前
小分子 pdb准化为sdf
python
蓝色的杯子3 小时前
Python面试30分钟突击掌握-LeetCode2-Strings
python
lcreek3 小时前
公钥密码学与数字签名:原理详解
密码学
ZC跨境爬虫3 小时前
海南大学交友平台开发实战 day9(头像上传存入 SQLite+BLOB 存储 + 前后端联调避坑全记录)
前端·数据库·python·sqlite
FreakStudio3 小时前
嘉立创开源:应该是全网MicroPython教程最多的开发板
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy
上天_去_做颗惺星 EVE_BLUE3 小时前
接口自动化测试全流程:pytest 用例收集、并行执行、Allure 报告合并与上传
python·pytest
J2虾虾3 小时前
使用Idea当Jar包的反编译
java·intellij-idea·jar
chushiyunen3 小时前
python fastapi使用、uvicorn
开发语言·python·fastapi
白露与泡影3 小时前
2026 全新 Java 面试题汇总(含答案)
java·开发语言