rsalibgcrypt

Why does gcrypt say to recalculate the coefficient of an RSA key when converting from SSL format to gcrypt?


The documentation for libgcrypt says:

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)))

...and...

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

...and...

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);
  }

If in one p is the smaller prime and in the other q is the smaller prime, and given that the two equations are identical save for exchanging p and q, is it really necessary to have to recompute u? Is it not sufficient just to exchange p and q?

As a side question, I am curious why gcrypt doesn't use the same values as the PKCS#1 encoding:

     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.

Solution

  • The answer is that recalculating "u" is irrelevant. Simply swap the usage of "p" and "q" and it all works.

    As a general comment on gcrypt, the asymmetric cryptography APIs are terrible. Truly abysmal.

    During the course of my investigations I discovered that there is another GNU encryption library. Why they maintain two I have no idea. The other is called "nettle" and is much better:

    *) It uses the GMP library for multi-precision integers, rather than having its own type as gcrypt does (mpi_t).

    *) It supports loading keys from files in a variety of formats (I used it as the basis for my own code to load keys for use with gcrypt).

    *) It supports conversion from various formats (PEM->DER, DER->Sexp).

    *) It supports a variety of symmetric encryption algorithms and modes.

    *) It supports asymmetric encryption/decryption/signing/verification.

    I didn't actually use it so I cannot really comment on the APIs usability, but from what I saw it was generally much much better.

    I don't really know the background on nettle, but I do wonder if it was created simply because gcrypt's API is so awful and they would rather start over than enhance gcrypt.