代码对比
/* 第一组:3行,显式设置两个哈希 */ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING); EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256()); // OAEP 哈希 = SHA-256 EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256()); // MGF1 哈希 = SHA-256 ← 多了这行 /* 第二组:2行,只设置 OAEP 哈希 */ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING); EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256()); // OAEP 哈希 = SHA-256 // MGF1 哈希 = ???(未显式设置)RSA OAEP 的两个哈希算法
OAEP 编码结构: ┌─────────────────────────────────────────────────────┐ │ Hash(L) │ PS(全零) │ 0x01 │ M(消息) │ ← 用 oaep_md 计算 Hash(L) │ (hLen) │ │ │ │ ├─────────────────────────────────────────────────────┤ │ DB = Hash(L) || PS || 0x01 || M │ │ maskedDB = DB XOR MGF(seed, mLen) │ ← 用 mgf1_md 计算 MGF │ maskedSeed = seed XOR MGF(maskedDB, hLen) │ ← 用 mgf1_md 计算 MGF └─────────────────────────────────────────────────────┘第二组代码的 MGF1 哈希到底是什么?
OpenSSL 版本 | 只设 oaep_md=SHA-256 时,mgf1_md 的值 |
1.0.2 及更早 | 保持默认SHA-1(不跟随 oaep_md) |
1.1.0 / 1.1.1 | 保持默认SHA-1(不跟随 oaep_md) |
3.0+ | 文档说"通常跟随 oaep_md",但不保证,建议显式设置 |
/* 第二组代码实际效果(OpenSSL 1.1.x): oaep_md = SHA-256 (设置的) mgf1_md = SHA-1 (默认值,你没设置) */实际影响:跨平台解密失败
场景1:和对端都用第一组代码(显式 SHA-256 + SHA-256)
场景2:加密端用第一组,解密端用第二组(OpenSSL 1.1.x)
场景3:和 Java / Python / 嵌入式设备交互
语言/平台 | OAEP 默认配置 | 注意事项 |
Java JCE | OAEPWithSHA-256AndMGF1Padding→ oaep=SHA-256, mgf1=SHA-1(!) | Java 的 MGF1 默认是 SHA-1,必须用 OAEPParameterSpec 显式指定 MGF1=SHA-256 |
Python cryptography | OAEP(mgf=MGF1(algorithm=SHA256()),algorithm=SHA256()) | 必须显式指定两者 |
嵌入式 mbedTLS | MBEDTLS_RSA_PKCS_V21+ hash_id | 两个哈希通常绑定为同一个 |
OpenSSL 命令行 | openssl pkeyutl -encrypt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 | 必须两个都指定 |
OAEPParameterSpec spec = new OAEPParameterSpec( "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, // ← 必须显式指定 MGF1=SHA-256 PSource.PSpecified.DEFAULT );为什么第一组是最佳实践
1. 行为确定,不依赖 OpenSSL 版本
2. 跨平台兼容性可控
3. 安全强度一致
4. 审计友好
pos项目中的建议
涉及 RSA 的场景(TR-34 远程密钥加载、脱机 PIN 加密等),统一用第一组写法:
/*RSA OAEP 标准配置 */ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING); EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256()); EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256()); // 必须显式设置- 所有 RSA 加密/解密都用 OAEP(禁止 PKCS#1 v1.5)
- oaep_md 和 mgf1_md 都显式设置为 SHA-256
- 和对端(银联/TMS/密钥注入系统)确认双方配置一致
- Java 端用 OAEPParameterSpec 显式指定 MGF1=SHA-256
- 密钥长度 ≥2048-bit(PCI PTS v7.0 建议 3072-bit 或 ECC P-256)
总结
对比项 | 第一组(3行) | 第二组(2行) |
OAEP 哈希 | SHA-256(显式) | SHA-256(显式) |
MGF1 哈希 | SHA-256(显式) | 取决于 OpenSSL 版本,通常是 SHA-1 |
行为确定性 | 跨版本一致 | 依赖默认值 |
跨平台兼容 | 可控 | 容易和 Java/Python 不匹配 |
安全强度 | 全 SHA-256 | MGF1 可能是 SHA-1 |
PCI PTS v7.0 | 合规 | 可能不合规(SHA-1) |
推荐度 | 推荐 | 不推荐 |