How to Use OpenSSL to Generate X.509 Certificate Request

In this tutorial, let’s learn how to use OpenSSL to generate X.509 certificate request.

Certificate signing request is a message sent from an applicant to a certificate authority, which usually includes:

  1. Country Name (2 letter code) [US]
  2. State or Province Name (full name) [BC]
  3. Locality Name (e.g., city) [Vancouver]
  4. Organization Name (e.g., company) [My Company Ltd]
  5. Organizational Unit Name (e.g., section)
  6. Common Name (e.g., your name or your server’s hostname)
  7. Email Address

Implementation Steps:

  1. Generate RSA key
  2. Set version
  3. Set subject
  4. Set public key
  5. Set sign key
  6. Free

Code & Result:

#include <stdio.h>
#include <iostream>
#include <openssl/rsa.h>
#include <openssl/pem.h>

bool gen_X509Req()
{
	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, *bio_err = NULL;

	const char		*szCountry = "CA";
	const char		*szProvince = "BC";
	const char		*szCity = "Vancouver";
	const char		*szOrganization = "Dynamsoft";
	const char		*szCommon = "localhost";

	const char		*szPath = "x509Req.pem";

	// 1. generate rsa key
	bne = BN_new();
	ret = BN_set_word(bne,e);
	if(ret != 1){
		goto free_all;
	}

	r = RSA_new();
	ret = RSA_generate_key_ex(r, bits, bne, NULL);
	if(ret != 1){
		goto free_all;
	}

	// 2. set version of x509 req
	x509_req = X509_REQ_new();
	ret = X509_REQ_set_version(x509_req, nVersion);
	if (ret != 1){
		goto free_all;
	}

	// 3. set subject of x509 req
	x509_name = X509_REQ_get_subject_name(x509_req);

	ret = X509_NAME_add_entry_by_txt(x509_name,"C", MBSTRING_ASC, (const unsigned char*)szCountry, -1, -1, 0);
	if (ret != 1){
		goto free_all;
	}

	ret = X509_NAME_add_entry_by_txt(x509_name,"ST", MBSTRING_ASC, (const unsigned char*)szProvince, -1, -1, 0);
	if (ret != 1){
		goto free_all;
	}

	ret = X509_NAME_add_entry_by_txt(x509_name,"L", MBSTRING_ASC, (const unsigned char*)szCity, -1, -1, 0);
	if (ret != 1){
		goto free_all;
	}	

	ret = X509_NAME_add_entry_by_txt(x509_name,"O", MBSTRING_ASC, (const unsigned char*)szOrganization, -1, -1, 0);
	if (ret != 1){
		goto free_all;
	}

	ret = X509_NAME_add_entry_by_txt(x509_name,"CN", MBSTRING_ASC, (const unsigned char*)szCommon, -1, -1, 0);
	if (ret != 1){
		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){
		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){
		goto free_all;
	}

	out = BIO_new_file(szPath,"w");
	ret = PEM_write_bio_X509_REQ(out, x509_req);

	// 6. free
free_all:
	X509_REQ_free(x509_req);
	BIO_free_all(out);

	EVP_PKEY_free(pKey);
	BN_free(bne);

	return (ret == 1);
}

int main(int argc, char* argv[]) 
{
	gen_X509Req();
	return 0;
}
-----BEGIN CERTIFICATE REQUEST-----
MIICmzCCAYMCAQEwVjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRIwEAYDVQQH
EwlWYW5jb3V2ZXIxEjAQBgNVBAoTCUR5bmFtc29mdDESMBAGA1UEAxMJbG9jYWxo
b3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA++1mP9LtZPaCKfFe
paVTjvIWdeWLOEwh5K8uSDNb84Hkx83nJxInY6CZPA+07nWq5Xudofahiiop2ifq
kyuIya0AQOpsiWjV6GyY9j9ERvyTKcTMaXW4FgKRVKb71y5DYVtx7GbluoCb6Iky
GBPzUJnBlbyzFWT7d/FH4YDxbdTEWTw7YJtm/nbakD09JprT/4JrjC+jBCmWwb19
2WXAI4vEFhqGVJIUufwHwMD9ZVwIhpk3cB83gNsQuwTtQIRFl0yuY7om15d5Qg1j
vvGsSodJdMmp2MV4NO2rmt2H7iZKlXREYVsmnvdbOzb4v4V/DUkm5gRp+MUXtBxf
2NCgsQIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAH7fo3WgaM8TakXN/jAsMZMs
F4Thyyc0ZcVPF8r23ULJgYgENjXhaS8xuoXWOVikRZZm+6H7OHzHyfVeOkwlplsH
1+yXG2IBP3W6nw71oJjDYIcU4Dtw3e3tTN3/J0eSXlSr7MU9DXeVLBdiodeWeKHw
AumED55pd0lpFiJ1f7bQ2Nh0+mVIuZaDgnN8YesPPDqW70t9bjD9LHJl6T9OxRJE
vTq7BEqNB8XmYKJ+ODEKDQQNUar2YFcs4tZHiaOotZ11ZRaLrkG+Svl7ZE6V9GaO
Yss1j3jb4rFENS3vQdt69ODNJHu/maPUS87TpN1vmX66ntiEt7M2HKx8FiBiz/E=
-----END CERTIFICATE REQUEST-----

You can feel free to download the sample code, and run it in Visual Studio.

How to Use OpenSSL to Generate RSA Keys in C/C++

It is known that RSA is a cryptosystem which is used for the security of data transmission. This tutorial introduces how to use RSA to generate a pair of public and private keys on Windows.

  1. Download and install OpenSSL https://www.openssl.org/community/binaries.html.
  2. Find libeay32.lib, ssleay32.lib and libeay32.dll.
  3. The following sample code will generate a public key “public.pem” and a private key “private.pem”.
#include <stdio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>

bool generate_key()
{
	int				ret = 0;
	RSA				*r = NULL;
	BIGNUM			*bne = NULL;
	BIO				*bp_public = NULL, *bp_private = NULL;

	int				bits = 2048;
	unsigned long	e = RSA_F4;

	// 1. generate rsa key
	bne = BN_new();
	ret = BN_set_word(bne,e);
	if(ret != 1){
		goto free_all;
	}

	r = RSA_new();
	ret = RSA_generate_key_ex(r, bits, bne, NULL);
	if(ret != 1){
		goto free_all;
	}

	// 2. save public key
	bp_public = BIO_new_file("public.pem", "w+");
	ret = PEM_write_bio_RSAPublicKey(bp_public, r);
	if(ret != 1){
		goto free_all;
	}

	// 3. save private key
	bp_private = BIO_new_file("private.pem", "w+");
	ret = PEM_write_bio_RSAPrivateKey(bp_private, r, NULL, NULL, 0, NULL, NULL);

	// 4. free
free_all:

	BIO_free_all(bp_public);
	BIO_free_all(bp_private);
	RSA_free(r);
	BN_free(bne);

	return (ret == 1);
}

int main(int argc, char* argv[]) 
{
	generate_key();
        return 0;
}

You can feel free to download the sample code, and run it in Visual Studio.