为什么gcrypt会在从SSL格式转换为gcrypt时重新计算RSA密钥的系数?

为什么gcrypt会在从SSL格式转换为gcrypt时重新计算RSA密钥的系数?

问题描述:

为libgcrypt文档说:为什么gcrypt会在从SSL格式转换为gcrypt时重新计算RSA密钥的系数?

An RSA private key is described by this S-expression: 

(private-key 
    (rsa 
    (n n-mpi) 
    (e e-mpi) 
    (d d-mpi) 
    (p p-mpi) 
    (q q-mpi) 
    (u u-mpi))) 

......还有......

p-mpi 
    RSA secret prime p. 
q-mpi 
    RSA secret prime q with p < q. 
u-mpi 
    Multiplicative inverse u = p^{-1} mod q. 

......还有......

Note that OpenSSL uses slighly different parameters: q < p and u = q^{-1} mod p. 
To use these parameters you will need to swap the values and recompute u. 
Here is example code to do this: 

    if (gcry_mpi_cmp (p, q) > 0) 
    { 
     gcry_mpi_swap (p, q); 
     gcry_mpi_invm (u, p, q); 
    } 

如果一个p越小素数和其他q是较小的素数,并且考虑到除了交换p和q之外,两个方程是相同的,是否真的有必要重新计算u?仅仅交换p和q是不够的?

作为一个方面的问题,我很好奇,为什么gcrypt不使用相同的值作为PKCS#1编码:

 RSAPrivateKey ::= SEQUENCE { 
     version   Version, 
     modulus   INTEGER, -- n 
     publicExponent INTEGER, -- e 
     privateExponent INTEGER, -- d 
     prime1   INTEGER, -- p 
     prime2   INTEGER, -- q 
     exponent1   INTEGER, -- d mod (p-1) 
     exponent2   INTEGER, -- d mod (q-1) 
     coefficient  INTEGER, -- (inverse of q) mod p 
     otherPrimeInfos OtherPrimeInfos OPTIONAL 
    } 

o modulus is the RSA modulus n. 
o publicExponent is the RSA public exponent e. 
o privateExponent is the RSA private exponent d. 
o prime1 is the prime factor p of n. 
o prime2 is the prime factor q of n. 
o exponent1 is d mod (p - 1). 
o exponent2 is d mod (q - 1). 
o coefficient is the CRT coefficient q^(-1) mod p. 
+0

这难道不是您可以通过简单的实验轻松发现的东西吗? –

+0

是的。我做到了。我不知道文件为什么要重新计算“u”。我只是在sexp中将p用作q的值,反之亦然,并且它工作正常......除了偶尔我会在解密的内容之前得到一个空字节。 – AlastairG

答案是重新计算“U”是无关紧要的。只需交换“p”和“q”的用法,它就可以工作。

作为对gcrypt的一般性评论,非对称密码API非常糟糕。真的很糟糕。

  • 不支持从任何格式的文件加载密钥。

  • 没有简单地加密/解密缓冲区的支持。相反,您需要先将缓冲区转换为MPI,然后才能将其转换为S表达式。加密后,您需要展开结果S表达式以获取正确的片段,然后调用另一个函数来获取数据本身。解密需要稍微更复杂一点的创建S表达式来从缓冲区解密,但检索数据只是一个函数调用。

  • 私钥的S表达式的参数与标准PKCS#1格式的值不匹配(尽管如本问答涵盖的那样,转换相当简单)。为什么不?

在调查过程中,我发现还有另一个GNU加密库。为什么他们保持两个我不知道。另一个被称为“荨麻”,好得多:

*)它使用GMP库作为多精度整数,而不是像gcrypt那样有自己的类型(mpi_t)。它支持从各种格式的文件加载密钥(我用它作为我自己的代码的基础来加载用于gcrypt的密钥)。

*)它支持从各种格式(PEM-> DER,DER-> Sexp)转换。

*)它支持各种对称加密算法和模式。

*)它支持非对称加密/解密/签名/验证。

我没有真正使用它,所以我不能评论API的可用性,但从我看到它通常要好得多。

我真的不知道荨麻的背景,但我不知道它是否是因为gcrypt的API非常糟糕而创建的,他们宁愿重新开始而不是加强gcrypt。