我的程序使用OpenSSL,并需要按需创建自签名证书。运行该程序的系统无法访问“openssl”CLI命令,因此我不能使用它。相反,我需要使用OpenSSL X509 API来实现这一目标。
请注意,我不需要创建证书文件,只需要创建一个证书;OpenSSL称之为“X509”结构。
我找不到任何关于如何实现这一点的文档。
我该怎么做?
谢谢。
请注意,我不需要创建证书文件,只需要创建一个证书;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);
}