http://bertrandmartel.github.io/ssl-cert-generator-lib/
Last update 11/10/2015
Generate SSL certificates using openssl api :
- generate X509 public/private key pair, output can be PEM, PKCS12 certs
- generate self-signed cert (which can be used as CA cert)
- generate X509 public/private key pair signed with a specific issuer cert or a CA
- generate a diffie hellman key
- output can be a specific file / certificates can be accessed programmatically as well
cd sslcertgenerator
make
Library release is under release
directory.
Declare new instance of SslGen :
#include "crypto/sslgen.h"
....
sslgen ssl_gen;
Generate self-signed certificates :
ssl_gen.create_standalone_keys(cert_entries *entries,struct tm *date_start,struct tm *date_end,int serial,char *passin,int rsa_key_size,certificate_raw *certs);
entries
: a set of certificate entries with following structure :
typedef struct {
std::string country_name;
std::string state_province_name;
std::string locality_name;
std::string organization_name;
std::string organizational_unit_name;
std::string common_name;
} cert_entries;
date_start
anddate_end
specifying certificate validation timingsserial
: specifying certificate serial number to be usedpassin
: optional password for private keyrsa_key_size
: size of key (2048 or more is prefered)certificate_raw
: output pointer structure as following :
typedef struct {
std::string public_key_pem;
std::string private_key_pem;
std::vector<char> key_pkcs12;
} certificate_raw;
ssl_gen.create_signed_keys(cert_entries *entries,struct tm *date_start,struct tm *date_end,int serial,char *passin,int rsa_key_size,ca_cert *cert_item,certificate_raw *certs);
entries
: a set of certificate entries with following structure :
typedef struct {
std::string country_name;
std::string state_province_name;
std::string locality_name;
std::string organization_name;
std::string organizational_unit_name;
std::string common_name;
} cert_entries;
date_start
and date_end specifying certificate validation timingsserial
: specifying certificate serial number to be usedpassin
: optional password for private keyrsa_key_size
: size of key (2048 or more is prefered)ca_cert
: structure defining public/private key of CA cert or cert issuer
typedef struct{
std::string public_key_pem;
std::string private_key_pem;
std::string pass;
} ca_cert;
certificate_raw
: output pointer structure as following :
typedef struct {
std::string public_key_pem;
std::string private_key_pem;
std::vector<char> key_pkcs12;
} certificate_raw;
By default public and private key are given in PEM format. By default, no output file path is specified.
You can specify cert output files for PEM cert as following :
ssl_gen.setOutputPEM(bool enable_pem,char* public_key_file,char* private_key_file);
enable_pem
: enable PEM format (default)public_key_file
: output file for public key in PEM formatprivate_key_file
: output file for private key in PEM format
You can specify cert output files for PKCS12 cert as following :
ssl_gen.setOutputP12(bool enable_p12,char* key_file);
enable_p12
: enable PKCS12 formatkey_file
: output file for public/private key in PKCS12 format
Generate Diffie-Hellman key with :
ssl_gen.create_dh_key(int key_size,char* file_path);
key_size
: key size to be used (2048 is preferred)file_path
: required output file path for the key
Examples
Generate self-signed certificates
/*instanciate certificate generation lib*/
sslgen ssl_gen;
/* get system time for date start*/
time_t systime;
struct tm *sys_time;
time(&systime);
sys_time=localtime(&systime);
/* set end date to 30/08/2019 00:00:00 (current timezone)*/
struct tm date_end;
date_end.tm_year = 2019 - 1900;
date_end.tm_mon = 8 - 1;
date_end.tm_mday = 30;
date_end.tm_hour = 0;
date_end.tm_min = 0;
date_end.tm_sec = 0;
date_end.tm_isdst = sys_time->tm_isdst;
/*set certificate entries*/
cert_entries entries;
entries.country_name=CERT_COUNTRY_NAME;
entries.state_province_name=CERT_STATE_OR_PROVINCE_NAME;
entries.locality_name=CERT_LOCALITY_NAME;
entries.organization_name=CERT_ORGANIZATION_NAME;
entries.organizational_unit_name=CERT_ORGANIZATION_UNIT_NAME;
/* generate public/private key (we want PEM + PKCS12 format) + output is retrieved through input pointer + file output name*/
/*set output cert as pem certificate (default). If you set file output name. Cert will be written under these files*/
ssl_gen.setOutputPEM(true,"../../output_test/test.crt","../../output_test/test.key");
/*set output cert as p12 certificate. If you set file output name. Cert will be written under these files*/
ssl_gen.setOutputP12(true,"../../output_test/test.p12");
certificate_raw certs;
certificate_raw *certs_ptr;
certs_ptr=&certs;
certs_ptr->public_key_pem="";
certs_ptr->private_key_pem="";
entries.common_name="Github ssl-cert-generator";
/* generate standalone keys (not signed with other certificate) */
ssl_gen.create_standalone_keys(&entries,sys_time,&date_end,509,"123456",2048,&certs);
cout << "public cert : " << certs_ptr->public_key_pem << endl;
cout << "private cert : " << certs_ptr->private_key_pem << endl;
cout << "p12 binary content : " << endl;
utils::printHexFormattedCert(certs_ptr->key_pkcs12,certs_ptr->key_pkcs12.size());
Generate signed certificate
std::ifstream in1("../../cert/ca.key");
std::string root_ca_key_input((std::istreambuf_iterator<char>(in1)),std::istreambuf_iterator<char>());
std::ifstream in2("../../cert/ca.crt");
std::string root_ca_pub_input((std::istreambuf_iterator<char>(in2)),std::istreambuf_iterator<char>());
/*set output cert as pem certificate (default). If you set file output name. Cert will be written under these files*/
ssl_gen.setOutputPEM(true,"../../output_test/client.crt","../../output_test/client.key");
/*set output cert as p12 certificate. If you set file output name. Cert will be written under these files*/
ssl_gen.setOutputP12(true,"../../output_test/client.p12");
ca_cert ca;
ca.public_key_pem=root_ca_pub_input;
ca.private_key_pem=root_ca_key_input;
ca.pass="123456";
entries.common_name="Github ssl-cert-generator signed cert";
ssl_gen.create_signed_keys(&entries,sys_time,&date_end,22555,"123456",2048,&ca,&certs);
cout << "public cert : " << certs_ptr->public_key_pem << endl;
cout << "private cert : " << certs_ptr->private_key_pem << endl;
cout << "p12 binary content : " << endl;
utils::printHexFormattedCert(certs_ptr->key_pkcs12,certs_ptr->key_pkcs12.size());
Here are some useful openssl command to test your output :
Check start date and end date for a PEM certificate
openssl x509 -startdate -noout -in cert.crt
openssl x509 -enddate -noout -in cert.crt
Check a public PEM key
- openssl x509 -in cert.crt -text -noout
Check a private PEM key
- openssl rsa -in cert.key -check
Check a PKCS12 file
- openssl pkcs12 -info -in cert.p12
Check that public/key pair is uncorrupted
Those commands should return same md5 :
openssl x509 -noout -modulus -in cert.crt | openssl md5
openssl rsa -noout -modulus -in cert.key | openssl md5
Verify certificate
openssl verify cert.pem
Verify certificate chain
openssl verify -CAfile ca.crt server.crt
Install certificates on Linux
sudo mkdir /usr/share/ca-certificates/extra
sudo cp your_cert.pem /usr/share/ca-certificates/extra/your_cert.crt
sudo dpkg-reconfigure ca-certificates
sudo update-ca-certificates
Memory checking
Project is memcheck free
valgrind --tool=memcheck --leak-check=full ./main
Project is built with openssl library built with -DPURIFY option to avoid valgrind to complain about uninitialized data ("Conditional jump or move depends on uninitialised value(s)" warnings).
https://www.openssl.org/docs/faq.html#PROG14
TODO
- add static library
- add certificate extensions
- add CA certificate to PKCS12 for signed certificate
- add pass for PKCS12 (distinguished from private key)