java.lang.Object
com.southernstorm.noise.protocol.HandshakeState
All Implemented Interfaces:
Destroyable, Cloneable

public class HandshakeStateextends Object implements Destroyable, Cloneable
Interface to a Noise handshake.
  • Field Details

    • symmetric

      private final SymmetricState symmetric
      The symmetric state carrying the keys.
    • isInitiator

      private final boolean isInitiator
      True for the initiator of the handshake.
    • localKeyPair

      private DHState localKeyPair
      Our static key pair for the handshake.
    • localEphemeral

      private DHState localEphemeral
      Our ephemeral key pair for the handshake.
    • localHybrid

      private DHState localHybrid
      Our hybrid key pair for the handshake.
    • remotePublicKey

      private DHState remotePublicKey
      The peer's static key, once received.
    • remoteEphemeral

      private DHState remoteEphemeral
      The peer's ephemeral key, once received.
    • remoteHybrid

      private DHState remoteHybrid
      The peer's hybrid key, once received.
    • action

      private int action
      The next action allowed in the pattern.
    • requirements

      private final int requirements
      The key types the pattern requires.
    • patternIndex

      private int patternIndex
      Position within the pattern tokens.
    • wasCloned

      private boolean wasCloned
      True once the state was cloned for writing.
    • isDestroyed

      private boolean isDestroyed
      True once the state was destroyed.
    • INITIATOR

      public static final int INITIATOR
      Enumerated value that indicates that the handshake object is handling the initiator role.
      See Also:
    • RESPONDER

      public static final int RESPONDER
      Enumerated value that indicates that the handshake object is handling the responder role.
      See Also:
    • NO_ACTION

      public static final int NO_ACTION
      No action is required of the application yet because the handshake has not started.
      See Also:
    • WRITE_MESSAGE

      public static final int WRITE_MESSAGE
      The HandshakeState expects the application to write the next message payload for the handshake.
      See Also:
    • READ_MESSAGE

      public static final int READ_MESSAGE
      The HandshakeState expects the application to read the next message payload from the handshake.
      See Also:
    • FAILED

      public static final int FAILED
      The handshake has failed due to some kind of error.
      See Also:
    • SPLIT

      public static final int SPLIT
      The handshake is over and the application is expected to call split() and begin data session communications.
      See Also:
    • COMPLETE

      public static final int COMPLETE
      The handshake is complete and the data session ciphers have been split() out successfully.
      See Also:
    • STATE_NAMES

      private static final String[] STATE_NAMES
      I2P for debugging
    • LOCAL_REQUIRED

      private static final int LOCAL_REQUIRED
      Local static keypair is required for the handshake.
      See Also:
    • REMOTE_REQUIRED

      private static final int REMOTE_REQUIRED
      Remote static keypai is required for the handshake.
      See Also:
    • PSK_REQUIRED

      private static final int PSK_REQUIRED
      Pre-shared key is required for the handshake.
      See Also:
    • FALLBACK_PREMSG

      private static final int FALLBACK_PREMSG
      Ephemeral key for fallback pre-message has been provided.
      See Also:
    • LOCAL_PREMSG

      private static final int LOCAL_PREMSG
      The local public key is part of the pre-message.
      See Also:
    • REMOTE_PREMSG

      private static final int REMOTE_PREMSG
      The remote public key is part of the pre-message.
      See Also:
    • FALLBACK_POSSIBLE

      private static final int FALLBACK_POSSIBLE
      Fallback is possible from this pattern (two-way, ends in "K").
      See Also:
    • protocolName

      public static final String protocolName
      NTCP2
      See Also:
    • protocolName2

      public static final String protocolName2
      Ratchet
      See Also:
    • protocolName3

      public static final String protocolName3
      Tunnels
      See Also:
    • protocolName4

      public static final String protocolName4
      SSU2
      See Also:
    • protocolName5

      public static final String protocolName5
      Hybrid Ratchet
      See Also:
    • protocolName6

      public static final String protocolName6
      protocolName6.
      See Also:
    • protocolName7

      public static final String protocolName7
      protocolName7.
      See Also:
    • protocolName8

      public static final String protocolName8
      Hybrid NTCP2
      See Also:
    • protocolName9

      public static final String protocolName9
      protocolName9.
      See Also:
    • protocolName10

      public static final String protocolName10
      protocolName10.
      See Also:
    • protocolName11

      public static final String protocolName11
      Hybrid SSU2
      See Also:
    • protocolName12

      public static final String protocolName12
      protocolName12.
      See Also:
    • patternId

      private final NoiseInit.PatternID patternId
      The handshake pattern being run.
    • PATTERN_ID_XK

      public static final String PATTERN_ID_XK
      NTCP2
      See Also:
    • PATTERN_ID_IK

      public static final String PATTERN_ID_IK
      Ratchet
      See Also:
    • PATTERN_ID_N

      public static final String PATTERN_ID_N
      Tunnels
      See Also:
    • PATTERN_ID_N_NO_RESPONSE

      public static final String PATTERN_ID_N_NO_RESPONSE
      same as N but no post-mixHash needed
      See Also:
    • PATTERN_ID_XK_SSU2

      public static final String PATTERN_ID_XK_SSU2
      SSU2
      See Also:
    • PATTERN_ID_IKHFS

      private static final String PATTERN_ID_IKHFS
      Hybrid Base
      See Also:
    • PATTERN_ID_XKHFS

      private static final String PATTERN_ID_XKHFS
      Name of the I2P ratchet handshake pattern.
      See Also:
    • PATTERN_ID_IKHFS_512

      public static final String PATTERN_ID_IKHFS_512
      Hybrid Ratchet
      See Also:
    • PATTERN_ID_IKHFS_768

      public static final String PATTERN_ID_IKHFS_768
      PATTERN_ID_IKHFS_768.
      See Also:
    • PATTERN_ID_IKHFS_1024

      public static final String PATTERN_ID_IKHFS_1024
      PATTERN_ID_IKHFS_1024.
      See Also:
    • PATTERN_ID_XKHFS_512

      public static final String PATTERN_ID_XKHFS_512
      Hybrid NTCP2
      See Also:
    • PATTERN_ID_XKHFS_768

      public static final String PATTERN_ID_XKHFS_768
      PATTERN_ID_XKHFS_768.
      See Also:
    • PATTERN_ID_XKHFS_1024

      public static final String PATTERN_ID_XKHFS_1024
      PATTERN_ID_XKHFS_1024.
      See Also:
    • PATTERN_ID_XKHFS_512_SSU2

      public static final String PATTERN_ID_XKHFS_512_SSU2
      Hybrid SSU2
      See Also:
    • PATTERN_ID_XKHFS_768_SSU2

      public static final String PATTERN_ID_XKHFS_768_SSU2
      PATTERN_ID_XKHFS_768_SSU2.
      See Also:
    • pattern

      private final short[] pattern
      The token list of the handshake pattern.
    • emptyPrologue

      private static final byte[] emptyPrologue
      The empty prologue used when none is set.
  • Constructor Details

    • HandshakeState

      public HandshakeState(NoiseInit.PatternID patternId, int role, KeyFactory xdh) throws NoSuchAlgorithmException
      Creates a new Noise handshake. Noise protocol name is hardcoded. Not for PQ Alice side.
      Parameters:
      patternId - XK, IK, or N
      role - The role, HandshakeState.INITIATOR or HandshakeState.RESPONDER.
      xdh - The key pair factory for ephemeral keys
      Throws:
      IllegalArgumentException - The protocolName is not formatted correctly, or the role is not recognized.
      NoSuchAlgorithmException - One of the cryptographic algorithms that is specified in the protocolName is not supported.
    • HandshakeState

      public HandshakeState(NoiseInit.PatternID patternId, int role, KeyFactory xdh, KeyFactory hdh) throws NoSuchAlgorithmException
      Creates a new Noise handshake. Noise protocol name is hardcoded.
      Parameters:
      patternId - XK, IK, or N
      role - The role, HandshakeState.INITIATOR or HandshakeState.RESPONDER.
      xdh - The key pair factory for ephemeral keys
      hdh - The key pair factory for hybrid keys, Alice side only, or null for Bob or non-hybrid
      Throws:
      IllegalArgumentException - The protocolName is not formatted correctly, or the role is not recognized.
      NoSuchAlgorithmException - One of the cryptographic algorithms that is specified in the protocolName is not supported.
    • HandshakeState

      protected HandshakeState(HandshakeState o) throws CloneNotSupportedException
      Copy constructor for cloning
      Parameters:
      o - the state to clone, whose symmetric state and DH key pairs are copied
      Throws:
      CloneNotSupportedException - if the handshake has already split or completed
  • Method Details

    • getProtocolName

      public String getProtocolName()
      Gets the name of the Noise protocol.
      Returns:
      The protocol name.
    • getRole

      public int getRole()
      Gets the role for this handshake.
      Returns:
      The role, HandshakeState.INITIATOR or HandshakeState.RESPONDER.
    • getLocalKeyPair

      public DHState getLocalKeyPair()
      Gets the keypair object for the local static key.
      Returns:
      The keypair, or null if a local static key is not required.
    • getLocalEphemeralKeyPair

      public DHState getLocalEphemeralKeyPair()
      Gets the keypair object for the local ephemeral key. I2P
      Returns:
      The keypair, or null if a local ephemeral key is not required or has not been generated.
    • needsLocalKeyPair

      public boolean needsLocalKeyPair()
      Determine if this handshake requires a local static key.
      Returns:
      true if a local static key is needed; false if not. If the local static key has already been set, then this function will return false.
    • hasLocalKeyPair

      public boolean hasLocalKeyPair()
      Determine if this handshake has already been configured with a local static key.
      Returns:
      true if the local static key has been configured; false if not.
    • getRemotePublicKey

      public DHState getRemotePublicKey()
      Gets the public key object for the remote static key.
      Returns:
      The public key, or null if a remote static key is not required.
    • needsRemotePublicKey

      public boolean needsRemotePublicKey()
      Determine if this handshake requires a remote static key.
      Returns:
      true if a remote static key is needed; false if not. If the remote static key has already been set, then this function will return false.
    • hasRemotePublicKey

      public boolean hasRemotePublicKey()
      Determine if this handshake has already been configured with a remote static key.
      Returns:
      true if the remote static key has been configured; false if not.
    • getLocalHybridKeyPair

      public DHState getLocalHybridKeyPair()
      Gets the keypair object for the local hybrid key. I2P
      Returns:
      The keypair, or null if a local hybrid key is not required or has not been generated.
    • getRemoteHybridKeyPair

      public DHState getRemoteHybridKeyPair()
      Gets the keypair object for the remote hybrid key. I2P
      Returns:
      The keypair, or null if a remote hybrid key is not required or has not been generated.
    • start

      public void start()
      Starts the handshake running. This function is called after all of the handshake parameters have been provided to the HandshakeState object. This function should be followed by calls to writeMessage() or readMessage() to process the handshake messages. The getAction() function indicates the action to take next.
      Throws:
      IllegalStateException - The handshake has already started, or one or more of the required parameters has not been supplied.
      UnsupportedOperationException - An attempt was made to start a fallback handshake pattern without first calling fallback() on a previous handshake.
      See Also:
    • getAction

      public int getAction()
      Gets the next action that the application should perform for the handshake part of the protocol.
      Returns:
      One of HandshakeState.NO_ACTION, HandshakeState.WRITE_MESSAGE, HandshakeState.READ_MESSAGE, HandshakeState.SPLIT, or HandshakeState.FAILED.
    • mixDH

      private void mixDH(DHState local, DHState remote)
      Mixes the result of a Diffie-Hellman calculation into the chaining key.
      Parameters:
      local - Local private key object.
      remote - Remote public key object.
    • writeMessage

      public int writeMessage(byte[] message, int messageOffset, byte[] payload, int payloadOffset, int payloadLength) throws ShortBufferException
      Writes a message payload during the handshake. Payload (plaintext) and message (encrypted) may be in the same buffer if the payload if offset enough past the message offset to leave room for the key(s) and/or MAC. For 32 byte keys and 16 byte MACs, if message == payload, payloadOffset must be at least this much greater than messageOffset: XK: Message 1: 32; message 2: 32; message 3: 48 IK: Message 1: 80; message 2: 48 N: Message 1: 32
      Parameters:
      message - The buffer that will be populated with the handshake packet to be written to the transport.
      messageOffset - First offset within the message buffer to be populated.
      payload - Buffer containing the payload to add to the handshake message; can be null if there is no payload.
      payloadOffset - Offset into the payload buffer of the first payload buffer.
      payloadLength - Length of the payload in bytes.
      Returns:
      The length of the data written to the message buffer.
      Throws:
      IllegalStateException - The action is not WRITE_MESSAGE.
      IllegalArgumentException - The payload is null, but payloadOffset or payloadLength is non-zero.
      ShortBufferException - The message buffer does not have enough space for the handshake message.
      See Also:
    • readMessage

      public int readMessage(byte[] message, int messageOffset, int messageLength, byte[] payload, int payloadOffset) throws ShortBufferException, BadPaddingException
      Reads a message payload during the handshake. Payload (plaintext) and message (encrypted) may be in the same buffer and have the same offset.
      Parameters:
      message - Buffer containing the incoming handshake that was read from the transport.
      messageOffset - Offset of the first message byte.
      messageLength - The length of the incoming message.
      payload - Buffer that will be populated with the message payload.
      payloadOffset - Offset of the first byte in the payload buffer to be populated with payload data.
      Returns:
      The length of the payload.
      Throws:
      IllegalStateException - The action is not READ_MESSAGE.
      ShortBufferException - The message buffer does not have sufficient bytes for a valid message or the payload buffer does not have enough space for the decrypted payload.
      BadPaddingException - A MAC value in the message failed to verify.
      See Also:
    • split

      public CipherStatePair split()
      Splits the transport encryption CipherState objects out of this HandshakeState object once the handshake completes.
      Returns:
      The pair of ciphers for sending and receiving.
      Throws:
      IllegalStateException - The action is not SPLIT.
    • split

      public CipherStatePair split(byte[] secondaryKey, int offset, int length)
      Splits the transport encryption CipherState objects out of this HandshakeObject after mixing in a secondary symmetric key.
      Parameters:
      secondaryKey - The buffer containing the secondary key.
      offset - The offset of the first secondary key byte.
      length - The length of the secondary key in bytes, which must be either 0 or 32.
      Returns:
      The pair of ciphers for sending and receiving.
      Throws:
      IllegalStateException - The action is not SPLIT.
      IllegalArgumentException - The length is not 0 or 32.
    • getHandshakeHash

      public byte[] getHandshakeHash()
      Gets the current value of the handshake hash.
      Returns:
      The handshake hash. This must not be modified by the caller.
      Throws:
      IllegalStateException - The action is not SPLIT or COMPLETE.
    • destroy

      public void destroy()
      Marks this state destroyed and destroys the symmetric state and keys.
      Specified by:
      destroy in interface Destroyable
    • computeRequirements

      private static int computeRequirements(short flags, String prefix, int role, boolean isFallback)
      Computes the requirements for a handshake.
      Parameters:
      flags - The flags from the handshake's pattern.
      prefix - The prefix from the protocol name; typically "Noise" or "NoisePSK".
      role - The role, HandshakeState.INITIATOR or HandshakeState.RESPONDER.
      isFallback - Set to true if we need the requirements for a fallback pattern; false for a regular pattern.
      Returns:
      The set of requirements for the handshake.
    • mixHash

      public void mixHash(byte[] data, int offset, int length)
      I2P for mixing in padding in messages 1 and 2
      Parameters:
      data - the buffer holding the bytes to mix into the handshake hash
      offset - index into data of the first byte to mix in
      length - count of bytes to mix in starting at offset
    • getChainingKey

      public byte[] getChainingKey()
      I2P for getting chaining key for siphash calc
      Returns:
      a copy of the current chaining key, not the internal array
    • clone

      I2P Must be called before both eph. keys set.
      Overrides:
      clone in class Object
      Throws:
      CloneNotSupportedException
    • toString

      public String toString()
      I2P debug
      Overrides:
      toString in class Object