2013-05-03 106 views
4

我的程序使用OpenSSL,需要根據需要創建自簽名證書。它所運行的系統無法訪問'openssl'CLI命令,因此我無法使用它。相反,我需要通過使用OpenSSL X509 API來實現這一點。如何以編程方式在OpenSSL中創建自簽名證書(即不使用「openssl」CLI命令)?

請注意,我不需要創建一個證書文件,只是一個證書; OpenSSL稱之爲「X509」結構。

我找不到有關如何執行此操作的任何文檔。

我該怎麼做?

謝謝。

+0

如果你抓住openssl源代碼,並在req.c文件中查找apps目錄,你可以看到OpenSSL二進制文件如何實現它。具體來說,您需要查看-x509和-new標誌,這會導致它創建一個新請求並對其進行自簽名。 – 2013-05-04 17:26:19

回答

4

我結合@斯里卡特與代碼我在OpenSSL分佈找到的碼(在演示/ 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);   
    } 
6

這裏是一個示例代碼可以是有益的

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

這使我在正確的軌道上。具體來說,我在OpenSSL代碼中找到了相似的代碼(在demos/selfsign.c中)。我將結合你的代碼併發布我認爲最簡單的解決方案。謝謝! – 2013-05-06 15:21:04

+0

不客氣。很高興知道它有幫助。 – Sreekanth 2013-05-07 13:30:40

相關問題