4.12 非对称算法实现:RSA与ECDSA的密码引擎
非对称算法家族
SoftHSM2支持的非对称算法:
非对称算法家族:
AsymmetricAlgorithm(抽象基类)
│
├── RSA
│ ├── BotanRSA (Botan实现)
│ └── OSSLRSA (OpenSSL实现)
│ └── 支持机制:PKCS, OAEP, PSS
│ └── 密钥长度:1024-4096位
│
├── DSA
│ ├── BotanDSA (Botan实现)
│ └── OSSLDSA (OpenSSL实现)
│ └── 支持机制:DSA签名
│ └── 密钥长度:1024-3072位
│
├── ECDSA
│ ├── BotanECDSA (Botan实现)
│ └── OSSLECDSA (OpenSSL实现)
│ └── 支持曲线:P-256, P-384, P-521
│ └── 密钥长度:曲线决定
│
├── ECDH
│ ├── BotanECDH (Botan实现)
│ └── OSSLECDH (OpenSSL实现)
│ └── 密钥派生:ECDH
│
├── EdDSA
│ ├── BotanEDDSA
│ └── OSSLEDDSA
│ └── 支持曲线:Ed25519, Ed448
│
└── DH
├── BotanDH
└── OSSLDH
└── 密钥长度:1024-8192位
AsymmetricAlgorithm抽象类
AsymmetricAlgorithm定义了非对称加密的通用接口:
struct AsymAlgo
{
enum Type
{
Unknown,
RSA,
DSA,
DH,
ECDH,
ECDSA,
GOST,
EDDSA,
MLDSA
};
};
struct AsymMech
{
enum Type
{
Unknown,
RSA,
RSA_MD5_PKCS,
RSA_PKCS,
RSA_PKCS_OAEP,
RSA_SHA1_PKCS,
RSA_SHA224_PKCS,
RSA_SHA256_PKCS,
RSA_SHA384_PKCS,
RSA_SHA512_PKCS,
RSA_PKCS_PSS,
RSA_SHA1_PKCS_PSS,
RSA_SHA224_PKCS_PSS,
RSA_SHA256_PKCS_PSS,
RSA_SHA384_PKCS_PSS,
RSA_SHA512_PKCS_PSS,
RSA_SSL,
DSA,
DSA_SHA1,
ECDSA,
ECDSA_SHA1,
ECDSA_SHA224,
ECDSA_SHA256,
ECDSA_SHA384,
ECDSA_SHA512,
EDDSA,
MLDSA
};
};
class AsymmetricAlgorithm
{
public:
AsymmetricAlgorithm();
virtual ~AsymmetricAlgorithm() { }
// 签名函数
virtual bool sign(PrivateKey* privateKey,
const ByteString& dataToSign,
ByteString& signature,
const AsymMech::Type mechanism,
const void* param = NULL,
const size_t paramLen = 0);
virtual bool signInit(PrivateKey* privateKey,
const AsymMech::Type mechanism,
const void* param = NULL,
const size_t paramLen = 0);
virtual bool signUpdate(const ByteString& dataToSign);
virtual bool signFinal(ByteString& signature);
// 验证函数
virtual bool verify(PublicKey* publicKey,
const ByteString& originalData,
const ByteString& signature,
const AsymMech::Type mechanism,
const void* param = NULL,
const size_t paramLen = 0);
virtual bool verifyInit(PublicKey* publicKey,
const AsymMech::Type mechanism,
const void* param = NULL,
const size_t paramLen = 0);
virtual bool verifyUpdate(const ByteString& originalData);
virtual bool verifyFinal(const ByteString& signature);
// 加密函数
virtual bool encrypt(PublicKey* publicKey,
const ByteString& data,
ByteString& encryptedData,
const AsymMech::Type padding) = 0;
// 解密函数
virtual bool decrypt(PrivateKey* privateKey,
const ByteString& encryptedData,
ByteString& data,
const AsymMech::Type padding) = 0;
// 密钥生成
virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair,
AsymmetricParameters* parameters,
RNG* rng = NULL) = 0;
// 密钥派生(ECDH)
virtual bool deriveKey(SymmetricKey **ppSymmetricKey,
PublicKey* publicKey,
PrivateKey* privateKey);
// 密钥重构
virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair,
ByteString& serialisedData) = 0;
virtual bool reconstructPublicKey(PublicKey** ppPublicKey,
ByteString& serialisedData) = 0;
virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey,
ByteString& serialisedData) = 0;
// 密钥工厂
virtual PublicKey* newPublicKey() = 0;
virtual PrivateKey* newPrivateKey() = 0;
protected:
PublicKey* currentPublicKey;
PrivateKey* currentPrivateKey;
AsymMech::Type currentMechanism;
};
RSA机制详解
RSA签名机制:
RSA签名机制:
RSA_PKCS(裸RSA签名)
┌─────────────────────────────────────┐
│ PKCS#1 v1.5 签名 │
│ │
│ 数据 → 填充 → RSA私钥运算 → 签名 │
│ │
│ 填充格式: │
│ 0x00 0x01 [0xFF...] 0x00 [数据] │
└─────────────────────────────────────┘
RSA_SHA256_PKCS(带Hash的签名)
┌─────────────────────────────────────┐
│ │
│ 数据 → SHA256 Hash → PKCS#1 填充 │
│ → RSA私钥运算 → 签名 │
│ │
│ 签名格式: │
│ 0x00 0x01 [0xFF...] 0x00 │
│ [SHA256 AlgorithmID] [Hash值] │
└─────────────────────────────────────┘
RSA_PKCS_PSS(PSS签名)
┌─────────────────────────────────────┐
│ │
│ 数据 → Hash → MGF1填充 │
│ → RSA私钥运算 → 签名 │
│ │
│ 需要参数: │
│ ├── hashAlg: Hash算法 │
│ ├── mgf: MGF函数 │
│ └── sLen: Salt长度 │
└─────────────────────────────────────┘
RSA加密机制:
RSA加密机制:
RSA_PKCS(PKCS#1 v1.5加密)
┌─────────────────────────────────────┐
│ │
│ 数据 → PKCS#1填充 → RSA公钥运算 │
│ → 密文 │
│ │
│ 填充格式: │
│ 0x00 0x02 [随机字节...] 0x00 [数据] │
└─────────────────────────────────────┘
RSA_PKCS_OAEP(OAEP加密)
┌─────────────────────────────────────┐
│ │
│ 数据 → OAEP填充 → RSA公钥运算 │
│ → 密文 │
│ │
│ OAEP填充: │
│ ├── MGF1掩码 │
│ ├── Hash算法 │
│ ├── 可选Label │
└─────────────────────────────────────┘
RSAPublicKey与RSAPrivateKey
RSA密钥的组成:
class RSAPublicKey : public PublicKey
{
public:
static const char* type;
virtual bool isOfType(const char* inType);
virtual unsigned long getBitLength() const;
virtual unsigned long getOutputLength() const;
virtual void setN(const ByteString& inN); // 模数
virtual void setE(const ByteString& inE); // 公钥指数
virtual const ByteString& getN() const;
virtual const ByteString& getE() const;
virtual ByteString serialise() const;
virtual bool deserialise(ByteString& serialised);
protected:
ByteString n; // 模数 N
ByteString e; // 公钥指数 E(通常为65537)
};
class RSAPrivateKey : public PrivateKey
{
public:
static const char* type;
virtual bool isOfType(const char* inType);
virtual unsigned long getBitLength() const;
virtual unsigned long getOutputLength() const;
// CRT参数
virtual void setP(const ByteString& inP); // 素数P
virtual void setQ(const ByteString& inQ); // 素数Q
virtual void setPQ(const ByteString& inPQ); // CRT系数 qInv = q⁻¹ mod p
virtual void setDP1(const ByteString& inDP1); // D mod P-1
virtual void setDQ1(const ByteString& inDQ1); // D mod Q-1
// 基本参数
virtual void setD(const ByteString& inD); // 私钥指数D
virtual void setN(const ByteString& inN); // 模数N
virtual void setE(const ByteString& inE); // 公钥指数E
virtual const ByteString& getP() const;
virtual const ByteString& getQ() const;
virtual const ByteString& getPQ() const;
virtual const ByteString& getDP1() const;
virtual const ByteString& getDQ1() const;
virtual const ByteString& getD() const;
virtual const ByteString& getN() const;
virtual const ByteString& getE() const;
virtual ByteString PKCS8Encode();
virtual bool PKCS8Decode(const ByteString& ber);
protected:
ByteString p, q, pq, dp1, dq1, d; // 私钥组件
ByteString n, e; // 公钥组件
};
RSA密钥结构:
RSA密钥数学关系:
公钥:
├── N = P * Q(模数)
├── E = 公钥指数(通常65537)
│
私钥(基本形式):
├── D = E^(-1) mod (P-1)(Q-1)
│
私钥(CRT加速形式):
├── P, Q(素数)
├── dP = D mod (P-1)
├── dQ = D mod (Q-1)
├── qInv = Q^(-1) mod P
│
签名计算:
├── 基本形式:S = M^D mod N
├── CRT加速:
│ ├── S1 = M^dP mod P
│ ├── S2 = M^dQ mod Q
│ ├── S = S2 + qInv*(S1-S2) mod N
OSSLRSA实现
OSSLRSA使用OpenSSL EVP API:
class OSSLRSA : public AsymmetricAlgorithm
{
public:
OSSLRSA();
virtual ~OSSLRSA();
virtual bool sign(PrivateKey* privateKey,
const ByteString& dataToSign,
ByteString& signature,
const AsymMech::Type mechanism,
const void* param = NULL,
const size_t paramLen = 0);
virtual bool encrypt(PublicKey* publicKey,
const ByteString& data,
ByteString& encryptedData,
const AsymMech::Type padding);
virtual bool decrypt(PrivateKey* privateKey,
const ByteString& encryptedData,
ByteString& data,
const AsymMech::Type padding);
virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair,
AsymmetricParameters* parameters,
RNG* rng = NULL);
virtual PublicKey* newPublicKey();
virtual PrivateKey* newPrivateKey();
private:
HashAlgorithm* pCurrentHash;
HashAlgorithm* pSecondHash;
size_t sLen; // PSS Salt长度
};
bool OSSLRSA::sign(PrivateKey* privateKey,
const ByteString& dataToSign,
ByteString& signature,
const AsymMech::Type mechanism,
const void* param,
const size_t paramLen)
{
// 创建RSA密钥对象
RSA* rsa = RSA_new();
RSAPrivateKey* rsaKey = (RSAPrivateKey*)privateKey;
// 设置密钥参数
BIGNUM* n = BN_bin2bn(rsaKey->getN().byte_str(), rsaKey->getN().size(), NULL);
BIGNUM* e = BN_bin2bn(rsaKey->getE().byte_str(), rsaKey->getE().size(), NULL);
BIGNUM* d = BN_bin2bn(rsaKey->getD().byte_str(), rsaKey->getD().size(), NULL);
RSA_set0_key(rsa, n, e, d);
// 设置CRT参数(如果可用)
if (rsaKey->getP().size() > 0) {
BIGNUM* p = BN_bin2bn(rsaKey->getP().byte_str(), rsaKey->getP().size(), NULL);
BIGNUM* q = BN_bin2bn(rsaKey->getQ().byte_str(), rsaKey->getQ().size(), NULL);
RSA_set0_factors(rsa, p, q);
BIGNUM* dp = BN_bin2bn(rsaKey->getDP1().byte_str(), rsaKey->getDP1().size(), NULL);
BIGNUM* dq = BN_bin2bn(rsaKey->getDQ1().byte_str(), rsaKey->getDQ1().size(), NULL);
BIGNUM* qInv = BN_bin2bn(rsaKey->getPQ().byte_str(), rsaKey->getPQ().size(), NULL);
RSA_set0_crt_params(rsa, dp, dq, qInv);
}
// 根据机制选择签名方式
switch (mechanism) {
case AsymMech::RSA_PKCS:
{
int sigLen = RSA_size(rsa);
unsigned char* sigBuf = new unsigned char[sigLen];
int ret = RSA_private_encrypt(dataToSign.size(), dataToSign.byte_str(),
sigBuf, rsa, RSA_PKCS1_PADDING);
if (ret > 0) {
signature = ByteString(sigBuf, ret);
}
delete[] sigBuf;
RSA_free(rsa);
return (ret > 0);
}
case AsymMech::RSA_SHA256_PKCS:
{
ByteString hash;
computeHash(dataToSign, hash, EVP_sha256());
int sigLen = RSA_size(rsa);
unsigned char* sigBuf = new unsigned char[sigLen];
int ret = RSA_sign(NID_sha256WithRSAEncryption,
hash.byte_str(), hash.size(),
sigBuf, &sigLen, rsa);
if (ret == 1) {
signature = ByteString(sigBuf, sigLen);
}
delete[] sigBuf;
RSA_free(rsa);
return (ret == 1);
}
case AsymMech::RSA_SHA256_PKCS_PSS:
{
int sigLen = RSA_size(rsa);
unsigned char* sigBuf = new unsigned char[sigLen];
ByteString hash;
computeHash(dataToSign, hash, EVP_sha256());
RSA_padding_add_PKCS1_PSS(rsa, sigBuf, hash.byte_str(), EVP_sha256(), -1);
int ret = RSA_private_encrypt(RSA_size(rsa), sigBuf, sigBuf, rsa, RSA_NO_PADDING);
if (ret > 0) {
signature = ByteString(sigBuf, ret);
}
delete[] sigBuf;
RSA_free(rsa);
return (ret > 0);
}
default:
RSA_free(rsa);
return false;
}
```cpp
bool OSSLRSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair,
AsymmetricParameters* parameters,
RNG* rng)
{
RSAParameters* rsaParams = (RSAParameters*)parameters;
size_t bits = rsaParams->getBitLength();
// 生成RSA密钥
RSA* rsa = RSA_new();
BIGNUM* e = BN_new();
BN_set_word(e, RSA_F4); // 65537
int ret = RSA_generate_key_ex(rsa, bits, e, NULL);
if (ret != 1) {
RSA_free(rsa);
BN_free(e);
return false;
}
// 提取公钥参数
const BIGNUM* n, *e_out;
RSA_get0_key(rsa, &n, &e_out, NULL);
RSAPublicKey* publicKey = new RSAPublicKey();
ByteString nBytes(BN_num_bytes(n));
BN_bn2bin(n, nBytes.byte_str());
publicKey->setN(nBytes);
ByteString eBytes(BN_num_bytes(e_out));
BN_bn2bin(e_out, eBytes.byte_str());
publicKey->setE(eBytes);
// 提取私钥参数
const BIGNUM* d, *p, *q, *dp, *dq, *pq;
RSA_get0_key(rsa, NULL, NULL, &d);
RSA_get0_crt_params(rsa, &dp, &dq, &pq);
RSA_get0_factors(rsa, &p, &q);
RSAPrivateKey* privateKey = new RSAPrivateKey();
ByteString dBytes(BN_num_bytes(d));
BN_bn2bin(d, dBytes.byte_str());
privateKey->setD(dBytes);
// ... 设置其他CRT参数
privateKey->setN(nBytes);
privateKey->setE(eBytes);
// 创建密钥对
*ppKeyPair = new RSAKeyPair(publicKey, privateKey);
RSA_free(rsa);
BN_free(e);
return true;
}
ECDSA实现
ECDSA使用椭圆曲线签名:
class ECPublicKey : public PublicKey
{
public:
virtual void setEC(const ByteString& inEC); // 曲线参数
virtual void setQ(const ByteString& inQ); // 公钥点Q
virtual const ByteString& getEC() const;
virtual const ByteString& getQ() const;
protected:
ByteString ec; // 曲线OID或参数
ByteString q; // 公钥点(压缩或非压缩格式)
};
class ECPrivateKey : public PrivateKey
{
public:
virtual void setEC(const ByteString& inEC); // 曲线参数
virtual void setD(const ByteString& inD); // 私钥值d
virtual const ByteString& getEC() const;
virtual const ByteString& getD() const;
protected:
ByteString ec; // 曲线OID
ByteString d; // 私钥值(大整数)
};
ECDSA签名结构:
ECDSA签名结构:
签名 (r, s):
├── r = x坐标 mod n
├── s = k^(-1)(z + r*d) mod n
│
其中:
├── k:随机数
├── z:消息Hash值
├── d:私钥
├── n:曲线阶数
│
签名格式(DER编码):
0x30 [长度]
0x02 [长度] [r]
0x02 [长度] [s]
BotanRSA实现
BotanRSA使用Botan C++ API:
class BotanRSA : public AsymmetricAlgorithm
{
public:
virtual bool sign(PrivateKey* privateKey,
const ByteString& dataToSign,
ByteString& signature,
const AsymMech::Type mechanism);
virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair,
AsymmetricParameters* parameters,
RNG* rng);
};
bool BotanRSA::sign(PrivateKey* privateKey,
const ByteString& dataToSign,
ByteString& signature,
const AsymMech::Type mechanism)
{
// 创建Botan RSA私钥
RSAPrivateKey* rsaKey = (RSAPrivateKey*)privateKey;
Botan::BigInt n(rsaKey->getN().byte_str(), rsaKey->getN().size());
Botan::BigInt e(rsaKey->getE().byte_str(), rsaKey->getE().size());
Botan::BigInt d(rsaKey->getD().byte_str(), rsaKey->getD().size());
Botan::RSA_PrivateKey botanKey(n, e, d);
// 根据机制选择签名方式
std::string padding;
switch (mechanism) {
case AsymMech::RSA_SHA256_PKCS:
padding = "PKCS1v15(SHA-256)";
break;
case AsymMech::RSA_SHA256_PKCS_PSS:
padding = "PSSR(SHA-256,MGF1,32)";
break;
default:
return false;
}
// 创建签名对象
Botan::PK_Signer signer(botanKey, padding, Botan::IEEE_1363);
// 执行签名
Botan::SecureVector<Botan::byte> sig = signer.sign_message(
dataToSign.byte_str(),
dataToSign.size(),
*rng);
signature = ByteString(sig.begin(), sig.size());
return true;
}
ECDH密钥派生
ECDH用于密钥协商:
bool BotanECDH::deriveKey(SymmetricKey** ppSymmetricKey,
PublicKey* publicKey,
PrivateKey* privateKey)
{
ECPublicKey* ecPub = (ECPublicKey*)publicKey;
ECPrivateKey* ecPriv = (ECPrivateKey*)privateKey;
// 创建Botan ECDH密钥
Botan::ECDH_PrivateKey privKey;
// ... 从ecPriv初始化
Botan::ECDH_PublicKey pubKey;
// ... 从ecPub初始化
// 执行密钥派生
Botan::PK_Key_Agreement ka(privKey, "Raw");
Botan::SecureVector<Botan::byte> sharedKey = ka.derive_key(
32, // 密钥长度
pubKey.public_value());
// 创建对称密钥
SymmetricKey* symKey = new AESKey(256);
symKey->setKeyBits(ByteString(sharedKey.begin(), sharedKey.size()));
*ppSymmetricKey = symKey;
return true;
}
ECDH密钥派生流程:
ECDH密钥派生流程:
Alice Bob
│ │
│ 私钥 d_A │ 私钥 d_B
│ 公钥 Q_A = d_A * G │ 公钥 Q_B = d_B * G
│ │
│ 发送 Q_A ────────────────────────→│
│ │
│←───────────────────────────────── Q_B
│ │
│ 计算: │ 计算:
│ K_A = d_A * Q_B │ K_B = d_B * Q_A
│ = d_A * d_B * G │ = d_B * d_A * G
│ │
│ K_A == K_B(共享密钥)
│
│ KDF(K_A) → AES密钥
非对称加密完整流程
非对称加密完整流程:
C_GenerateKeyPair
│
│ CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA)
│ algo->generateKeyPair(&keyPair, params, rng)
▼
密钥对创建(RSAKeyPair对象)
│
│ C_SignInit
│ CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA)
│ algo->signInit(privateKey, mechanism)
▼
签名初始化
│
│ C_Sign
│ algo->sign(privateKey, data, signature, mechanism)
▼
签名完成
│
│ CryptoFactory::i()->recycleAsymmetricAlgorithm(algo)
▼
回收算法实例
C_Encrypt
│
│ algo->encrypt(publicKey, data, encrypted, padding)
▼
加密完成
一个类比:保险箱的物理钥匙
保险箱物理钥匙类比:
RSA密钥(物理钥匙)
│
├── 公钥(锁的图纸)
│ ├── N:锁芯规格
│ ├── E:开锁规则
│ │
│ ├── 可公开分发
│ ├── 用于验证签名(检查锁)
│ └── 用于加密(设计新锁)
│
├── 私钥(物理钥匙)
│ ├── P, Q:钥匙齿形状
│ ├── D:钥匙转动角度
│ │
│ ├── 保密存储
│ ├── 用于签名(盖章)
│ └── 用于解密(开锁)
│
├── 签名机制(盖章方式)
│ │
│ ├── PKCS#1 v1.5(普通盖章)
│ │ ├── 盖章后附上数据
│ │ ├── 固定格式
│ │
│ ├── RSA-PSS(防伪盖章)
│ │ ├── 加随机Salt
│ │ ├── 防伪造攻击
│ │ ├── 更安全
│
└── 加密机制(锁设计)
│
├── PKCS#1 v1.5(普通锁)
│ ├── 随机填充
│ ├── 可能被攻击
│
├── RSA-OAEP(防破解锁)
│ ├── MGF掩码
│ ├── Hash校验
│ ├── 更安全
本篇小结
今天我们分析了SoftHSM2的非对称算法实现。
AsymmetricAlgorithm抽象类:
- sign/verify:签名验证
- encrypt/decrypt:加密解密
- generateKeyPair:密钥生成
- deriveKey:密钥派生
RSA机制:
- RSA_PKCS:裸RSA签名
- RSA_SHA256_PKCS:带Hash签名
- RSA_PKCS_PSS:PSS签名
- RSA_PKCS_OAEP:OAEP加密
RSA密钥:
- 公钥:N(模数)、E(公钥指数)
- 私钥:P、Q、D、CRT参数
ECDSA:
- 公钥:曲线EC、公钥点Q
- 私钥:曲线EC、私钥值D
- 签名:(r, s) DER编码
ECDH:
- 交换公钥
- 计算共享密钥
- KDF派生对称密钥
OpenSSL实现:
- RSA_sign/RSA_verify
- EVP_PKEY API
- BIGNUM处理大整数
Botan实现:
- PK_Signer/PK_Verifier
- C++原生API
- BigInt类
下一节,我们将分析哈希与MAC实现——SHA-256、HMAC如何工作。
【下集预告】
哈希算法如何实现?
SHA-256计算过程?
HMAC如何使用密钥?
CMAC如何工作?
下一节,哈希与MAC实现。