IoT 密码学的"够用就好"
目标:会应用、能理解并能设计方案。不讲复杂数学,只讲必要概念、参数与避坑清单。
必要概念
- 机密性(Confidentiality):防止被看懂(加密)
- 完整性(Integrity):防止被悄悄改(认证)
- 身份不可否认性(Identity):谁在对话(签名/证书)
- 对称密钥(Symmetric):同一把密钥加解密(AES/ChaCha20-Poly1305)
- 非对称密钥(Asymmetric):私钥/公钥(ECDSA/Ed25519、ECDH/X25519)
- AEAD(Authenticated Encryption with Associated Data):一次完成加密+认证(GCM/CCM、ChaCha20-Poly1305)
- MAC(Message Authentication Code):只做认证(HMAC/AES-CMAC),不加密
- KDF(Key Derivation Function):把"原始秘密"(如 ECDH/X25519 共享秘密)变成"可用密钥"
- 密钥格式:SPKI(公钥)/PKCS8(私钥)容器,DER(二进制)/PEM(文本)编码
一张图
[A私钥 + B公钥] --(ECDH/X25519)--> [共享秘密S]
[S] --(HKDF salt, info, L)--> [对称密钥K]
[消息M, AAD] --(AEAD:K, nonce)--> [C || tag]
[M] --(HMAC/CMAC:K)--> [tag]
[M] --(签名:私钥)--> [signature]
- AEAD 输出总是"密文+标签",解密前先验标签
- MAC/签名不加密数据
- 共享秘密不能直接当密钥,必须 KDF
参数小抄(长度与格式)
- Nonce/IV:GCM=12字节;ChaCha20-Poly1305=12字节;CCM=13字节(常用);CBC=16字节
- Key:AES=16/24/32字节;ChaCha20-Poly1305=32字节
- 签名编码:ECDSA=DER 或 RAW(r||s 64字节);Ed25519=RAW
- 公钥/私钥容器:SPKI(公钥)/PKCS8(私钥),DER 字节可转 PEM 文本
何时用什么
- 受限设备/无线协议:AES-CCM(硬件加速) 或 ChaCha20-Poly1305(软实现友好)
- Web/通用:AES-GCM(Galois/Counter Mode) 或 ChaCha20-Poly1305
- 只要完整性:HMAC-SHA256(Hash-based Message Authentication Code) 或 AES-CMAC
- 固件/长消息签名:Ed25519 或 ECDSA-P256
- 会话建立:ECDH-P256 或 X25519 → HKDF → AEAD
攻防小卡片
- 绝不在同一密钥下复用 AEAD nonce
- CBC 本身不认证,必须"加 MAC",推荐改用 AEAD
- 密钥交换一定要带签名,防止中间人攻击(MITM)
快速上手
在 CryptoBox网页版 快速验证:
- 打开网页,按页面完成对应任务:
- Symmetric:对称/AEAD(AES-GCM/CCM/CBC、ChaCha20-Poly1305)
- Hash:哈希(SHA-256)
- MAC:消息认证码(HMAC-SHA256、AES-CMAC)
- KDF:密钥派生(HKDF-SHA256、PBKDF2-SHA256)
- Sign/Verify:签名/验签(ECDSA P-256、Ed25519)
- Key Exchange:密钥交换(ECDH P-256、X25519)
- X.509:证书解析与转换
- Codec:编码转换(Text/Hex/Base64、PEM/DER)
- Random:随机数生成
- 输入与输出默认用 HEX(页面支持 text/hex/base64 三态切换)
- 若向量里给的是 Base64,请用 Codec 页先转为 HEX 再粘贴到对应页面
哈希(Hash)
SHA-256
原理
- 将任意长度输入压缩成固定 32 字节(256位)“指纹”,小改动引起大变化(雪崩效应)
- 只能检出"是否被改",不提供"是谁改的"
[消息 bytes] --(SHA-256)--> [32字节摘要]
动手
- 页面:Hash
- 输入(HEX):68656c6c6f(“hello”)
- 点击 Compute
- 期望输出(HEX):2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
消息认证码(MAC)
HMAC-SHA256
原理
- 基于哈希的认证码:证明"持有密钥且消息未改"
- 结构直觉:两层哈希,内层混入密钥(ipad),外层再混一次(opad)
tag = H( K ⊕ opad || H( K ⊕ ipad || msg ) )
动手
- 页面:MAC → HMAC-SHA256
- Key(HEX):0102030405060708090a0b0c0d0e0f1011121314
- Input(HEX):48656c6c6f(“Hello”)
- 点击 Compute
- 期望 Tag(HEX): 6a14dddf21c1cda3ed32da7461cecad54717d31dcfcdc9be4a11d25086df696f
AES-CMAC
原理
- 基于 AES 的消息认证码。先生成子密钥 K1/K2,对最后一个块做轻微"调整",再用 AES-CBC 的方式聚合得到标签
[msg] --(分块/填充)--> [M1..Mn]
last = (完整块? K1 : K2) ⊕ Mn
tag = AES-CBC-Encrypt(key, IV=0, M1..M{n-1}, last) 的最后 16 字节
动手
- 页面:MAC → AES-CMAC
- Key(HEX):2b7e151628aed2a6abf7158809cf4f3c
- Input(HEX):6bc1bee22e409f96e93d7e117393172a
- 点击 Compute
- 输出: 070a16b46b4d4144f79bdd9dd04a287c
对称与 AEAD
AES-GCM
原理
- 使用 CTR 方式加密 + GHASH 计算认证标签(tag)。nonce 必须 12 字节;同一密钥下绝不复用 nonce
密钥K, nonceN
C = CTR_Encrypt(K, N, P)
tag = GHASH(K, AAD, C)
输出 = C || tag
动手
- 页面:Symmetric → AES-GCM
- Input(HEX):00112233445566778899aabbccddeeff0001020304050607
- Key(HEX):000102030405060708090a0b0c0d0e0f
- Nonce(HEX):000102030405060708090a0b(12 字节)
- AAD(HEX,可选):0c0d0e0f101112131415161718191a1b
- 点击 Encrypt
- 输出(HEX,ciphertext||tag):
937d85fd224e9123c34bcb31fa7e9ef7b32718e557e8fbf14c987e199c7d4d165cb8826e52c2d1f0
ChaCha20-Poly1305
原理
- ChaCha20 负责加密(流密码),Poly1305 负责标签(认证)。key=32 字节,nonce=12 字节
C = ChaCha20_Encrypt(key, nonce, P)
tag = Poly1305(key', AAD || C)
输出 = C || tag
动手
- 页面:Symmetric → ChaCha20-Poly1305
- Input(HEX):0102030405060708
- Key(HEX):0000…00(32 字节全 00)
- Nonce(HEX):0000…00(12 字节全 00)
- 点击 Encrypt
- 输出(HEX,ciphertext||tag):9e05e4ba50573f7216b4569116f74ad2ff14a1f5698d0dda
AES-CCM
原理
- CCM = CTR 加密 + CBC-MAC 标签。协议常用,nonce 固定 13 字节,tag 可为 4/8/16 字节
tag = CBC-MAC(key, B0 || AAD' || PT')
C = CTR_Encrypt(key, nonce, P)
输出 = C || tag
动手
- 页面:Symmetric → AES-CCM
- Input(HEX):00112233445566778899aabbccddeeff
- Key(HEX):00000000000000000000000000000000
- Nonce(HEX):0f0e0d0c0b0a09080706050403(13 字节)
- AAD(HEX):aabbccdd
- Tag Length:8(即 64 bit)
- 点击 Encrypt
- 输出(HEX,ciphertext||tag): 0b351eb48bc68b348aca2cd428d4864dedec3573620d52d5
AES-CBC(PKCS7/NoPadding)
原理
- CBC 是分组链接加密:每块明文先与前一块密文异或再加密。默认 PKCS7 填充;NoPadding 需 16 字节对齐。CBC 本身不认证,推荐 AEAD
- AES 是分组密码,分组大小固定为 128 位(16 字节),所以需要填充或要求输入数据长度为 16 字节的整数倍
C1 = E( K, P1 ⊕ IV )
Ci = E( K, Pi ⊕ Ci-1 )
动手
- 页面:Symmetric → AES-CBC(默认 PKCS7)
- Input(HEX):00112233
- Key(HEX):000102030405060708090a0b0c0d0e0f
- IV(HEX):000102030405060708090a0b0c0d0e0f
- 点击 Encrypt
- 期望 bbd0ba9d822962f9d25c344801fe195d
动手
- 勾选 NoPadding;将输入改为 16 字节:
- Input(HEX):00112233445566778899aabbccddeeff
- 期望 76d0627da1d290436e21a4af7fca94b7
密钥派生(KDF)
HKDF-SHA256
原理
- HKDF = Extract + Expand:先"提纯"原始秘密(与盐混合),再按需求长度扩展,绑定 info 以区分用途
PRK = HMAC(salt, IKM)
OKM = HMAC(PRK, info || 0x01) || ... # 分段拼接至所需长度
动手
- 页面:KDF → HKDF-SHA256
- IKM(HEX):000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
- Salt(HEX):(留空)
- Info(HEX):(留空)
- Length:32
- 点击 Derive
- OKM(HEX): 37ad29109f43265287804b674e2653d0a513718907f97fca97c95bded8104bbf
PBKDF2-SHA256
原理
- 口令拉伸:多次迭代 HMAC,显著增加暴力破解成本。盐随机且不复用
DK = PBKDF2( password, salt, iterations, length )
动手
- 页面:KDF → PBKDF2-SHA256
- Password(HEX):70617373776f7264(“password”)
- Salt(HEX):73616c74(“salt”)
- Iterations:4096
- Length:32
- 点击 Derive
- DK(HEX): c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a
签名/验签
原理
- 用私钥签名、公钥验证。ECDSA(Elliptic Curve Digital Signature Algorithm) 输出 (r,s) 常见 DER/RAW 两种编码;Ed25519 接口更直接
sig = Sign(privateKey, H(message))
ok = Verify(publicKey, H(message), sig)
ECDSA-P256(DER/RAW)
原理
- 用私钥对消息做"不可否认"的认证;公钥验证。ECDSA 结果含两个大整数 r,s,常见两种编码:DER、RAW(r||s 64字节)
动手
页面:Sign/Verify → ECDSA-P256
Message(HEX):616263(“abc”)
Public Key(SPKI,HEX):
3059301306072a8648ce3d020106082a8648ce3d030107034200047a593180860c4037c83c12749845c8ee1424dd297fadcb895e358255d2c7d2b2a8ca25580f2626fe579062ff1b99ff91c24a0da06fb32b5be20148c9249f5650Sig Encoding:DER
Signature(HEX):
30440220334d7ae5ce7dfa1f69c24acd19601442bda82b4c3dd0a26890f0053066325f72022046cfb76d8f55b0da16e3f82f34ea7264abc85305333ce6db49f48e9c4587d3a9点击 Verify
Verify Result:成功
Ed25519
原理
- 现代曲线签名,接口直接、性能好。与 ECDSA 不同,无 DER/RAW 切换困扰
动手
- 页面:Sign/Verify → Ed25519
- Message(HEX):68656c6c6f(“hello”)
- Public Key(SPKI,HEX):
302a300506032b657003210003a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8 - Signature(HEX):
e1a7fca94a835127885b99e2eba733d6ee5bf5dc463ed8385eb6f1dcaa1117c0f151750a10f46f5b3796a91203578f702c85c67c334b5689a516284d499f710f - 点击 Verify
- Verify Result:成功
密钥交换
原理
- 双方各自使用"我的私钥 + 你的公钥"得到相同共享秘密;该秘密必须再经 HKDF(HMAC-based Key Derivation Function) 派生成会话密钥
S = ECDH(a_priv, b_pub) = ECDH(b_priv, a_pub)
或 S = X25519(a_priv, b_pub) = X25519(b_priv, a_pub)
ECDH-P256
原理
- A 用私钥、B 用公钥,各自独立计算同一个共享秘密。该秘密不直接用于加密,需 HKDF 派生成 AEAD 密钥
动手
- 页面:Key Exchange 页 → ECDH-P256
- A 私钥(PKCS8.DER):
308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420009f3d9f3d9f3d9f3d9f3d9f3d9f3d9f3d9f3d9f3d9f3d9f3d9f3d9f3d9f3d9fa1440342000408fb02eb998e991b5a615279ac576b5524fcd6b5a26e685aa0c96e88867625a59a106cd6a63087ff2a27c31c392647d18cc5fa8ba9f196e60a04eace8de6f38d - B 公钥(SPKI.DER):
3059301306072a8648ce3d020106082a8648ce3d030107034200045bc3633e112acf5d0abb90f486776ba3500c19b5d095d7ea7163c7846f61f10cce93315c6c3b4dbfee3557a6677f58721c14a18bafc1fe253678e32b7a8337bf - 点击 Derive
- Shared Secret(HEX): 22a91d018252d0169da3bcb269c2e3852f08b27d2ef5e6c27e4f2ecd4b8e7463
X25519
原理
- 现代密钥交换曲线,接口直接、性能好。与 ECDH 同理,输出共享秘密,需 HKDF→AEAD 才能加密
动手
- 页面:Key Exchange 页 → X25519
- A 私钥(PKCS8.DER):
302e020100300506032b656e04220420000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f - B 公钥(SPKI.DER):
302a300506032b656e03210087968c1c1642bd0600f6ad869b88f92c9623d0dfc44f01deffe21c9add3dca5f - 点击 Derive
- Shared Secret(HEX): dae0079aea6e6d02ca215a60d5d8f6689c3ed6009d41882b9181ff2481d9e27a
证书与密钥格式
X.509证书
- 证书是"公钥+身份+有效期+扩展"的载体(X.509 v3)
- 公钥通常放在 SPKI;私钥通常放在 PKCS8。编码可为 DER(二进制)或 PEM(文本)
[证书] = { 公钥(SPKI), 主题/颁发者, 有效期, 扩展, 签名 }
DER(字节) ⇄ PEM(文本包裹)
动手
页面:X.509
将下方 PEM 粘贴到输入区:
-----BEGIN CERTIFICATE----- MIICjTCCAjSgAwIBAgIUQ6eSZ5V2VDhwWNpPYbkmhbNO6JkwCgYIKoZIzj0EAwIw gYQxCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQHDAdCZWlq aW5nMQwwCgYDVQQKDANJb1QxDDAKBgNVBAsMA0RldjEUMBIGA1UEAwwLZXhhbXBs ZS5jb20xHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wHhcNMjUwODEw MTcwODE3WhcNMzUwODA4MTcwODE3WjCBhDELMAkGA1UEBhMCQ04xEDAOBgNVBAgM B0JlaWppbmcxEDAOBgNVBAcMB0JlaWppbmcxDDAKBgNVBAoMA0lvVDEMMAoGA1UE CwwDRGV2MRQwEgYDVQQDDAtleGFtcGxlLmNvbTEfMB0GCSqGSIb3DQEJARYQdGVz dEBleGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCE1SJx84gOs MdT3I7UGLlrKZpHSuRc2mnoeepHkWGfo72iiLr5DJoxCyJJrxsnNvYQEhBg6vsum JyHMX6mVylGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDAdBgNVHSUEFjAU BggrBgEFBQcDAQYIKwYBBQUHAwIwJwYDVR0RBCAwHoILZXhhbXBsZS5jb22CD3d3 dy5leGFtcGxlLmNvbTAdBgNVHQ4EFgQU8+X7PvzqGxEGxEaCcjN5Evp6NC0wCgYI KoZIzj0EAwIDRwAwRAIgO5/F8Mu2KSP3zzxhp6n9HgZT0LIvOjXbMILZF94arY0C IG8cF+T8wn1VyGgbwqFvFLy36qufJ2TgeL/l4mkrj9az -----END CERTIFICATE-----点击 Parse(解析)与 Convert(转换)
解析文本包含:Public-Key: (256 bit)、Subject/Issuer、Validity、扩展 OID 等
Convert 能在 PEM 与 DER-HEX 间互转
编码转换(Codec)
- 数据=字节;显示/交换需要编码。Hex/Base64 是字节到字符串的表示;PEM 是对 DER(二进制)的 Base64 外壳
bytes ⇄ hex / base64
DER(bytes) ⇄ PEM("-----BEGIN ..." + base64 + "-----END ...")
动手
- 页面:Codec
- 将 Base64 的 PKCS8/SPKI 转成 HEX 后再粘贴到其他页面使用
- 常用:Base64 → HEX;或 HEX → Base64
随机数(RNG)
- CSPRNG(密码学安全随机数)用于生成密钥/nonce/salt
- 长度要与用途匹配:密钥(16/24/32字节)、GCM/ChaCha20-Poly1305 nonce(12字节)、CCM nonce(13字节)
Random(n) → [n字节随机] → (key/nonce/salt)
动手
- 页面:Random
- 选择 16/32/64 字节;点击 Generate;根据需要在其他页面粘贴使用
术语表
| 缩略语 | 全称 | 说明 |
|---|---|---|
| AEAD | Authenticated Encryption with Associated Data | 带关联数据的认证加密,同时提供加密和认证 |
| MAC | Message Authentication Code | 消息认证码,用于验证消息完整性和真实性 |
| HMAC | Hash-based Message Authentication Code | 基于哈希的消息认证码 |
| KDF | Key Derivation Function | 密钥派生函数,从原始密钥材料生成工作密钥 |
| HKDF | HMAC-based Key Derivation Function | 基于HMAC的密钥派生函数 |
| PBKDF2 | Password-Based Key Derivation Function 2 | 基于密码的密钥派生函数版本2 |
| AES | Advanced Encryption Standard | 高级加密标准,对称加密算法 |
| GCM | Galois/Counter Mode | 伽罗瓦/计数器模式,AEAD的一种实现 |
| CCM | Counter with CBC-MAC | 使用CBC-MAC的计数器模式,另一种AEAD实现 |
| CBC | Cipher Block Chaining | 密码块链接模式,传统分组加密模式 |
| CTR | Counter Mode | 计数器模式,分组密码的一种工作模式 |
| GHASH | Galois Hash Function | 用于AES-GCM的哈希函数 |
| SHA | Secure Hash Algorithm | 安全哈希算法 |
| ECDSA | Elliptic Curve Digital Signature Algorithm | 椭圆曲线数字签名算法 |
| ECDH | Elliptic Curve Diffie-Hellman | 椭圆曲线迪菲-赫尔曼密钥交换 |
| SPKI | Subject Public Key Info | 主体公钥信息,公钥容器格式 |
| PKCS8 | Private-Key Information Syntax Standard | 私钥信息语法标准,私钥容器格式 |
| DER | Distinguished Encoding Rules | 区别编码规则,二进制编码格式 |
| PEM | Privacy-Enhanced Mail | 隐私增强邮件,基于Base64的文本编码格式 |
| RSA | Rivest-Shamir-Adleman | 一种公钥加密算法名称 |
| ChaCha20 | Chaotic Cipher 20 | 流加密算法 |
| Poly1305 | Polynomial Evaluation in a 1305-bit finite field | 一次性认证器,常与ChaCha20结合使用 |
| Ed25519 | Edwards Curve 25519 | 基于Edwards 25519曲线的签名算法 |
| X.509 | ITU-T standard | 公钥证书格式标准,一种数字证书格式 |
| X25519 | Edwards Curve 25519 | 基于Curve25519曲线的密钥交换算法 |
| CSPRNG | Cryptographically Secure Pseudo-Random Number Generator | 密码学安全伪随机数生成器 |
| MITM | Man-in-the-Middle | 中间人攻击,攻击者秘密中转通信双方的数据 |
