home |  contact
CountermeasuresTools

Simple PKI


This x.509 Certificate Authority based public key infrastructure utilizes the most basic architecture possible while remaining cryptographically sound. It does not employ a Registration Authority layer. It concentrates on low volume, single certificates for users. It does not address the very important problem of certificate revokation, key escrow, or key recovery.

Most of the technology uses OpenSSL at http://www.openssl.org/

Generate a CA private key and self signed certificate

Many people envision a certificate authority as a server with complex software running deep in the bowels of a secured server room. While this can be true, in this example, the CA is a single bash script, the openssl toolkit, and a closely guarded private key.

Generate a key pair on the isolated system using openssl:

Straight from the mod_ssl faq at http://www.modssl.org/

  openssl genrsa -des3 -out ca.key 1024
  openssl req -new -x509 -days 365 -key ca.key -out ca.crt

Create a mechanism for certificate application

Next you will need an easy way for users to apply for certificates. This mechanism does not issue the certificates. It is a way for users to generate a private key, the corresponding public key and submit the public key for signing.

The following script is for IE user applications:

  <OBJECT CLASSID="clsid:43F8F289-7A20-11D0-8F06-00C04FC295E1"
          CODEBASE="xenroll.dll"
          ID="Enroll">
  </OBJECT>
  <SCRIPT LANGUAGE="VBScript">
  
  Sub Submit_OnClick
  
    Dim TheForm
    Set TheForm = document.CertReqForm
  
    szName = "C=""" & TheForm.countryName.value & """," & _
             "S=""" & TheForm.stateOrProvinceName.value & """," &
             "L=""" & TheForm.localityName.value & """," &
             "O=""" & TheForm.organizationName.value & """," &
             "OU=""" & TheForm.organizationalUnitName.value & """," &
             "CN=""" & TheForm.commonName.value & """," &
             "E=""" & TheForm.emailAddress.value & """"
  
    On Error Resume Next
    Enroll.KeySpec = 1
    Enroll.GenKeyFlags = 3
    sz10 = Enroll.CreatePKCS10(szName,"1.3.6.1.5.5.7.3.2")
  
    if (sz10 = Empty OR theError <> 0) Then
      sz = "The error '" & Hex(theError) & "' occurred."    & _
           chr(13) & chr(10)                                & _
           "Your credentials could not be generated." & szName
      result = MsgBox(sz, 0, "Credentials Enrollment")
  
      Exit Sub
    else
      TheForm.ms_req.value = sz10
      TheForm.submit()
    end if
  
  End Sub
  
  </SCRIPT>
      <FORM ACTION="submit.php" METHOD="POST" NAME="CertReqForm">
      <TABLE>
      <TR>
        <TD>Common Name:</TD>
        <TD><INPUT TYPE="TEXT" NAME="commonName" VALUE="John Doe" SIZE=64></TD>
      </TR>
      <TR>
        <TD>email:</TD>
        <TD><INPUT TYPE="TEXT" NAME="emailAddress" VALUE="jdoe@itillious.com" SIZE=40></TD>
      </TR>
      <TR>
        <TD>Organization:</TD>
        <TD><INPUT TYPE="TEXT" NAME="organizationName" VALUE="Itillious, Inc."></TD>
      </TR>
      <TR>
        <TD>Organizational Unit:</TD>
        <TD><INPUT TYPE="TEXT" NAME="organizationalUnitName" VALUE=""></TD>
      </TR>
      <TR>
        <TD>Locality (City):</TD>
        <TD><INPUT TYPE="TEXT" NAME="localityName" VALUE="Atlanta"></TD>
      </TR>
      <TR>
        <TD>State:</TD>
        <TD><INPUT TYPE="TEXT" NAME="stateOrProvinceName" VALUE="GA"></TD>
      </TR>
      <TR>
        <TD>Country:</TD>
        <TD><INPUT TYPE="TEXT" NAME="countryName" VALUE="US" SIZE="2"></TD>
      </TR>
      </TABLE>
  <INPUT TYPE="hidden" NAME="ms_req" VALUE="">
  <INPUT VALUE="Submit your certificate request"
            TYPE="BUTTON"
            ONCLICK="Submit_OnClick"
            LANGUAGE="VBScript">
  </FORM>

The following snippet is used in place of the javascript and ActiveX control for Netscape users:

  <KEYGEN NAME="mykey">
  <INPUT VALUE="Submit your certificate request" TYPE="SUBMIT">

You will also need a cgi script to process the incoming request. I used php to process requests:

  if(strstr($HTTP_USER_AGENT, 'MSIE')) {
    $body = "-----BEGIN CERTIFICATE REQUEST-----\n" .
            $ms_req .
            "-----END CERTIFICATE REQUEST-----\n";

  } else if(strstr($HTTP_USER_AGENT, 'Mozilla')) {
    $key = str_replace("\r\n", '', $mykey);
    $body = "C=$countryName\n" .
            "ST=$stateOrProvinceName\n" .
            "L=$localityName\n" .
            "O=$organizationName\n" .
            "OU=$organizationalUnitName\n" .
            "CN=$commonName\n" .
            "Email=$emailAddress\n" .
            "SPKAC=$key\n";
  }

  mail('ca@itillious.com', "Certificate Request for $emailAddress", $body);
  $md5sum = exec("/bin/echo -ne \"$body\" | md5sum");

The md5sum at the end of the script is displayed to the user to help verify the request.

Process CSR requests

Certificate Signing Requests are processed by those with signing authority for the CA. These requests should be verified before signing. The integrity of the entire system depends on stringent signing procedures. Signing is done by a simple bash script:

  #!/bin/sh
  ##
  ##  sign.sh -- Sign a SSL Certificate Request (CSR)
  ##  Copyright (c) 1998-2000 Ralf S. Engelschall, All Rights Reserved. 
  ##
  
  #   argument line handling
  CSR=$1
  if [ $# -ne 1 ]; then
      echo "Usage: sign.sign <whatever>.csr"; exit 1
  fi
  if [ ! -f $CSR ]; then
      echo "CSR not found: $CSR"; exit 1
  fi
  case $CSR in
     *.csr ) CERT="`echo $CSR | sed -e 's/\.csr/.crt/'`" ;;
         * ) CERT="$CSR.crt" ;;
  esac
  
  #   make sure environment exists
  if [ ! -d ca.db.certs ]; then
      mkdir ca.db.certs
  fi
  if [ ! -f ca.db.serial ]; then
      echo '01' >ca.db.serial
  fi
  if [ ! -f ca.db.index ]; then
      cp /dev/null ca.db.index
  fi
  
  #   create an own SSLeay config
  cat >ca.config <<EOT
  [ ca ]
  default_ca              = CA_own
  [ CA_own ]
  dir                     = .
  certs                   = \$dir
  new_certs_dir           = \$dir/ca.db.certs
  database                = \$dir/ca.db.index
  serial                  = \$dir/ca.db.serial
  RANDFILE                = \$dir/ca.db.rand
  certificate             = \$dir/ca.crt
  private_key             = \$dir/ca.key
  default_days            = 365
  default_crl_days        = 30
  default_md              = md5
  preserve                = no
  policy                  = policy_anything
  [ policy_anything ]
  countryName             = optional
  stateOrProvinceName     = optional
  localityName            = optional
  organizationName        = optional
  organizationalUnitName  = optional
  commonName              = supplied
  emailAddress            = optional
  EOT
  
  #  sign the certificate
  echo "CA signing: $CSR -> $CERT:"
  openssl ca -config ca.config -out $CERT -infiles $CSR
  echo "CA verifying: $CERT <-> CA cert"
  openssl verify -CAfile ca.crt $CERT
  
  #  cleanup after SSLeay 
  rm -f ca.config
  rm -f ca.db.serial.old
  rm -f ca.db.index.old
  
  #  die gracefully
  exit 0

This script maintains a rudimentary file based database of processed certificates, next serial number for certificates, and the interface to openssl for signing. It will generate the .crt files that are the CA signed, user certificates.

Distribute CA Certificate and User Certificates

The CA certificate can simply be distributed on a web server, mailing as an attachment, or any other public channel. This piece must be installed by the users and authorized for verifying signatures on user certificates. User certificates can be distributed in the same fashion. Additionally, ldap can be used for distribution in address book applications. If these keys are going to be used for S/MIME e-mail, many applications such as Outlook Express and Outlook allow you to send the certificate within the e-mail itself.


Home

Services

Partners

About Us

Contact Us

 

©2001-2003 by Itillious, Inc. All Rights Reserved.
Privacy Policy