java.lang.Object
net.i2p.crypto.SelfSignedGenerator

public final class SelfSignedGeneratorextends Object
Generate keys and a selfsigned certificate, suitable for storing in a Keystore with KeyStoreUtil.storePrivateKey(File, String, String, String, PrivateKey, List). All done programatically, no keytool, no BC libs, no sun classes. Ref: RFC 2459, RFC 5280

This is coded to create a cert that is similar to what comes out of keytool.

NOTE: Recommended use is via KeyStoreUtil.createKeys(File, String, String, String, String) and related methods. This API may not be stable.

  • Field Details

  • Constructor Details

    • SelfSignedGenerator

      public SelfSignedGenerator()
      The key and certificate generators below are static, and the only state is a thread-local date format, so an instance carries nothing.
  • Method Details

    • generate

      public static Object[] generate(String cname, String ou, String o, String l, String st, String c, int validDays, SigType type) throws GeneralSecurityException
      Create a self-signed certificate with a new keypair.
      Parameters:
      cname - the common name, non-null. Must be a hostname or email address. IP addresses will not be correctly encoded.
      ou - The OU (organizational unit) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      o - The O (organization)in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      l - The L (city or locality) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      st - The ST (state or province) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      c - The C (country) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      validDays - how many days from now the certificate stays valid
      type - the signature algorithm the certificate is signed with
      Returns:
      length 4 array: rv[0] is a Java PublicKey rv[1] is a Java PrivateKey rv[2] is a Java X509Certificate rv[3] is a Java X509CRL
      Throws:
      GeneralSecurityException - if the keypair cannot be generated or the certificate cannot be signed
    • generate

      public static Object[] generate(String cname, Set<String> altNames, String ou, String o, String l, String st, String c, int validDays, SigType type) throws GeneralSecurityException
      Create a self-signed certificate with a new keypair.
      Parameters:
      cname - the common name, non-null. Must be a hostname or email address. IP addresses will not be correctly encoded.
      altNames - the Subject Alternative Names. May be null. May contain hostnames and/or IP addresses. cname, localhost, 127.0.0.1, and ::1 will be automatically added.
      ou - The OU (organizational unit) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      o - The O (organization)in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      l - The L (city or locality) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      st - The ST (state or province) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      c - The C (country) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      validDays - how long the certificate stays valid
      type - the signature type to generate the keypair for
      Returns:
      length 4 array: rv[0] is a Java PublicKey rv[1] is a Java PrivateKey rv[2] is a Java X509Certificate rv[3] is a Java X509CRL
      Throws:
      GeneralSecurityException - if the keypair cannot be generated or signed
    • generate

      public static X509Certificate generate(SigningPrivateKey priv, String cname, int validDays) throws GeneralSecurityException
      Create a self-signed certificate for the existing private key.
      Parameters:
      priv - the key to sign the new certificate with
      cname - the common name, non-null. Must be a hostname or email address. IP addresses will not be correctly encoded.
      validDays - how long the certificate stays valid
      Returns:
      the X509Certificate signed by priv, valid for validDays from now
      Throws:
      GeneralSecurityException - if the certificate cannot be built or signed
    • generate

      private static Object[] generate(PublicKey jpub, PrivateKey jpriv, SigningPrivateKey priv, SigType type, String cname, Set<String> altNames, String ou, String o, String l, String st, String c, int validDays) throws GeneralSecurityException
      Create a self-signed certificate with the given keypair.
      Parameters:
      jpub - the public key to be embedded in the certificate, as a Java key
      jpriv - the private key as a Java key, currently unused
      priv - the signing private key used to sign the certificate
      type - the signature type, must be a supported type, non-null
      cname - the common name, non-null. Must be a hostname or email address. IP addresses will not be correctly encoded.
      altNames - the Subject Alternative Names. May be null. May contain hostnames and/or IP addresses. cname, localhost, 127.0.0.1, and ::1 will be automatically added.
      ou - The OU (organizational unit) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      o - The O (organization) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      l - The L (city or locality) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      st - The ST (state or province) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      c - The C (country) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      validDays - the certificate validity period, in days from now
      Returns:
      length 4 array: rv[0] is a Java PublicKey rv[1] is a Java PrivateKey rv[2] is a Java X509Certificate rv[3] is a Java X509CRL
      Throws:
      GeneralSecurityException - if the signature type is not supported, or signing the certificate fails
    • renew

      public static Object[] renew(X509Certificate cert, PrivateKey jpriv, int validDays) throws GeneralSecurityException
      Create a renewed certificate from the given cert and keypair.
      Parameters:
      cert - the old cert to be replaced
      jpriv - the private key
      validDays - how long the renewed certificate stays valid
      Returns:
      length 4 array: rv[0] is a Java PublicKey, from cert as passed in rv[1] is a Java PrivateKey, jpriv as passed in rv[2] is a Java X509Certificate, new one rv[3] is a Java X509CRL, new one
      Throws:
      GeneralSecurityException - if the renewed certificate cannot be signed
    • generateCRL

      private static X509CRL generateCRL(X509Certificate cert, int validDays, int crlNum, byte[] sigoid, SigningPrivateKey priv) throws GeneralSecurityException
      Generate a CRL for the given cert, signed with the given private key.
      Parameters:
      cert - the certificate whose issuer signs the CRL and which is listed as revoked
      validDays - the CRL validity period, in days from now
      crlNum - the CRL number extension value, 0-255
      sigoid - the encoded signature algorithm OID sequence, as from getEncodedOIDSeq()
      priv - the signing private key used to sign the CRL
      Returns:
      the CRL object parsed back from the encoded bytes
      Throws:
      GeneralSecurityException - if signing fails or the CRL cannot be parsed
    • genTBS

      private static byte[] genTBS(String cname, Set<String> altNames, String ou, String o, String l, String st, String c, int validDays, byte[] sigoid, PublicKey jpub)
      Generate the TBS portion of the certificate.
      Parameters:
      cname - the common name, non-null
      altNames - the Subject Alternative Names. May be null. May contain hostnames and/or IP addresses. cname, localhost, 127.0.0.1, and ::1 will be automatically added.
      ou - The OU (organizational unit) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      o - The O (organization) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      l - The L (city or locality) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      st - The ST (state or province) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      c - The C (country) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
      validDays - the certificate validity period, in days from now
      sigoid - the encoded signature algorithm OID sequence, as from getEncodedOIDSeq()
      jpub - the public key to be embedded in the certificate, as a Java key
      Returns:
      the encoded to-be-signed certificate, including the algorithm identifier but not the signature
    • genTBSCRL

      private static byte[] genTBSCRL(X509Certificate cert, int validDays, int crlNum, byte[] sigalg)
      Generate the TBS portion of the CRL.
      Parameters:
      cert - the certificate whose issuer is the CRL issuer and whose serial number is revoked
      validDays - the CRL validity period, in days from now
      crlNum - 0-255 because lazy
      sigalg - the encoded signature algorithm OID sequence
      Returns:
      ASN.1 encoded object
    • spaceFor

      private static int spaceFor(int val)
      Total bytes needed to hold a value of the given length in ASN.1.
      Parameters:
      val - the length of the value, 65535 max
      Returns:
      the length of the TLV
    • getValidity

      private static byte[] getValidity(int validDays)
      Sequence of two UTCDates.
      Parameters:
      validDays - the not-valid-after date is this many days past the backdated not-valid-before date
      Returns:
      32 bytes ASN.1 encoded object
    • getDate

      private static byte[] getDate(long now)
      A single UTCDate.
      Parameters:
      now - the instant to encode, in milliseconds since the epoch
      Returns:
      15 bytes ASN.1 encoded object
    • skiOffset

      static int skiOffset(byte[] der)
      Index into a DER-encoded SubjectPublicKeyInfo where the SKI/AKI hash input begins, i.e. just past the outer SEQUENCE's tag and length.

      A DER length is short-form when the first length octet has bit 8 clear, and long-form otherwise, in which case that octet's low 7 bits are the number of following length octets - 1 or 2 in practice. Reading the flag bit instead of the count advanced the index by 128, so every DSA and RSA certificate hashed a window starting 127 bytes into the key instead of just past its header. Ed25519's 44-byte SPKI is short-form and was unaffected.

      Parameters:
      der - the DER-encoded SubjectPublicKeyInfo, at least 2 bytes long
      Returns:
      the offset the identifier is hashed from
    • getExtensions

      private static byte[] getExtensions(byte[] pubbytes, String cname, Set<String> altNames)
      Add the following extensions: 1) Subject Key Identifier 2) Key Usage 3) Basic Constraints 4) Subject Alternative Name As of 0.9.34, adds 127.0.0.1 and ::1 to the SAN also 5) Authority Key Identifier (not necessarily output in that order)

      Ref: RFC 5280.

      Parameters:
      pubbytes - the DER-encoded public key bit string the extension identifier is derived from
      cname - the common name, added to the SANs and used to decide if the cert is a CA
      altNames - the Subject Alternative Names. May be null. May contain hostnames and/or IP addresses. cname, localhost, 127.0.0.1, and ::1 will be automatically added.
      Returns:
      ASN.1 encoded object
    • getCRLExtensions

      private static byte[] getCRLExtensions(int crlNum)
      Generate the extensions section of the CRL.
      Parameters:
      crlNum - 0-255 because lazy
      Returns:
      16 bytes ASN.1 encoded object
    • getEncodedOIDSeq

      private static byte[] getEncodedOIDSeq(String oid)
      0x30 len 0x06 len encodedbytes... 0x05 0.
      Parameters:
      oid - the dotted object identifier, e.g. 1.2.840.113549.1.1.1
      Returns:
      ASN.1 encoded object
      Throws:
      IllegalArgumentException - if getEncodedOID() rejects the identifier as invalid
    • getEncodedOID

      private static byte[] getEncodedOID(String oid)
      0x06 len encodedbytes...
      Parameters:
      oid - the dotted object identifier, e.g. 1.2.840.113549.1.1.1
      Returns:
      ASN.1 encoded object
      Throws:
      IllegalArgumentException - if the identifier has fewer than two components, a component is out of range, or the encoding exceeds 127 bytes
    • main

      public static void main(String[] args) throws Exception
      Note: For CLI testing, use java -jar i2p.jar su3file keygen pubkey.crt keystore.ks commonName.
      Parameters:
      args - the command line, starting with the subcommand
      Throws:
      Exception - if the subcommand fails
    • usage

      private static void usage()
      Prints the command line usage text.