java.lang.Object
net.i2p.crypto.SU3File

public class SU3Fileextends Object
I2P update file format handler for .su3 files. Supports reading, writing, and verification of signed update packages.
  • Field Details

    • _context

      private final I2PAppContext _context
      The app context.
    • _file

      private final File _file
      The SU3 file being read.
    • _version

      private String _version
      The file's version string.
    • _versionLength

      private int _versionLength
      Length of the version field, in bytes.
    • _signer

      private String _signer
      The signer name from the header.
    • _signatureLength

      private int _signatureLength
      Length of the signature, in bytes.
    • _signerLength

      private int _signerLength
      Length of the signer field, in bytes.
    • _fileType

      private int _fileType
      The content type code, -1 until read.
    • _contentType

      private SU3File.ContentType _contentType
      The content type of the file.
    • _contentLength

      private long _contentLength
      Length of the content, in bytes.
    • _signerPubkey

      private PublicKey _signerPubkey
      The signer's public key.
    • _headerVerified

      private boolean _headerVerified
      True once the header has been verified.
    • _sigType

      private SigType _sigType
      The signature type of the file.
    • _verifySignature

      private boolean _verifySignature
      Whether to verify the signature.
    • _certFile

      private File _certFile
      Certificate file used for verification.
    • MAGIC

      public static final String MAGIC
      The magic string every SU3 file starts with.
      See Also:
    • MAGIC_BYTES

      private static final byte[] MAGIC_BYTES
      Magic bytes at the start of the file.
    • FILE_VERSION

      private static final int FILE_VERSION
      The SU3 file version we write.
      See Also:
    • MIN_VERSION_BYTES

      private static final int MIN_VERSION_BYTES
      Shortest version string accepted.
      See Also:
    • VERSION_OFFSET

      private static final int VERSION_OFFSET
      Offset where the version string starts.
      See Also:
    • TYPE_ZIP

      public static final int TYPE_ZIP
      The file type is advisory and is application-dependent. The following values are defined but any value 0-255 is allowed.
      See Also:
    • TYPE_XML

      public static final int TYPE_XML
      A file whose contents are XML.
      See Also:
    • TYPE_HTML

      public static final int TYPE_HTML
      A file whose contents are HTML.
      See Also:
    • TYPE_XML_GZ

      public static final int TYPE_XML_GZ
      A gzipped XML file.
      See Also:
    • TYPE_TXT_GZ

      public static final int TYPE_TXT_GZ
      A gzipped plain text file.
      See Also:
    • TYPE_DMG

      public static final int TYPE_DMG
      A macOS disk image.
      See Also:
    • TYPE_EXE

      public static final int TYPE_EXE
      A Windows executable.
      See Also:
    • CONTENT_UNKNOWN

      public static final int CONTENT_UNKNOWN
      The content type has not been determined.
      See Also:
    • CONTENT_ROUTER

      public static final int CONTENT_ROUTER
      The archive holds a router.
      See Also:
    • CONTENT_PLUGIN

      public static final int CONTENT_PLUGIN
      The archive holds a plugin.
      See Also:
    • CONTENT_RESEED

      public static final int CONTENT_RESEED
      The archive holds reseed data.
      See Also:
    • CONTENT_NEWS

      public static final int CONTENT_NEWS
      The archive holds a news feed.
      See Also:
    • CONTENT_BLOCKLIST

      public static final int CONTENT_BLOCKLIST
      The archive holds a blocklist.
      See Also:
    • BY_CODE

      private static final Map<Integer, SU3File.ContentType> BY_CODE
      Content types indexed by code.
    • DEFAULT_CONTENT_TYPE

      private static final SU3File.ContentType DEFAULT_CONTENT_TYPE
      Type assumed when the code is unknown.
    • DEFAULT_SIG_CODE

      private static final int DEFAULT_SIG_CODE
      Signature type assumed when none is set.
      See Also:
  • Constructor Details

    • SU3File

      public SU3File(String file)
      SU3 file from the given path.
      Parameters:
      file - the path to the su3 file
    • SU3File

      public SU3File(File file)
      SU3 file from the given file.
      Parameters:
      file - the su3 file
    • SU3File

      public SU3File(I2PAppContext context, File file)
      SU3 file from the given file, using the given context.
      Parameters:
      context - the application context
      file - the su3 file
  • Method Details

    • setVerifySignature

      public void setVerifySignature(boolean shouldVerify)
      Choose whether the signature is verified.
      Parameters:
      shouldVerify - true to verify the signature, the default
    • setPublicKeyCertificate

      private void setPublicKeyCertificate(File certFile)
      Use this X.509 cert file for verification instead of $I2P/certificates/content_type/foo_at_mail.i2p.
      Parameters:
      certFile - the X.509 certificate file to verify the signature against
    • getVersionString

      public String getVersionString() throws IOException
      This does not check the signature, but it will fail if the signer is unknown, unless setVerifySignature(false) has been called.
      Returns:
      the version string
      Throws:
      IOException - if the header cannot be read
    • getSignerString

      public String getSignerString() throws IOException
      This does not check the signature, but it will fail if the signer is unknown, unless setVerifySignature(false) has been called.
      Returns:
      the signer string
      Throws:
      IOException - if the header cannot be read
    • getSigType

      public SigType getSigType() throws IOException
      This does not check the signature, but it will fail if the signer is unknown, unless setVerifySignature(false) has been called.
      Returns:
      null if unknown
      Throws:
      IOException - if the header cannot be read
    • getContentType

      public int getContentType() throws IOException
      The ContentType is the trust domain for the content. The signer and signature will be checked with the trusted certificates for that type.

      This does not check the signature, but it will fail if the signer is unknown, unless setVerifySignature(false) has been called.

      Returns:
      -1 if unknown
      Throws:
      IOException - if the header cannot be read
    • getFileType

      public int getFileType() throws IOException
      The file type is advisory and is application-dependent. The following values are defined but any value 0-255 is allowed.

      This does not check the signature, but it will fail if the signer is unknown, unless setVerifySignature(false) has been called.

      Returns:
      0-255 or -1 if unknown
      Throws:
      IOException - if the header cannot be read
    • verifyHeader

      public void verifyHeader() throws IOException
      This does not check the signature, but it will fail if the signer is unknown, unless setVerifySignature(false) has been called.
      Throws:
      IOException - if the header cannot be read or the signer is unknown
    • verifyHeader

      private void verifyHeader(InputStream in) throws IOException, DataFormatException
      Throws if verify fails.
      Parameters:
      in - the stream positioned at the start of the su3 file
      Throws:
      IOException - if the magic bytes, file version, or a length field is invalid, or the signer is unknown
      DataFormatException - not thrown by the current implementation
    • skip

      private static void skip(InputStream in, int cnt) throws IOException
      Skip the given number of bytes.
      Parameters:
      in - the stream to read from
      cnt - the number of bytes to skip
      Throws:
      IOException - if the stream ends before cnt bytes are read
    • getContentOffset

      private int getContentOffset() throws IOException
      Returns the offset where the content starts.
      Returns:
      the content offset
      Throws:
      IOException - if the header is invalid
    • verify

      public boolean verify() throws IOException
      One-pass verify.
      Returns:
      true if signature is good
      Throws:
      IOException - on any format error
    • verifyAndMigrate

      public boolean verifyAndMigrate(File migrateTo) throws IOException
      One-pass verify and extract the content. Recommend extracting to a temp location as the sig is not checked until after extraction. This will delete the file if the sig does not verify.
      Parameters:
      migrateTo - the output file, probably in zip format. Null for verify only.
      Returns:
      true if signature is good
      Throws:
      IOException - on any format error
    • write

      public void write(File content, int fileType, int contentType, String version, String signer, PrivateKey privkey, SigType sigType) throws IOException
      One-pass wrap and sign the content. Writes to the file specified in the constructor.
      Parameters:
      content - the input file, probably in zip format
      fileType - 0-255, 0 for zip
      contentType - 0-255
      version - 1-255 bytes when converted to UTF-8
      signer - ID of the public key, 1-255 bytes when converted to UTF-8
      privkey - the signing key, whose public half is the signer ID
      sigType - the digest and signature scheme to sign with
      Throws:
      IOException - if the content cannot be read or the file cannot be written
    • main

      public static void main(String[] args)
      Parses command line arguments when this class is used from the command line. Exits 1 on failure so this can be used in scripts.
      Parameters:
      args - Command line parameters.
    • showUsageCLI

      private static final void showUsageCLI()
      Prints the command line usage.
    • dumpTypes

      private static String dumpTypes()
      String listing available signature types.
      Returns:
      the list of type names for the -t option
    • parseContentType

      private static SU3File.ContentType parseContentType(String ctype)
      Resolve a content type from its number or its name.
      Parameters:
      ctype - number or name
      Returns:
      null if not found
    • showVersionCLI

      private static final boolean showVersionCLI(String signedFile)
      Display version from a signed SU3 file via CLI.
      Parameters:
      signedFile - path of the signed SU3 file to display
      Returns:
      true if version was displayed successfully
    • bulkSignCLI

      private static final boolean bulkSignCLI(String stype, String ctype, String dir, String privateKeyFile, String version, String signerName, String kspass)
      Zip, xml, and xml.gz only.
      Parameters:
      stype - signature type name or code, null for the default
      ctype - content type name or code, null for unknown
      dir - directory containing the .zip, .xml, and .xml.gz files to sign
      privateKeyFile - keystore file containing the private signing key
      version - the version string written into the su3 header
      signerName - key alias in the keystore, also written as the signer string
      kspass - the keystore password
      Returns:
      true on success
    • signCLI

      private static final boolean signCLI(String stype, String ctype, String ftype, String inputFile, String signedFile, String privateKeyFile, String version, String signerName, String keypw, String kspass)
      Whether the operation succeeded.
      Parameters:
      stype - signature type name or code, null for the default
      ctype - content type name or code, null for unknown
      ftype - file type name (ZIP, XML, HTML, XML_GZ, DMG, EXE) or code 0-255, null for ZIP
      inputFile - path of the unsigned input file
      signedFile - path of the su3 file to write
      privateKeyFile - keystore file containing the private signing key
      version - the version string written into the su3 header
      signerName - key alias in the keystore, also written as the signer string
      keypw - private key password, prompted for if under 6 characters
      kspass - the keystore password
      Returns:
      true on success
    • signCLI

      private static final boolean signCLI(SigType type, SU3File.ContentType ctype, int ftype, String inputFile, String signedFile, String privateKeyFile, String version, String signerName, String keypw, String kspass)
      Whether the operation succeeded.
      Parameters:
      type - signature type, overridden by the actual type of the private key
      ctype - content type recorded in the su3 header
      ftype - numeric file type, 0-255
      inputFile - path of the unsigned input file
      signedFile - path of the su3 file to write
      privateKeyFile - keystore file containing the private signing key
      version - the version string written into the su3 header
      signerName - key alias in the keystore, also written as the signer string
      keypw - private key password, prompted for if under 6 characters
      kspass - the keystore password
      Returns:
      true on success
    • verifySigCLI

      private static final boolean verifySigCLI(String signedFile, String pkFile)
      Verify signature on a signed file via CLI.
      Parameters:
      signedFile - path of the signed SU3 file to verify
      pkFile - X.509 cert file to verify against, null to use the key rings
      Returns:
      true if the signature verified successfully
    • extractCLI

      private static final boolean extractCLI(String signedFile, String outFile, boolean verifySig, String pkFile)
      If null, will use a name derived from signedFile.
      Parameters:
      signedFile - path of the signed SU3 file to extract
      outFile - if null, will use a name derived from signedFile
      verifySig - true to verify the signature before extracting
      pkFile - X.509 cert file to verify against, null to use the key rings
      Returns:
      true on success
    • genKeysCLI

      private static final boolean genKeysCLI(String stype, String publicKeyFile, String privateKeyFile, String crlFile, String alias, String kspass)
      May be null; non-null to save.
      Parameters:
      stype - signature type name or code, null for the default
      publicKeyFile - path of the X.509 certificate file to write, must not already exist
      privateKeyFile - keystore file to store the new private key in
      crlFile - may be null; non-null to save
      alias - key name and certificate subject, prompted for if empty
      kspass - the keystore password
      Returns:
      true on success
    • genKeysCLI

      private static final boolean genKeysCLI(SigType type, String publicKeyFile, String privateKeyFile, String crlFile, String alias, String kspass)
      Writes Java-encoded keys (X.509 for public and PKCS#8 for private).
      Parameters:
      type - signature type for the new key pair
      publicKeyFile - path of the X.509 certificate file to write, must not already exist
      privateKeyFile - keystore file to store the new private key in
      crlFile - may be null; non-null to save
      alias - key name and certificate subject, prompted for if empty
      kspass - the keystore password
      Returns:
      true on success
    • loadKey

      private static PublicKey loadKey(File kd) throws IOException
      For the -k CLI option.
      Parameters:
      kd - the X.509 certificate file to load the public key from
      Returns:
      non-null, throws IOE on all errors
      Throws:
      IOException - if the file cannot be read or does not contain a valid certificate