torus
torus

Reputation: 1049

OpenSSL: How to create RSA structure with p, q and e

Is there a public API to create a RSA structure by specifying the values of p, q and e?

I found Crypt-OpenSSL-RSA/RSA.xs doing what I want to do.

new_key_from_parameters

Given Crypt::OpenSSL::Bignum objects for n, e, and optionally d, p, and q, where p and q are the prime factors of n, e is the public exponent and d is the private exponent, create a new Crypt::OpenSSL::RSA object using these values.

But on the other hand the rsa section in the OpenSSL manual says:

applications should generally avoid using RSA structure elements directly and instead use API functions to query or modify keys

Upvotes: 0

Views: 3995

Answers (2)

LinconFive
LinconFive

Reputation: 2012

Openssl does not offer API to gen key via p, q, yet one can create one based on math...

 static int rsa_keygen_self(RSA *rsa, int bits)
      {
      BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp;
      BIGNUM local_r0,local_d,local_p;
      BIGNUM *pr0,*d,*p;
      int bitsp,bitsq,ok= -1,n=0;
      BN_CTX *ctx=NULL;

      ctx=BN_CTX_new();
      if (ctx == NULL) goto err;
      BN_CTX_start(ctx);
      r0 = BN_CTX_get(ctx);
      r1 = BN_CTX_get(ctx);
      r2 = BN_CTX_get(ctx);
      r3 = BN_CTX_get(ctx);
      if (r3 == NULL) goto err;

      bitsp=(bits+1)/2;
      bitsq=bits-bitsp;

      /* We need the RSA components non-NULL */
      if(!rsa->n && ((rsa->n=BN_new()) == NULL)) goto err;
      if(!rsa->d && ((rsa->d=BN_new()) == NULL)) goto err;
      if(!rsa->e && ((rsa->e=BN_new()) == NULL)) goto err;
      if(!rsa->p && ((rsa->p=BN_new()) == NULL)) goto err;
      if(!rsa->q && ((rsa->q=BN_new()) == NULL)) goto err;
      if(!rsa->dmp1 && ((rsa->dmp1=BN_new()) == NULL)) goto err;
      if(!rsa->dmq1 && ((rsa->dmq1=BN_new()) == NULL)) goto err;
      if(!rsa->iqmp && ((rsa->iqmp=BN_new()) == NULL)) goto err;
 //p,q,e all from out side when creating RSA structure.




      /* calculate n */
      if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err;

      /* calculate d */
      if (!BN_sub(r1,rsa->p,BN_value_one())) goto err;    /* p-1 */
      if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;    /* q-1 */
      if (!BN_mul(r0,r1,r2,ctx)) goto err;    /* (p-1)(q-1) */
      if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
          {
            pr0 = &local_r0;
            BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
          }
      else
        pr0 = r0;
      if (!BN_mod_inverse(rsa->d,rsa->e,pr0,ctx)) goto err;   /* d */

      /* set up d for correct BN_FLG_CONSTTIME flag */
      if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
          {
          d = &local_d;
          BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
          }
      else
          d = rsa->d;

      /* calculate d mod (p-1) */
      if (!BN_mod(rsa->dmp1,d,r1,ctx)) goto err;

      /* calculate d mod (q-1) */
      if (!BN_mod(rsa->dmq1,d,r2,ctx)) goto err;

      /* calculate inverse of q mod p */
      if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
          {
          p = &local_p;
          BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
          }
      else
          p = rsa->p;
      if (!BN_mod_inverse(rsa->iqmp,rsa->q,p,ctx)) goto err;

      ok=1;
  err:
      if (ok == -1)
          {
          //RSAerr(RSA_F_RSA_BUILTIN_KEYGEN,ERR_LIB_BN);
          ok=0;
          }
      if (ctx != NULL)
          {
          BN_CTX_end(ctx);
          BN_CTX_free(ctx);
          }

      return ok;
      }

Upvotes: 2

dave_thompson_085
dave_thompson_085

Reputation: 38821

The statement about "use API" is aspirational at this time. The RSA module is one of the oldest in OpenSSL and dates to the time it was SSLeay and Eric cared about other things more than information hiding. Newer modules like ECC SHA AES EVP, and even somewhat reworked ones like BN BIO SSL, have APIs that almost always remain opaque, but RSA doesn't. Now that the project actually has developers plural, some of this old stuff may get cleaned up.

Semantically your combination is inconsistent. An RSA structure used as a public key must have n and e, and should not have p q or any other private info; one used as a private key must have n d p q dp dq qinv and probably e. (e isn't used for privatekey operations, but it is required to check a keypair or write it out or read it back.) If you really have p q e you must compute n, and if you want a private key you must also compute d (then) dp dq qinv. See PKCS#1 aka https://www.rfc-editor.org/rfc/rfc3447 and once you have the correct BN values for now just stuff them in rsa->whatever .

Upvotes: 2

Related Questions