C++ OpenSSL 之三:生成CSR文件
1.等同于使用: openssl req -new -key "key_path" -out "save_path" -subj "/emailAddress=email/CN=name/C=country"
2.代码如下:keyFilePath为RSA private key 文件。
bool MakeCsrSSL(const char * keyFilePath, const char *email, const char *name, const char *country, const char *saveCsrFilePath) {
int ret = 0;
RSA *r = NULL;
BIGNUM *bne = NULL;
int nVersion = 1;
int bits = 2048;
unsigned long e = RSA_F4;
X509_REQ *x509_req = NULL;
X509_NAME *x509_name = NULL;
EVP_PKEY *pKey = NULL;
RSA *tem = NULL;
BIO *out = NULL, *keyFileBIO = NULL;
FILE *pubKeyFile = NULL;
if (strlen(saveCsrFilePath) == 0) {
fprintf(stderr, "MakeLocalCsrSSLApi save path is empty\n");
return false;
}
//not exists public key file, create one immediately.
if (strlen(keyFilePath) == 0) {
// 1. generate rsa key
bne = BN_new();
ret = BN_set_word(bne, e);
if (ret != 1) {
fprintf(stderr, "MakeLocalCsrSSLApi BN_set_word err\n");
goto free_all;
}
r = RSA_new();
ret = RSA_generate_key_ex(r, bits, bne, NULL);
if (ret != 1) {
fprintf(stderr, "MakeLocalCsrSSLApi RSA_generate_key_ex err\n");
goto free_all;
}
} else { //open it
pubKeyFile = fopen(keyFilePath, "r");
if (pubKeyFile == NULL) {
fprintf(stderr, "MakeLocalCsrSSLApi opening file %s err\n", keyFilePath);
goto free_all;
}
keyFileBIO = BIO_new_file(keyFilePath, "r");
if (keyFileBIO == NULL) {
fprintf(stderr, "MakeLocalCsrSSLApi BIO_new_file err %s\n", keyFilePath);
goto free_all;
}
r = PEM_read_bio_RSAPrivateKey(keyFileBIO, NULL, NULL, NULL);
if (r == NULL) {
fprintf(stderr, "MakeLocalCsrSSLApi PEM_read_bio_RSAPrivateKey err\n");
goto free_all;
}
/*
//从csr文件中获取私钥
BIO* bio = bio_open_default(csrFilePath, "r", 1);
r = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
if (r == NULL) {
fprintf(stderr, "Error PEM_read_RSAPublicKey file %s\n", savePrivateKeyFilePath);
return false;
}*/
}
// 2. set version of x509 req
x509_req = X509_REQ_new();
ret = X509_REQ_set_version(x509_req, nVersion);
if (ret != 1) {
fprintf(stderr, "MakeLocalCsrSSLApi X509_REQ_set_version err\n");
goto free_all;
}
// 3. set subject of x509 req
x509_name = X509_REQ_get_subject_name(x509_req); //x509_req->req_info.subject;
ret = X509_NAME_add_entry_by_txt(x509_name, "emailAddress", MBSTRING_ASC, (const unsigned char*)email, -1, -1, 0);
if (ret != 1) {
fprintf(stderr, "MakeLocalCsrSSLApi X509_NAME_add_entry_by_txt emailAddress err\n");
goto free_all;
}
ret = X509_NAME_add_entry_by_txt(x509_name, "CN", MBSTRING_ASC, (const unsigned char*)name, -1, -1, 0);
if (ret != 1) {
fprintf(stderr, "MakeLocalCsrSSLApi X509_NAME_add_entry_by_txt CN err\n");
goto free_all;
}
ret = X509_NAME_add_entry_by_txt(x509_name, "C", MBSTRING_ASC, (const unsigned char*)country, -1, -1, 0);
if (ret != 1) {
fprintf(stderr, "MakeLocalCsrSSLApi X509_NAME_add_entry_by_txt C err\n");
goto free_all;
}
// 4. set public key of x509 req
pKey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(pKey, r);
r = NULL; // will be free rsa when EVP_PKEY_free(pKey)
ret = X509_REQ_set_pubkey(x509_req, pKey);
if (ret != 1) {
fprintf(stderr, "MakeLocalCsrSSLApi X509_REQ_set_pubkey err\n");
goto free_all;
}
// 5. set sign key of x509 req
ret = X509_REQ_sign(x509_req, pKey, EVP_sha1()); // return x509_req->signature->length
if (ret <= 0) {
fprintf(stderr, "MakeLocalCsrSSLApi X509_REQ_sign err\n");
goto free_all;
}
out = BIO_new_file(saveCsrFilePath, "w");
ret = PEM_write_bio_X509_REQ(out, x509_req);
// 6. free
free_all:
BIO_free_all(keyFileBIO);
X509_REQ_free(x509_req);
BIO_free_all(out);
EVP_PKEY_free(pKey);
BN_free(bne);
if (pubKeyFile) fclose(pubKeyFile);
return (ret == 1);
}
以上。
《C++ OpenSSL 之一:编译和使用》
《C++ OpenSSL 之二:生成RSA文件》
《C++ OpenSSL 之三:生成CSR文件》
《C++ OpenSSL 之四:CER转换为PEM》
《C++ OpenSSL 之五:生成P12文件》