Introduction
The example 'C' program certsignature.c demonstrates how to extract the serial number from a X.509 digitial certificate, using the OpenSSL library functions.
Example Code Listing
/* ------------------------------------------------------------ *
* file: certsignature.c *
* purpose: Example to extract and display cert signatures *
* author: 09/30/2012 Frank4DD *
* *
* gcc -o certsignature certsignature.c -lssl -lcrypto *
* ------------------------------------------------------------ */
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
/* ---------------------------------------------------------- *
* This function is taken from openssl/crypto/asn1/t_x509.c. *
* ---------------------------------------------------------- */
int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent);
int main() {
const char cert_filestr[] = "./cert-file.pem";
ASN1_STRING *asn1_sig = NULL;
X509_ALGOR *sig_type = NULL;
size_t sig_bytes = 0;
BIO *certbio = NULL;
BIO *outbio = NULL;
X509 *cert = NULL;
int ret;
/* ---------------------------------------------------------- *
* These function calls initialize openssl for correct work. *
* ---------------------------------------------------------- */
OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
/* ---------------------------------------------------------- *
* Create the Input/Output BIO's. *
* ---------------------------------------------------------- */
certbio = BIO_new(BIO_s_file());
outbio = BIO_new_fp(stdout, BIO_NOCLOSE);
/* ---------------------------------------------------------- *
* Load the certificate from file (PEM). *
* ---------------------------------------------------------- */
ret = BIO_read_filename(certbio, cert_filestr);
if (! (cert = PEM_read_bio_X509(certbio, NULL, 0, NULL))) {
BIO_printf(outbio, "Error loading cert into memory\n");
exit(-1);
}
/* ---------------------------------------------------------- *
* Extract the certificate's signature data. *
* ---------------------------------------------------------- */
sig_type = cert->sig_alg;
asn1_sig = cert->signature;
sig_bytes = asn1_sig->length;
/* ---------------------------------------------------------- *
* Print the signature type here *
* ---------------------------------------------------------- */
BIO_printf(outbio, "Signature Algorithm:\n");
if (i2a_ASN1_OBJECT(outbio, sig_type->algorithm) <= 0)
BIO_printf(outbio, "Error getting the signature algorithm.\n");
else BIO_puts(outbio, "\n\n");
/* ---------------------------------------------------------- *
* Print the signature length here *
* ---------------------------------------------------------- */
BIO_printf(outbio, "Signature Length:\n%d Bytes\n\n", sig_bytes);
/* ---------------------------------------------------------- *
* Print the signature data here *
* ---------------------------------------------------------- */
BIO_printf(outbio, "Signature Data:");
if (X509_signature_dump(outbio, asn1_sig, 0) != 1)
BIO_printf(outbio, "Error printing the signature data\n");
/* ---------------------------------------------------------- *
* Free up all structures *
* ---------------------------------------------------------- */
X509_free(cert);
BIO_free_all(certbio);
BIO_free_all(outbio);
exit(0);
}
/* ---------------------------------------------------------- *
* X509_signature_dump() converts binary signature data into *
* hex bytes, separated with : and a newline after 54 chars. *
* (2 chars + 1 ':' = 3 chars, 3 chars * 18 = 54) *
* ---------------------------------------------------------- */
int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) {
const unsigned char *s;
int i, n;
n=sig->length;
s=sig->data;
for (i=0; i<n; i++) {
if ((i%18) == 0) {
if (BIO_write(bp,"\n",1) <= 0) return 0;
if (BIO_indent(bp, indent, indent) <= 0) return 0;
}
if (BIO_printf(bp,"%02x%s",s[i],
((i+1) == n)?"":":") <= 0) return 0;
}
if (BIO_write(bp,"\n",1) != 1) return 0;
return 1;
}
Compiling the Code
Compile the test program with:
fm@susie114:~> gcc -o certsignature certsignature.c -lssl -lcrypto
Example Output
The program expects a certificate file called cert-file.pem in the same directory. If the certificate is found and loaded, the following examplary output is produced:
fm@susie114:~> ./certsignature Signature Algorithm: sha1WithRSAEncryption Signature Length: 256 Bytes Signature Data: 5f:69:7d:de:ed:95:99:c3:43:03:a8:0f:91:bc:d7:0a:b9:c7: 0b:93:3f:0e:4e:c8:19:2d:7e:70:01:35:16:67:79:a6:45:87: 9f:6d:c6:63:04:c7:e2:49:53:83:d2:94:ba:1d:db:4d:57:54: 1c:d2:20:75:05:4c:c9:79:67:d2:5b:9c:b5:58:b9:80:bd:8f: 80:3f:7e:79:d1:86:93:e8:75:74:e2:0b:4a:81:74:3a:67:10: ea:e1:d5:4d:a2:3c:c2:da:4c:b0:60:73:24:50:4a:96:2d:da: 11:f4:6a:b7:f3:84:1e:1a:08:b9:6c:41:b8:2d:59:1a:3f:a5: af:d0:82:60:c1:98:57:ab:65:e5:ee:c5:b7:e8:82:9d:0d:29: a6:b2:6c:d9:6c:49:70:35:ec:85:15:c0:3b:47:82:9f:52:7e: 85:c3:c7:73:ed:bd:35:98:38:4d:ee:3a:e7:3d:73:5e:e6:3b: e9:4a:14:f6:f0:b6:5d:39:8a:c6:cf:1b:6d:e4:8c:1a:14:e5: 02:f2:0c:c4:c9:3c:74:4c:04:f4:52:b8:5e:dc:b0:d5:f8:86: b1:59:d8:fa:5c:b3:eb:cf:96:14:50:c7:db:14:a9:3a:d9:99: 3e:e0:28:ca:84:03:a2:f7:1f:7e:fd:3f:08:3a:2d:8a:22:cf: 42:7f:d5:26
Remarks
The certificate signature is generated by using the private key of the signing CA certificate. The exception are so-called "self-signed" certificates, where the certificates own private key is used to sign itself. Self-signed certificates are also identifyable by having their subject data identical to their issuer section.