OpenSSL:如何使用 p、q 和 e 创建 RSA 结构

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

是否有publicAPI通过指定pq[=23=的值来创建RSA结构] 和 e?

我发现 Crypt-OpenSSL-RSA/RSA.xs 正在做我想做的事。

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.

但另一方面 rsa section in the OpenSSL manual 说:

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

此时关于“使用 API”的说法是有抱负的。 RSA 模块是 OpenSSL 中最古老的模块之一 并且可以追溯到 SSLeay 和 Eric 关心其他事情而不是信息隐藏的时间。较新的模块 像 ECC SHA AES EVP,甚至像 BN BIO SSL 这样经过一些改造的,有 APIs 几乎总是保持不透明, 但 RSA 没有。现在这个项目实际上有多个开发人员,一些旧东西可能会被清理掉。

从语义上讲,您的组合不一致。用作 public 键的 RSA 结构必须有 n 和 e,并且不应有 p q 或任何其他私人信息; 用作私钥的必须有 n d p q dp dq qinv 和可能的 e。 (e 不用于私钥 操作 , 但它需要检查密钥对或将其写出或读回。)如果你真的有 p q e 你必须计算 n, 如果你想要一个私钥,你还必须计算 d (then) dp dq qinv。请参阅 PKCS#1 又名 https://www.rfc-editor.org/rfc/rfc3447,一旦您拥有正确的 BN 值,现在只需将它们填充到 rsa->whatever 中。

Openssl 不提供 API 通过 p、q 生成密钥,但可以根据数学创建密钥...

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