10.8. Cloning a CA That Has Been Re-Keyed

When a certificate expires, it has to be replaced. This can either be done by renewing the certificate, which re-uses the original keypair to generate a new certificate, or it can be done by generating a new keypair and certificate. The second method is called re-keying.
When a CA is re-keyed, new keypairs are stored in its certificate database, and these are the keys references for normal operations. However, for cloning a subsystem, the cloning process checks for the CA private key IDs as stored in its CS.cfg configuration file — and those key IDs are not updated when the certificate database keys change.
If a CA has been re-keyed and then an administrator attempts to clone it, the cloned CA fails to generate any certificates for the certificates which were re-keyed, and it shows up in the error logs with this error:
CertUtil::createSelfSignedCert() - CA private key is null!
To clone a CA that has been re-keyed:
  1. Find all of the private key IDs in the CS.cfg file.
    # grep privkey.id /var/lib/pki/instance_name/ca/conf/CS.cfg
    cloning.signing.privkey.id     =-4d798441aa7230910d4e1c39fa132ea228d5d1bc
    cloning.ocsp_signing.privkey.id =-3e23e743e0ddd88f2a7c6f69fa9f9bcebef1a60
    cloning.subsystem.privkey.id     =-c3c1b3b4e8f5dd6d2bdefd07581c0b15529536
    cloning.sslserver.privkey.id    =3023d30245804a4fab42be209ebb0dc683423a8f
    cloning.audit_signing.privkey.id=2fe35d9d46b373efabe9ef01b8436667a70df096
  2. Print all of the current private key IDs stored in the NSS database and compare them to the private key IDs stored in the CS.cfg file:
    # certutil -K -d alias
    certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and Certificate Services"
    Enter Password or Pin for "NSS Certificate DB":
    < 0> rsa      a7b0944b7b8397729a4c8c9af3a9c2b96f49c6f3   caSigningCert cert-ca4-test-master
    < 1> rsa      6006094af3e5d02aaa91426594ca66cb53e73ac0   ocspSigningCert cert-ca4-test-master
    < 2> rsa      d684da39bf4f2789a3fc9d42204596f4578ad2d9   subsystemCert cert-ca4-test-master
    < 3> rsa      a8edd7c2b5c94f13144cacd99624578ae30b7e43   sslserverCert cert-ca4-test1
    < 4> rsa      2fe35d9d46b373efabe9ef01b8436667a70df096   auditSigningCert cert-ca4-test1
    In this example, only the audit signing key is the same; the others have been changed.
  3. Take the keys returned in step 2 and convert them from unsigned values (which is what certutil returns) to signed Java BigIntegers (which is how the keys are stored in the Certificate System database).
    This can be done with a calculator or by using the script in Example 10.1, “Certutil to BigInteger Conversion Program”.
  4. Copy the new key values into the CS.cfg file.
    # vim /var/lib/pki/instance_name/ca/conf/CS.cfg
    
    cloning.signing.privkey.id     =-584f6bb4847c688d65b373650c563d4690b6390d
    cloning.ocsp_signing.privkey.id =6006094af3e5d02aaa91426594ca66cb53e73ac0
    cloning.subsystem.privkey.id   =-297b25c640b0d8765c0362bddfba690ba8752d27
    cloning.sslserver.privkey.id   =-5712283d4a36b0ecebb3532669dba8751cf481bd
    cloning.audit_signing.privkey.id=2fe35d9d46b373efabe9ef01b8436667a70df096
  5. Clone the CA as described in Section 10.2, “Cloning a CA”.

Example 10.1. Certutil to BigInteger Conversion Program

This Java program can convert the key output from certutil to the required BigInteger format.
Save this as a .java file, such as Test.java.
import java.math.BigInteger;

public class Test
{

  public static byte[] hexStringToByteArray(String s) {
      int len = s.length();
      byte[] data = new byte[len / 2];
      for (int i = 0; i < len; i += 2) {
          data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                               + Character.digit(s.charAt(i+1), 16));
      }
      return data;
  }

  public static void main(String[] args)
  {
      byte[] bytes = hexStringToByteArray(args[0]);
      BigInteger big = new BigInteger (bytes);
      System.out.println("Result is  ==> " + big.toString(16));
  }
}
Then, compile the file:
# javac Test.java