java.lang.Object
net.i2p.crypto.SigUtil

public final class SigUtilextends Object
Comprehensive utility class for I2P signing keys and digital signatures.

This class provides essential methods for converting between I2P's native key formats and standard Java cryptographic key representations, as well as utilities for signature encoding/decoding and key validation.

Key functionalities include:

  • Conversion between I2P and Java key formats
  • Support for DSA, ECDSA, EdDSA, and RSA algorithms
  • ASN.1 signature encoding and decoding
  • Key validation and rectification
  • Field Details

  • Constructor Details

    • SigUtil

      private SigUtil()
      Utility class, not intended for instantiation.
  • Method Details

    • toJavaKey

      public static PublicKey toJavaKey(SigningPublicKey pk) throws GeneralSecurityException
      Convert an I2P SigningPublicKey to a Java PublicKey, dispatching by algorithm.
      Parameters:
      pk - non-null
      Returns:
      Java PublicKey (DSA, EC, EdDSA, or RSA)
      Throws:
      GeneralSecurityException - if conversion fails
    • toJavaKey

      public static PrivateKey toJavaKey(SigningPrivateKey pk) throws GeneralSecurityException
      Convert an I2P SigningPrivateKey to a Java PrivateKey, dispatching by algorithm.
      Parameters:
      pk - non-null
      Returns:
      Java PrivateKey (DSA, EC, EdDSA, or RSA)
      Throws:
      GeneralSecurityException - if conversion fails
    • fromJavaKey

      public static SigningPublicKey fromJavaKey(PublicKey pk) throws GeneralSecurityException
      Use if SigType is unknown. For efficiency, use fromJavakey(pk, type) if type is known.
      Parameters:
      pk - JAVA key!
      Returns:
      the I2P signing public key
      Throws:
      InvalidKeyException - on unknown type
      GeneralSecurityException
    • fromJavaKey

      public static SigningPublicKey fromJavaKey(PublicKey pk, SigType type) throws GeneralSecurityException
      Use if SigType is known.
      Parameters:
      pk - JAVA key!
      type - the I2P signature type naming the base algorithm to convert with
      Returns:
      I2P public key
      Throws:
      GeneralSecurityException - if the JAVA key does not match the base algorithm of the type, or the type names an unknown algorithm
    • fromJavaKey

      public static SigningPrivateKey fromJavaKey(PrivateKey pk) throws GeneralSecurityException
      Use if SigType is unknown. For efficiency, use fromJavakey(pk, type) if type is known.
      Parameters:
      pk - JAVA key!
      Returns:
      the I2P signing private key
      Throws:
      InvalidKeyException - on unknown type
      GeneralSecurityException
    • fromJavaKey

      public static SigningPrivateKey fromJavaKey(PrivateKey pk, SigType type) throws GeneralSecurityException
      Use if SigType is known.
      Parameters:
      pk - JAVA key!
      type - the I2P signature type naming the base algorithm to convert with
      Returns:
      I2P private key
      Throws:
      GeneralSecurityException - if the JAVA key does not match the base algorithm of the type, or the type names an unknown algorithm
    • toJavaECKey

      public static ECPublicKey toJavaECKey(SigningPublicKey pk) throws GeneralSecurityException
      Convert an I2P EC public key to a Java ECPublicKey, with caching.
      Parameters:
      pk - non-null
      Returns:
      Java ECPublicKey
      Throws:
      GeneralSecurityException - if conversion fails
    • toJavaECKey

      public static ECPrivateKey toJavaECKey(SigningPrivateKey pk) throws GeneralSecurityException
      Convert an I2P EC private key to a Java ECPrivateKey, with caching.
      Parameters:
      pk - non-null
      Returns:
      Java ECPrivateKey
      Throws:
      GeneralSecurityException - if conversion fails
    • cvtToJavaECKey

      private static ECPublicKey cvtToJavaECKey(SigningPublicKey pk) throws GeneralSecurityException
      Convert an I2P EC public key to a Java ECPublicKey without caching. Splits the key data into affine x and y coordinates.
      Parameters:
      pk - non-null
      Returns:
      Java ECPublicKey
      Throws:
      GeneralSecurityException - if conversion fails
    • cvtToJavaECKey

      private static ECPrivateKey cvtToJavaECKey(SigningPrivateKey pk) throws GeneralSecurityException
      Convert an I2P EC private key to a Java ECPrivateKey without caching. Extracts the scalar s from the key data.
      Parameters:
      pk - non-null
      Returns:
      Java ECPrivateKey
      Throws:
      GeneralSecurityException - if conversion fails
    • fromJavaKey

      public static SigningPublicKey fromJavaKey(ECPublicKey pk, SigType type) throws GeneralSecurityException
      Convert a Java ECPublicKey to an I2P SigningPublicKey of the given type.
      Parameters:
      pk - non-null
      type - the I2P signature type
      Returns:
      I2P public key
      Throws:
      GeneralSecurityException - if conversion fails
    • fromJavaKey

      public static SigningPrivateKey fromJavaKey(ECPrivateKey pk, SigType type) throws GeneralSecurityException
      Convert a Java ECPrivateKey to an I2P SigningPrivateKey of the given type.
      Parameters:
      pk - non-null
      type - the I2P signature type
      Returns:
      I2P private key
      Throws:
      GeneralSecurityException - if conversion fails
    • toJavaEdDSAKey

      public static EdDSAPublicKey toJavaEdDSAKey(SigningPublicKey pk) throws GeneralSecurityException
      Convert an I2P EdDSA public key to a Java EdDSAPublicKey, with caching.
      Parameters:
      pk - non-null
      Returns:
      Java EdDSAPublicKey
      Throws:
      GeneralSecurityException - if the I2P key bytes cannot be converted to a Java EdDSA key
    • toJavaEdDSAKey

      public static EdDSAPrivateKey toJavaEdDSAKey(SigningPrivateKey pk) throws GeneralSecurityException
      Convert an I2P EdDSA private key to a Java EdDSAPrivateKey, with caching.
      Parameters:
      pk - non-null
      Returns:
      Java EdDSAPrivateKey
      Throws:
      GeneralSecurityException - if the I2P key bytes cannot be converted to a Java EdDSA key
    • cvtToJavaEdDSAKey

      private static EdDSAPublicKey cvtToJavaEdDSAKey(SigningPublicKey pk) throws GeneralSecurityException
      Convert an I2P EdDSA public key to a Java EdDSAPublicKey without caching.
      Parameters:
      pk - non-null
      Returns:
      Java EdDSAPublicKey
      Throws:
      GeneralSecurityException - as InvalidKeyException if the key bytes do not form a valid key for the type
    • cvtToJavaEdDSAKey

      private static EdDSAPrivateKey cvtToJavaEdDSAKey(SigningPrivateKey pk) throws GeneralSecurityException
      Convert an I2P EdDSA or RedDSA private key to a Java EdDSAPrivateKey without caching.
      Parameters:
      pk - non-null
      Returns:
      Java EdDSAPrivateKey
      Throws:
      GeneralSecurityException - as InvalidKeyException if the type is neither EdDSA nor RedDSA, or the key bytes are invalid
    • fromJavaKey

      public static SigningPublicKey fromJavaKey(EdDSAPublicKey pk, SigType type)
      Convert a Java EdDSAPublicKey to an I2P SigningPublicKey.
      Parameters:
      pk - non-null
      type - the I2P signature type
      Returns:
      I2P public key
    • fromJavaKey

      public static SigningPrivateKey fromJavaKey(EdDSAPrivateKey pk, SigType type) throws GeneralSecurityException
      Convert a Java EdDSAPrivateKey to an I2P SigningPrivateKey. Handles EdDSA (seed-based) and RedDSA (private scalar) key types.
      Parameters:
      pk - non-null
      type - the I2P signature type
      Returns:
      I2P private key
      Throws:
      GeneralSecurityException - if the key type names neither an EdDSA seed nor a RedDSA private scalar
    • toJavaDSAKey

      public static DSAPublicKey toJavaDSAKey(SigningPublicKey pk) throws GeneralSecurityException
      Convert an I2P DSA public key to a Java DSAPublicKey.
      Parameters:
      pk - non-null
      Returns:
      Java DSAPublicKey
      Throws:
      GeneralSecurityException - if conversion fails
    • toJavaDSAKey

      public static DSAPrivateKey toJavaDSAKey(SigningPrivateKey pk) throws GeneralSecurityException
      Convert an I2P DSA private key to a Java DSAPrivateKey.
      Parameters:
      pk - non-null
      Returns:
      Java DSAPrivateKey
      Throws:
      GeneralSecurityException - if conversion fails
    • fromJavaKey

      public static SigningPublicKey fromJavaKey(DSAPublicKey pk) throws GeneralSecurityException
      Convert a Java DSAPublicKey to an I2P DSA public key.
      Parameters:
      pk - non-null
      Returns:
      I2P DSA public key
      Throws:
      GeneralSecurityException - if conversion fails
    • fromJavaKey

      public static SigningPrivateKey fromJavaKey(DSAPrivateKey pk) throws GeneralSecurityException
      Convert a Java DSAPrivateKey to an I2P DSA private key.
      Parameters:
      pk - non-null
      Returns:
      I2P DSA private key
      Throws:
      GeneralSecurityException - if conversion fails
    • toJavaRSAKey

      public static RSAPublicKey toJavaRSAKey(SigningPublicKey pk) throws GeneralSecurityException
      Prefer toJavaKey(SigningPublicKey) for type-generic conversion.
      Parameters:
      pk - non-null
      Returns:
      Java RSA public key
      Throws:
      GeneralSecurityException - if conversion fails
    • toJavaRSAKey

      public static RSAPrivateKey toJavaRSAKey(SigningPrivateKey pk) throws GeneralSecurityException
      Convert an I2P RSA private key to a Java RSAPrivateKey. As of 0.9.31, if pk is a RSASigningPrivateCrtKey, returns a RSAPrivateCrtKey.
      Parameters:
      pk - non-null
      Returns:
      Java RSAPrivateKey
      Throws:
      GeneralSecurityException - if conversion fails
    • fromJavaKey

      public static SigningPublicKey fromJavaKey(RSAPublicKey pk, SigType type) throws GeneralSecurityException
      Convert a Java RSAPublicKey to an I2P RSA public key of the given type.
      Parameters:
      pk - non-null
      type - the I2P signature type
      Returns:
      I2P RSA public key
      Throws:
      GeneralSecurityException - if conversion fails
    • fromJavaKey

      public static SigningPrivateKey fromJavaKey(RSAPrivateKey pk, SigType type) throws GeneralSecurityException
      Convert a Java RSAPrivateKey to an I2P RSA private key of the given type. As of 0.9.31, if pk is a RSAPrivateCrtKey, returns a RSASigningPrivateCrtKey.
      Parameters:
      pk - non-null
      type - the I2P signature type
      Returns:
      I2P RSA private key
      Throws:
      GeneralSecurityException - if conversion fails
    • toJavaSig

      public static byte[] toJavaSig(Signature sig)
      Convert an I2P Signature to a Java ASN.1 signature byte array. RSA and EdDSA signatures are passed through unchanged.
      Parameters:
      sig - non-null
      Returns:
      ASN.1 DER-encoded signature bytes (or raw for RSA/EdDSA)
    • fromJavaSig

      public static Signature fromJavaSig(byte[] asn, SigType type) throws SignatureException
      Convert a Java ASN.1 signature byte array to an I2P Signature. RSA and EdDSA signatures are passed through unchanged.
      Parameters:
      asn - ASN.1 DER-encoded signature bytes (or raw for RSA/EdDSA)
      type - the I2P signature type
      Returns:
      an I2P Signature with the given type
      Throws:
      SignatureException - if ASN.1 decoding fails
    • importJavaPublicKey

      public static PublicKey importJavaPublicKey(File file, SigType type) throws GeneralSecurityException, IOException
      Import a Java X.509-encoded public key from a file.
      Parameters:
      file - non-null, containing X.509 encoded key data
      type - the I2P signature type
      Returns:
      Java PublicKey
      Throws:
      GeneralSecurityException - if key conversion fails
      IOException - if file reading fails
    • importJavaPrivateKey

      public static PrivateKey importJavaPrivateKey(File file, SigType type) throws GeneralSecurityException, IOException
      Import a Java PKCS8-encoded private key from a file.
      Parameters:
      file - non-null, containing PKCS8 encoded key data
      type - the I2P signature type
      Returns:
      Java PrivateKey
      Throws:
      GeneralSecurityException - if key conversion fails
      IOException - if file reading fails
    • getData

      private static byte[] getData(File file) throws IOException
      Read the whole file, capped at 16 KB.
      Parameters:
      file - the file to read
      Returns:
      the bytes read, never more than 16 KB
      Throws:
      IOException - if the file cannot be read, or holds more than 16 KB
    • split

      private static NativeBigInteger[] split(byte[] b)
      Split a byte array into two BigIntegers.
      Parameters:
      b - length must be even
      Returns:
      array of two BigIntegers
    • combine

      static byte[] combine(BigInteger x, BigInteger y, int len) throws InvalidKeyException
      Combine two BigIntegers of nominal length = len / 2.
      Parameters:
      x - non-negative first value
      y - non-negative second value
      len - total output length (must be even)
      Returns:
      array of exactly len bytes
      Throws:
      InvalidKeyException - if length is odd or either value is too large
    • rectify

      public static byte[] rectify(BigInteger bi, int len) throws InvalidKeyException
      Convert a BigInteger to a fixed-length byte array, trimming or zero-padding as needed.
      Parameters:
      bi - non-negative
      len - desired output length
      Returns:
      array of exactly len bytes
      Throws:
      InvalidKeyException - if the value is negative or too large to fit
    • sigBytesToASN1

      private static byte[] sigBytesToASN1(byte[] sig)
      Encode raw signature bytes (r || s) into ASN.1 DER SEQUENCE format.

      See Standard Algorithm Names

      Convert to BigInteger and back so we have the minimum length representation, as required. r and s are always non-negative.

      Only supports sigs up to about 252 bytes. See code to fix BER encoding for this before you add a SigType with bigger signatures.

      Parameters:
      sig - raw r||s bytes, length must be even
      Returns:
      ASN.1 DER-encoded SEQUENCE { r INTEGER, s INTEGER }
      Throws:
      IllegalArgumentException - if length is odd or encoded size exceeds limits
    • sigBytesToASN1

      public static byte[] sigBytesToASN1(BigInteger r, BigInteger s)
      Encode two BigInteger values (r, s) into an ASN.1 DER SEQUENCE of two INTEGER values. r and s are always non-negative.

      Only supports sigs up to about 65530 bytes. See code to fix BER encoding for this before you add a SigType with bigger signatures.

      The output is an ASN.1 DER SEQUENCE of two INTEGER values, r and s, in that order:

       SEQUENCE ::= { r INTEGER, s INTEGER }
      
       30 -- tag indicating SEQUENCE
       xx - length in octets
      
       02 -- tag indicating INTEGER
       xx - length in octets
       xxxxxx - value
      
      Parameters:
      r - non-negative
      s - non-negative
      Returns:
      ASN.1 DER-encoded SEQUENCE { r INTEGER, s INTEGER }
      Throws:
      IllegalArgumentException - if too big
      See Also:
    • intToASN1

      public static int intToASN1(byte[] d, int idx, int val)
      Output an length or integer value in ASN.1 Does NOT output the tag e.g. 0x02 / 0x30.
      Parameters:
      d - the destination buffer to write the ASN.1 form into
      idx - the offset in d to start writing at, advanced past what is written
      val - 0-65535
      Returns:
      the new index
    • aSN1ToSigBytes

      private static byte[] aSN1ToSigBytes(byte[] asn, int len) throws SignatureException
      Decode a DER-encoded signature into the fixed-width r then s bytes I2P signs. Only supports sigs up to about 65530 bytes. See code to fix BER encoding for bigger than that.
      Parameters:
      asn - the DER-encoded signature to decode
      len - must be even, twice the nominal length of each BigInteger
      Returns:
      a byte array of len bytes; call split(byte[]) on the result to get the two BigIntegers
      Throws:
      SignatureException - if the input is not an ASN.1 sequence of two integers
    • aSN1ToBigInteger

      public static NativeBigInteger[] aSN1ToBigInteger(byte[] asn, int len) throws SignatureException
      See above. Only supports sigs up to about 65530 bytes. See code to fix BER encoding for bigger than that.
      Parameters:
      asn - the ASN.1 encoded signature or public key to decode
      len - the nominal length of each BigInteger the encoding holds
      Returns:
      the R and S integers, each of len bytes
      Throws:
      SignatureException - if the encoding does not hold the two integers of the expected length
    • clearCaches

      public static void clearCaches()
      Clear all cached Java key conversions. Should be called when key types or configurations change.