Introduction


The example 'C' program certserial.c demonstrates how to extract the serial number from a X.509 digitial certificate, using the OpenSSL library functions.

Example Code Listing


/* ------------------------------------------------------------ *
 * file:        certserial.c                                    *
 * purpose:     Example code for OpenSSL certificate serials    *
 * author:      06/12/2012 Frank4DD                             *
 *                                                              *
 * gcc -o certserial certserial.c -lssl -lcrypto                *
 * ------------------------------------------------------------ */

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>

int main() {

  const char cert_filestr[] = "./cert-file.pem";
  ASN1_INTEGER *asn1_serial = NULL;
  BIO              *certbio = NULL;
  BIO               *outbio = NULL;
  X509                *cert = NULL;
  const char *neg;
  int ret, i;
  long l;

  /* ---------------------------------------------------------- *
   * 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 serial number.                   *
   * ---------------------------------------------------------- */
   asn1_serial = X509_get_serialNumber(cert);
   if (asn1_serial == NULL)
     BIO_printf(outbio, "Error getting serial number from certificate");

  /* ---------------------------------------------------------- *
   * Print the serial number value, openssl x509 -serial style  *
   * ---------------------------------------------------------- */
  BIO_puts(outbio,"serial (openssl x509 -serial style): ");
  i2a_ASN1_INTEGER(outbio, asn1_serial);
  BIO_puts(outbio,"\n");

  /* ---------------------------------------------------------- *
   * Print the serial number value, openssl x509 -text style    *
   * ---------------------------------------------------------- */
  if (asn1_serial->length <= (int)sizeof(long)) {
    l=ASN1_INTEGER_get(asn1_serial);
    if (asn1_serial->type == V_ASN1_NEG_INTEGER) {
      l= -l;
      neg="-";
    }
    else neg="";

    if (BIO_printf(outbio," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0)
      BIO_printf(outbio, "Error during printing the serial.\n");
  } else {
    neg=(asn1_serial->type == V_ASN1_NEG_INTEGER)?" (Negative)":"";
    //if (BIO_printf(outbio,"\n%12s%s","",neg) <= 0)
    if (BIO_printf(outbio,"serial (openssl x509 -text   style): %s","",neg) <= 0)
      BIO_printf(outbio, "Error during printing the serial.\n");

    for (i=0; i<asn1_serial->length; i++) {
     if (BIO_printf(outbio,"%02x%c",asn1_serial->data[i],
        ((i+1 == asn1_serial-<length)?'\n':':')) <= 0)
      BIO_printf(outbio, "Error during printing the serial.\n");
    }
  }

  X509_free(cert);
  BIO_free_all(certbio);
  BIO_free_all(outbio);
  exit(0);
}

Compiling the Code


Compile the test program with:

fm@susie114:~> gcc -o certserial certserial.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 output is produced:

fm@susie114:~> ./certserial
serial (openssl x509 -serial style): 2797BD99F24DC4841DB4335DBE25CF8A
serial (openssl x509 -text   style): 27:97:bd:99:f2:4d:c4:84:1d:b4:33:5d:be:25:cf:8a

Remarks


Each certificate is required to have a serial number. This serial is assigned by the CA at the time of signing. Because the data type is specified as a non-negative integer of up to 20 octets length (160 bit), a CA can create a astronomical high number of certs. Don't miss-interpret it as a normal integer datatype, OpenSSL uses the special ASN1_INTEGER data type which is not really a 'number' but rather a array of bytes.

Per standard, the serial number should be unique per CA, however it is up to the CA code to enforce this. For example, with OpenSSL makes it possible to manually set the serial during signing, using the -set_serial option. Although not officially standardized, a CA should give out serials at random on one hand (to prevent predictability), and tracking them to be unique on the other hand.

Related standard/section: RFC 3280, section 4.1.2.2


OpenSSL Logo

Topics:

Source:

Documentation: