+ // Construct the Certificate
+
+ std::shared_ptr<X509> ret = std::shared_ptr<X509>( X509_new(), X509_free );
+
+ if( !ret ) {
+ throw "Creating X509 failed.";
+ }
+
+ X509_CINF* ci = ret->cert_info;
+
+ if( !X509_set_version( ret.get(), 2 ) ) {
+ throw "Setting X509-version to 3 failed";
+ }
+
+ if( !X509_set_issuer_name( ret.get(), X509_get_subject_name( caCert.get() ) ) ) {
+ throw "Error setting Issuer name";
+ }
+
+ // Serial and Pubkey
+ ASN1_INTEGER_set( ci->serialNumber, 4711 );
+ pktmp = X509_REQ_get_pubkey( req.get() );
+
+ if( !X509_set_pubkey( ret.get(), pktmp ) ) {
+ EVP_PKEY_free( pktmp );
+ throw "Setting public key failed.";
+ } else {
+ EVP_PKEY_free( pktmp );
+ }
+
+ // Dates
+ X509_gmtime_adj( X509_get_notBefore( ret.get() ), 0 );
+ X509_gmtime_adj( X509_get_notAfter( ret.get() ), ( long )60 * 60 * 24 * 10 );
+
+ // Extensions
+ add_ext( caCert, ret.get(), NID_basic_constraints, "critical,CA:FALSE" );
+ add_ext( caCert, ret.get(), NID_subject_key_identifier, "hash" );
+ add_ext( caCert, ret.get(), NID_authority_key_identifier, "keyid,issuer:always" );
+ add_ext( caCert, ret.get(), NID_key_usage, "critical,nonRepudiation,digitalSignature,keyEncipherment" );
+ add_ext( caCert, ret.get(), NID_ext_key_usage, "clientAuth, serverAut" );
+ add_ext( caCert, ret.get(), NID_info_access, "OCSP;URI:http://ocsp.cacert.org" );
+ add_ext( caCert, ret.get(), NID_crl_distribution_points, "URI:http://crl.cacert.org/class3-revoke.crl" );
+
+ if( !X509_sign( ret.get(), caKey.get(), EVP_sha512() ) ) {
+ throw "Signing failed.";
+ }
+
+ X509_print_fp( stdout, ret.get() );
+ std::shared_ptr<BIO> mem = std::shared_ptr<BIO>( BIO_new( BIO_s_mem() ), BIO_free );
+ PEM_write_bio_X509( mem.get(), ret.get() );
+ BUF_MEM* buf;
+ BIO_get_mem_ptr( mem.get(), &buf );
+ std::string output( buf->data, buf->data + buf->length );
+ std::cout << "Certificate:" << std::endl << output << std::endl;