c语言 - 如何在 OpenSSL 中以编程方式创建自签名证书(即不使用"openssl"CLI 命令)?



我的程序使用OpenSSL,需要根据需要创建一个自签名证书。它运行的系统没有访问'openssl' CLI命令的权限,所以我不能使用它。相反,我需要通过使用OpenSSL X509 api来实现这一点。

注意,我不需要创建一个证书文件,只是一个证书;OpenSSL称之为"X509"结构。

我找不到任何关于如何做到这一点的文档。

我该怎么做?

谢谢。

这里是一个示例代码,可能会有帮助

X509 *certificate = NULL;
EVP_PKEY *pkey = NULL;
int   ASN1_INTEGER *serialNumber = NULL;
int i = 0;
RSA *rsaKeyPair = NULL;
BIGNUM *e = NULL;
X509_NAME *name = NULL;
time_t currentTime;
certificate = X509_new();

rsaKeyPair = RSA_new();
e = BN_new();
BN_set_word(e, 65537);

if (!RSA_generate_key_ex(rsaKeyPair, 1024, e, NULL))
{
  ret = error;
}
/* the big number is no longer used */
BN_free(e);
e = NULL;

 EVP_PKEY_assign_RSA(pkey,rsaKeyPair))

  /* no more use for rsaKeyPair */
  rsaKeyPair = NULL;

  (void)X509_set_version(certificate,2);
  /*Allocate and create serial number*/
  serialNumber = M_ASN1_INTEGER_new();
  /*implement serial number algorithm here*/
  CreateSerialNumber(serialNumber);
  /* set the serial number */
  (void)X509_set_serialNumber(certificate,serialNumber);
  /*Serial number set to certificate, free it now*/
  M_ASN1_INTEGER_free(serialNumber); 
  serialNumber = NULL;
  /* set the validity */
  currentTime = time(0);
  X509_gmtime_adj(X509_get_notBefore(certificate), 0);
  X509_gmtime_adj(X509_get_notAfter(certificate), 1000);
  /* set the public key from the privateKey structure into the certificate structure */
  X509_set_pubkey(certificate,pkey);
  /* get the subject name pointer */
  name = X509_get_subject_name(certificate);}

/* country */
 X509_NAME_add_entry_by_txt(
  name,"C",MBSTRING_ASC, (unsigned char *)creationParams->Country, -1, -1, 0);
 !X509_NAME_add_entry_by_txt(name,"O", MBSTRING_ASC, (unsigned char*) "sample", -1, -1, 0);

X509_NAME_add_entry_by_txt(
  name,"CN",MBSTRING_ASC, (unsigned char*) creationParams->CommonName, -1, -1, 0);
 /* its self signed: set issuer name = subject  */
 X509_set_issuer_name(certificate,name);
 /* sign the certificate using sha-1 */
X509_sign(certificate,pkey,EVP_sha1());

我将@Sreekanth的代码与我在OpenSSL发行版(在demos/selfsign.c中)中找到的代码结合起来。下面是我能想到的最简单的:

X509 *CreateCertificate (char *Country, char *OrganizationName, char *CommonName, char *DNSName, int Serial, int DaysValid)
   {  X509 *Cert = NULL;
      EVP_PKEY *PrivateKey = NULL;
      X509_NAME *Name = NULL;
      RSA *KeyPair = NULL;
      BIGNUM *BigNumber = NULL;
      int Success = 0;
   // Faux loop...
   do {
      // Create the certificate object
      Cert = X509_new();
      if (!Cert)
         break;
      // Set version 2, and get version 3         
      X509_set_version (Cert, 2);
      // Set the certificate's properties
      ASN1_INTEGER_set (X509_get_serialNumber (Cert), Serial);
      X509_gmtime_adj (X509_get_notBefore (Cert), 0);
      X509_gmtime_adj (X509_get_notAfter (Cert), (long)(60 * 60 * 24 * (DaysValid ? DaysValid : 1)));
      Name = X509_get_subject_name (Cert);
      if (Country && *Country)
         X509_NAME_add_entry_by_txt (Name, "C", MBSTRING_ASC, Country, -1, -1, 0);
      if (CommonName && *CommonName)
         X509_NAME_add_entry_by_txt (Name, "CN", MBSTRING_ASC, CommonName, -1, -1, 0);
      if (OrganizationName && *OrganizationName)
         X509_NAME_add_entry_by_txt (Name, "O", MBSTRING_ASC, OrganizationName, -1, -1, 0);
      X509_set_issuer_name (Cert, Name);
      // Set the DNS name
      if (DNSName && *DNSName)
         {  X509_EXTENSION *Extension;
            char Buffer[512];
         // Format the value
         sprintf (Buffer, "DNS:%s", DNSName);
         Extension = X509V3_EXT_conf_nid (NULL, NULL, NID_subject_alt_name, Buffer);
         if (Extension)
            {
            X509_add_ext (DynamicCert->Certificate, Extension, -1);
            X509_EXTENSION_free (Extension);
            }
         }
      // Create the RSA key pair object
      KeyPair = RSA_new();
      if (!KeyPair)
         break;
      // Create the big number object
      BigNumber = BN_new();
      if (!BigNumber)
         break;
      // Set the word      
      if (!BN_set_word (BigNumber, 65537))
         break;
      // Generate the key pair; lots of computes here         
      if (!RSA_generate_key_ex (KeyPair, 1024, BigNumber, NULL))
         break;
      // Now we need a private key object
      PrivateKey = EVP_PKEY_new();
      if (!PrivateKey)
         break;
      // Assign the key pair to the private key object
      if (!EVP_PKEY_assign_RSA (PrivateKey, KeyPair))
         break;
      // KeyPair now belongs to PrivateKey, so don't clean it up separately
      KeyPair = NULL;
      // Set the certificate's public key from the private key object
      if (!X509_set_pubkey (Cert, PrivateKey))
         break;
      // PrivateKey now belongs to Cert, so don't clean it up separately
      PrivateKey = NULL;
      // Sign it with SHA-1
      if (!X509_sign (Cert, PrivateKey, EVP_sha1()))
         break;
      // Success               
      Success = 1;
      } while (0);         
   // Things we always clean up
   if (BigNumber)
      BN_free (BigNumber);
   if (PrivateKey)
      EVP_PKEY_free (PrivateKey);
   // Things we clean up only on failure
   if (!Success)
      {
      if (Cert)
         X509_free (Cert);
      if (PrivateKey)
         EVP_PKEY_free (PrivateKey);
      if (KeyPair)
         RSA_free (KeyPair);
      Cert = NULL;
      }
   // Return the certificate (or NULL)
   return (Cert);         
   }

最新更新