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

时间:2013-05-03 17:27:02

标签: c openssl certificate

我的程序使用OpenSSL,需要根据需要创建自签名证书。它运行的系统无法访问'openssl'CLI命令,因此我无法使用它。相反,我需要通过使用OpenSSL X509 API来实现这一目标。

请注意,我不需要创建证书FILE,只需要创建证书; OpenSSL称之为“X509”结构。

我找不到有关如何执行此操作的任何文档。

我该怎么做?

感谢。

2 个答案:

答案 0 :(得分:7)

这是一个有用的示例代码

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

答案 1 :(得分:4)

我将@Sreekanth的代码与我在OpenSSL发行版中找到的代码(在desmos / self signed.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);         
   }