net.i2p.data

## Class PrivateKeyFile

- java.lang.Object
- - net.i2p.data.PrivateKeyFile

- Direct Known Subclasses:
    RouterPrivateKeyFile

      public class PrivateKeyFile
      extends Object

  This helper class reads and writes files in the same "eepPriv.dat" format used by the client code. The format is:

        - Destination (387 bytes if no certificate, otherwise longer)
           - Public key (256 bytes), random data as of 0.9.57 (except for RouterPrivateKeyFile)
           - Signing Public key (128 bytes)
           - Cert. type (1 byte)
           - Cert. length (2 bytes)
           - Certificate if length != 0
        - Private key (256 bytes for ElGamal, or length specified by key certificate)
           -          All zeros as of 0.9.57 (except for RouterPrivateKeyFile)
        - Signing Private key (20 bytes, or length specified by key certificate)
        - As of 0.9.38, if the Signing Private Key is all zeros,
          the offline signature section (see proposal 123):
           - Expires timestamp (4 bytes, seconds since epoch, rolls over in 2106)
           - Sig type of transient public key (2 bytes)
           - Transient Signing Public key (length as specified by transient sig type)
           - Signature of Signed Public key by offline key (length as specified by destination sig type)
           - Transient Signing Private key (length as specified by transient sig type)

       Total: 663 or more bytes for ElGamal, may be smaller for other enc. types

  Destination encryption keys have been unused since 0.6 (2005). As of 0.9.57, new Destination encryption public keys are simply random data, and encryption private keys may be random data or all zeros. This class is extended by net.i2p.data.router.RouterPrivateKeyFile. RouterIdentity encryption keys ARE used and must be valid.

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `protected Destination` | `dest`
    `protected File` | `file`
    `protected PrivateKey` | `privKey`
    `protected SigningPrivateKey` | `signingPrivKey`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `PrivateKeyFile(File file)`
    `PrivateKeyFile(File file, Destination dest, PrivateKey pk, SigningPrivateKey spk)`
    `PrivateKeyFile(File file, I2PClient client)`
    `PrivateKeyFile(File file, I2PSession session)`
    `PrivateKeyFile(File file, PublicKey pubkey, SigningPublicKey spubkey, Certificate cert, PrivateKey pk, SigningPrivateKey spk)`
    `PrivateKeyFile(File file, PublicKey pubkey, SigningPublicKey spubkey, Certificate cert, PrivateKey pk, SigningPrivateKey spk, byte[] padding)`
    `PrivateKeyFile(InputStream in)` Can't be used for writing
    `PrivateKeyFile(String file)`

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `static boolean` | `checkSignature(Signature s, byte[] data, SigningPublicKey spk)`
    `Destination` | `createIfAbsent()` Create with the default signature type if nonexistent.
    `Destination` | `createIfAbsent(SigType type)` Create with the specified signature type if nonexistent.
    `Destination` | `getDestination()` If the destination is not set, read it in from the file.
    `long` | `getOfflineExpiration()`
    `Signature` | `getOfflineSignature()`
    `SigningPrivateKey` | `getSigningPrivKey()`
    `SigningPrivateKey` | `getTransientSigningPrivKey()`
    `SigningPublicKey` | `getTransientSigningPubKey()`
    `boolean` | `isOffline()` Does this session have offline and transient keys?
    `static void` | `main(String[] args)` Create a new PrivateKeyFile, or modify an existing one, with various types of Certificates.
    `I2PSession` | `open()`
    `I2PSession` | `open(Properties opts)`
    `Certificate` | `setCertType(int t)` Change cert type - caller must also call write().
    `void` | `setDestination(Destination d)`
    `Certificate` | `setKeyCert(SigType type)` Change cert type - caller must also call write().
    `void` | `setOfflineData(long expires, SigningPublicKey transientPub, Signature sig, SigningPrivateKey transientPriv)` Side effect - zeroes out the current signing private key
    `Certificate` | `setSignedCert(PrivateKeyFile pkf2)` sign this dest by dest found in pkf2 - caller must also call write()
    `String` | `toString()`
    `boolean` | `validateKeyPairs()` Verify that the PublicKey matches the PrivateKey, and the SigningPublicKey matches the SigningPrivateKey.
    `static boolean` | `verifySignature(Destination d)` Sample code to verify a 3rd party signature.
    `void` | `write()` Copied from I2PClientImpl.createDestination()

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- - ### Field Detail

    - #### dest

          protected Destination dest

    - #### file

          protected final File file

    - #### privKey

          protected PrivateKey privKey

    - #### signingPrivKey

          protected SigningPrivateKey signingPrivKey

  - ### Constructor Detail

    - #### PrivateKeyFile

          public PrivateKeyFile(File file)

    - #### PrivateKeyFile

          public PrivateKeyFile(File file,
                                Destination dest,
                                PrivateKey pk,
                                SigningPrivateKey spk)

      Throws:
        `IllegalArgumentException` - on mismatch of spubkey and spk types

    - #### PrivateKeyFile

          public PrivateKeyFile(File file,
                                I2PClient client)

    - #### PrivateKeyFile

          public PrivateKeyFile(File file,
                                I2PSession session)

    - #### PrivateKeyFile

          public PrivateKeyFile(File file,
                                PublicKey pubkey,
                                SigningPublicKey spubkey,
                                Certificate cert,
                                PrivateKey pk,
                                SigningPrivateKey spk)

      Throws:
        `IllegalArgumentException` - on mismatch of spubkey and spk types

    - #### PrivateKeyFile

          public PrivateKeyFile(File file,
                                PublicKey pubkey,
                                SigningPublicKey spubkey,
                                Certificate cert,
                                PrivateKey pk,
                                SigningPrivateKey spk,
                                byte[] padding)

      Parameters:
        `padding` - null OK, must be non-null if spubkey length < 128
      Throws:
        `IllegalArgumentException` - on mismatch of spubkey and spk types

    - #### PrivateKeyFile

          public PrivateKeyFile(InputStream in)
                         throws I2PSessionException

      Can't be used for writing
      Throws:
        `I2PSessionException`

    - #### PrivateKeyFile

          public PrivateKeyFile(String file)

  - ### Method Detail

    - #### checkSignature

          public static boolean checkSignature(Signature s,
                                               byte[] data,
                                               SigningPublicKey spk)

    - #### createIfAbsent

          public Destination createIfAbsent()
                                     throws I2PException,
                                            IOException,
                                            DataFormatException

      Create with the default signature type if nonexistent. Also reads in the file to get the privKey and signingPrivKey, which aren't available from I2PClient.
      Throws:
        `I2PException`
        `IOException`
        `DataFormatException`

    - #### createIfAbsent

          public Destination createIfAbsent(SigType type)
                                     throws I2PException,
                                            IOException,
                                            DataFormatException

      Create with the specified signature type if nonexistent. Also reads in the file to get the privKey and signingPrivKey, which aren't available from I2PClient.
      Throws:
        `I2PException`
        `IOException`
        `DataFormatException`

    - #### getDestination

          public Destination getDestination()
                                     throws I2PSessionException,
                                            IOException,
                                            DataFormatException

      If the destination is not set, read it in from the file. Also sets the local privKey and signingPrivKey.
      Throws:
        `I2PSessionException`
        `IOException`
        `DataFormatException`

    - #### getOfflineExpiration

          public long getOfflineExpiration()

      Returns:
        Java time (ms) or 0 if not initialized or does not have offline keys

    - #### getOfflineSignature

          public Signature getOfflineSignature()

    - #### getSigningPrivKey

          public SigningPrivateKey getSigningPrivKey()

      Returns:
        null on error or if not initialized

    - #### getTransientSigningPrivKey

          public SigningPrivateKey getTransientSigningPrivKey()

      Returns:
        null on error or if not initialized or does not have offline keys

    - #### getTransientSigningPubKey

          public SigningPublicKey getTransientSigningPubKey()

      Returns:
        null on error or if not initialized or does not have offline keys

    - #### isOffline

          public boolean isOffline()

      Does this session have offline and transient keys?

    - #### main

          public static void main(String[] args)

      Create a new PrivateKeyFile, or modify an existing one, with various types of Certificates. Changing a Certificate does not change the public or private keys. But it does change the Destination Hash, which effectively makes it a new Destination. In other words, don't change the Certificate on a Destination you've already registered in a hosts.txt key add form. Copied and expanded from that in Destination.java

    - #### open

          public I2PSession open()
                          throws I2PSessionException,
                                 IOException

      Throws:
        `I2PSessionException`
        `IOException`

    - #### open

          public I2PSession open(Properties opts)
                          throws I2PSessionException,
                                 IOException

      Throws:
        `I2PSessionException`
        `IOException`

    - #### setCertType

          public Certificate setCertType(int t)

      Change cert type - caller must also call write(). Side effect - creates new Destination object.

    - #### setDestination

          public void setDestination(Destination d)

    - #### setKeyCert

          public Certificate setKeyCert(SigType type)

      Change cert type - caller must also call write(). Side effect - creates new Destination object.

    - #### setOfflineData

          public void setOfflineData(long expires,
                                     SigningPublicKey transientPub,
                                     Signature sig,
                                     SigningPrivateKey transientPriv)

      Side effect - zeroes out the current signing private key

    - #### setSignedCert

          public Certificate setSignedCert(PrivateKeyFile pkf2)

      sign this dest by dest found in pkf2 - caller must also call write()

    - #### toString

          public String toString()

      Overrides:
        `toString` in class `Object`

    - #### validateKeyPairs

          public boolean validateKeyPairs()

      Verify that the PublicKey matches the PrivateKey, and the SigningPublicKey matches the SigningPrivateKey. NOTE this will fail for Destinations containing random padding for the enc. key
      Returns:
        success

    - #### verifySignature

          public static boolean verifySignature(Destination d)

      Sample code to verify a 3rd party signature. This just goes through all the hosts.txt files and tries everybody. You need to be in the $I2P directory or have a local hosts.txt for this to work. Doubt this is what you want as it is super-slow, and what good is a signing scheme where anybody is allowed to sign? In a real application you would make a list of approved signers, do a naming lookup to get their Destinations, and try those only. Or do a netDb lookup of the Hash in the Certificate, do a reverse naming lookup to see if it is allowed, then verify the Signature.

    - #### write

          public void write()
                     throws IOException,
                            DataFormatException

      Copied from I2PClientImpl.createDestination()
      Throws:
        `IOException`
        `DataFormatException`