2

Specifically, if I preserve the private key can I reproduce the exact same (self-signed) certificate at any time?

The use case I have is a server-to-server protocol that allows (even encourages) self-signed certificates; where I won't know my exact CN ahead of time (varies by peer) and so wish to generate the X509 on-the-fly.

4

As described in RFC 5280, a certificate has the following overall structure:

Certificate  ::=  SEQUENCE  {
     tbsCertificate       TBSCertificate,
     signatureAlgorithm   AlgorithmIdentifier,
     signatureValue       BIT STRING  }

The three elements are the "to-be-signed", an identifier for the signature algorithm, and the signature. If you want to be able to regenerate the exact same certificate, then all three elements must be rebuilt identically.

Most certificate in circulation use RSA "v1.5" signatures, as described in PKCS#1. That signature algorithm is deterministic, so if you use the same private key, same algorithm parameters (the companion hash function), and same input (the to-be-signed), then you will get the same signature. The same does NOT hold for the newer, fancier "PSS" signature scheme described in PKCS#1; that one is randomized and you will get a distinct signature value each time. Similarly, if the key type is DSA or ECDSA, then the corresponding signature scheme is randomized, unless you use a specific deterministic implementation (which is possible but not a given).

Assuming that you use a deterministic signature scheme, then the question reduces to reproducing the same to-be-signed contents. The to-be-signed contains the following:

TBSCertificate  ::=  SEQUENCE  {
    version         [0]  EXPLICIT Version DEFAULT v1,
    serialNumber         CertificateSerialNumber,
    signature            AlgorithmIdentifier,
    issuer               Name,
    validity             Validity,
    subject              Name,
    subjectPublicKeyInfo SubjectPublicKeyInfo,
    issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
                         -- If present, version MUST be v2 or v3
    subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
                         -- If present, version MUST be v2 or v3
    extensions      [3]  EXPLICIT Extensions OPTIONAL
                         -- If present, version MUST be v3
    }

Most libraries that create "self-signed certificates" will introduce variations in the serialNumber (since the serial number is supposed to be unique, it will often be randomly generated) and validity fields. The validity contains the two dates that delimit the time range of certificate validity; usually, a library that creates a self-signed certificate will use the current date and time for the first date, and, thus, won't use the same value if the certificate is recreated at a later time.

Extensions are, by definition, open-ended, and may contain various random elements as well.

Self-signed certificates, by definition, are NOT certificates; they live outside of the certificate validation process, and that process is the only reason why certificates actually exist. A self-signed certificate is a name and a public key, encoded together into what superficially looks like a certificate out of a mixture of quick and dirty reuse of existing code, long-standing Tradition, and historical confusion. Such a "certificate" is self-signed because there is a non-optional field for a signature, but that signature is meaningless.

Therefore, in a self-signed certificate, most if not all "extensions" will be ignored, and so will be some other fields such as the serial number. You can probably (depending on what your server-to-server protocol requires in these "certificates") fill the fields with dummy, fixed values that will make your protocol happy, and can be refilled identically later on. However, not all existing support libraries will allow that; you may have to rewrite your own certificate encoder (which is doable but at the price of your sanity).

| improve this answer | |
  • Thanks Thomas. So it's doable but I'll need to check if the libraries at my disposal expose a deterministic function. I may have to implement database persistence for previously generated x509s instead. The tenant/peer group is in the 100s not the 1000s, so persistence is workable if not optimal. :-) – LateralFractal Apr 9 '15 at 21:09
0

You need to save more than just the private key in order to reproduce the certificate.

You should be able to create a Certificate Signing Request (CSR) which will contain most of the information needed, in addition to the private key.

However, since there is data in the certificate that is not supposed to be duplicated in another other certificates (e.g. serial number) you need to have control over the signing authority and be willing to break the rules.

| improve this answer | |
  • CSRs typically encapsulate information for the benefit of third party CAs; so the question is would the private exponent be the only entropy introduced into the CSR or consequent self-signed certificate? The PKI serial number of root certificate need be only organisationally self consistent; uuid properties of various certificate fields being derived from introduced entropy - hence what I need to preserve to regenerate the same X509 cert as needed (caching of resultant cert doesn't persist beyond the lifecycle of parent app). – LateralFractal Apr 9 '15 at 19:27
  • The problem with your question is that you are misusing the term entropy. Entropy of the certificate is the amount of information that is contained in certificate. So strictly speaking the answer is no, the private key is not the only source of entropy. If you want to recreate the exact certificate, then you'll need additional information. – COL Wotohice Apr 9 '15 at 19:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.