继续之前章节的内容,这里说一下RSA
RSA部分:
BCrypt导出密钥的内存BLOB结构有三种:BCRYPT_RSAFULLPRIVATE_BLOB、BCRYPT_RSAPRIVATE_BLOB和BCRYPT_RSAPUBLIC_BLOB
简单理解为BCRYPT_RSAFULLPRIVATE_BLOB同时包含公钥和私钥
即RSA的:
e = 公钥指数
d = 私钥指数
n = 模数
p = 质因子
q = 质因子
dmp1 = d mod (p-1)
dmq1 = d mod (q-1)
iqmp = q^-1 mod p
其中,公钥指数e一般为0x3L或者0x10001L(65537),CNG和OpenSSL一般使用65537
不论是BCRYPT_RSAFULLPRIVATE_BLOB、BCRYPT_RSAPRIVATE_BLOB还是BCRYPT_RSAPUBLIC_BLOB都包含一个BCRYPT_RSAKEY_BLOB结构的文件头
typedef struct _BCRYPT_RSAKEY_BLOB {
ULONG Magic;
ULONG BitLength;
ULONG cbPublicExp;
ULONG cbModulus;
ULONG cbPrime1;
ULONG cbPrime2;
} BCRYPT_RSAKEY_BLOB;
Magic 指定此 BLOB 表示的 RSA 密钥的类型。 这可以是以下值之一。
BCRYPT_RSAPUBLIC_MAGIC 密钥是 RSA 公钥。
BCRYPT_RSAPRIVATE_MAGIC 密钥是 RSA 私钥。
BCRYPT_RSAFULLPRIVATE_MAGIC 密钥是完整的 RSA 私钥。
BitLength 密钥的大小(以位为单位)。
cbPublicExp 键指数(e)的大小(以字节为单位)。 截至 1903 Windows 10 版本,不再支持大于 (2^64 - 1) 的公共指数。
cbModulus 键的模数(n)的大小(以字节为单位)。
cbPrime1 键的第一个质数(p)的大小(以字节为单位)。 这仅用于私钥 BLOB。
cbPrime2 键的第二个质数(q)的大小(以字节为单位)。 这仅用于私钥 BLOB。
RSA 公钥 BLOB(BCRYPT_RSAPUBLIC_BLOB )在连续内存中采用以下格式。 结构后面的所有数字都采用大端格式。
BCRYPT_RSAKEY_BLOB
PublicExponent[cbPublicExp] // Big-endian.
Modulus[cbModulus] // Big-endian.
RSA 私钥 BLOB (BCRYPT_RSAPRIVATE_BLOB) 在连续内存中采用以下格式。 结构后面的所有数字都采用大端格式。
BCRYPT_RSAKEY_BLOB
PublicExponent[cbPublicExp] // Big-endian.
Modulus[cbModulus] // Big-endian.
Prime1[cbPrime1] // Big-endian.
Prime2[cbPrime2] // Big-endian.
完整的 RSA 私钥 BLOB (BCRYPT_RSAFULLPRIVATE_BLOB) 在连续内存中采用以下格式。 结构后面的所有数字都采用大端格式。
BCRYPT_RSAKEY_BLOB
PublicExponent[cbPublicExp] // Big-endian.-- e
Modulus[cbModulus] // Big-endian.-- n
Prime1[cbPrime1] // Big-endian.-- p
Prime2[cbPrime2] // Big-endian.-- q
Exponent1[cbPrime1] // Big-endian.-- d mod (p-1)
Exponent2[cbPrime2] // Big-endian.-- d mod (q-1)
Coefficient[cbPrime1] // Big-endian.-- (inverse of q) mod p //q模p的乘法逆元即qInv *q = 1 (mod p)
PrivateExponent[cbModulus] // Big-endian.-- d
MSDN中明确说明PrivateExponent根据不同系统版本等效数学模型,其计算公式是不同的可能是modulo (Prime1 - 1) * (Prime2 - 1) ,或者 modulo LeastCommonMultiple (Prime1 - 1, Prime2 - 1),额外说一句两个公式的计算结果所得的PrivateExponent可能相同,也可能不同,如果两种不同的话,后者modulo LeastCommonMultiple (Prime1 - 1, Prime2 - 1)的结果会比前者modulo (Prime1 - 1) * (Prime2 - 1) 的结果来的小(位数),相对使用时,速度会更快一些
OpenSSL中关于RSA的定义(仅供参考,OpenSSL后续版本内部实现可能会有变化)
typedef struct rsa_st {
// RSA 公钥部分
BIGNUM *n; // 模数 (modulus)
BIGNUM *e; // 公共指数 (public exponent)
// RSA 私钥部分
BIGNUM *d; // 私有指数 (private exponent)
BIGNUM *p; // 第一个大素数 (prime1)
BIGNUM *q; // 第二个大素数 (prime2)
// 预计算值,用于加快密钥运算速度
BIGNUM *dmp1; // d 对 (p-1) 求模 (d mod (p-1))
BIGNUM *dmq1; // d 对 (q-1) 求模 (d mod (q-1))
BIGNUM *iqmp; // q 对 p 的模反元素 (q^(-1) mod p)
// 私有成员 (不建议直接访问)
CRYPTO_EX_DATA ex_da

本文详细介绍了RSA密钥在MicrosoftCNG(CryptoAPINextGeneration)与OpenSSL之间的转换过程,包括公钥和私钥的结构、转换方法以及涉及到的数学计算。转换过程中特别提到了大端到本机字节序的转换和不同系统版本下私钥指数的计算差异。
最低0.47元/天 解锁文章
1012

被折叠的 条评论
为什么被折叠?



