java.lang.Object
net.i2p.router.crypto.ratchet.ECIESAEADEngine

public final class ECIESAEADEngineextends Object
ECIES+AEAD encryption engine providing New Session, New Session Reply, and Existing Session message handling

No, this does not extend ElGamalAESEngine or AEADEngine or CryptixAEADEngine.

  • Field Details

    • _context

      private final RouterContext _context
      The router context.
    • _log

      private final Log _log
      Logger for ratchet decryption.
    • _muxedEngine

      private final MuxedEngine _muxedEngine
      Engine for the legacy muxed encryption types.
    • _muxedPQEngine

      private final MuxedPQEngine _muxedPQEngine
      Engine for the post-quantum muxed types.
    • _hkdf

      private final HKDF _hkdf
      Key derivation function for the ratchet.
    • _edhThread

      private final Elg2KeyFactory _edhThread
      Key factory for the X25519 ratchet.
    • _mlkem768Thread

      private MLKEMKeyFactory _mlkem768Thread
      Key factory for ML-KEM 768, started on demand.
    • _isRunning

      private volatile boolean _isRunning
      True while the engine is running.
    • ZEROLEN

      private static final byte[] ZEROLEN
      Shared empty array for zero-length values.
    • TAGLEN

      private static final int TAGLEN
      Length of a short ratchet tag, in bytes.
      See Also:
    • MACLEN

      private static final int MACLEN
      Length of a truncated MAC, in bytes.
      See Also:
    • KEYLEN

      private static final int KEYLEN
      Length of an X25519 key, in bytes.
      See Also:
    • BHLEN

      private static final int BHLEN
      Length of a block header, in bytes.
      See Also:
    • DATETIME_SIZE

      private static final int DATETIME_SIZE
      Size of a datetime block, in bytes.
      See Also:
    • NS_OVERHEAD

      private static final int NS_OVERHEAD
      Overhead of a NS-encrypted payload, in bytes.
      See Also:
    • NS_N_OVERHEAD

      private static final int NS_N_OVERHEAD
      Overhead of an NS-N encrypted payload, in bytes.
      See Also:
    • NSR_OVERHEAD

      private static final int NSR_OVERHEAD
      Overhead of an NSR-encrypted payload, in bytes.
      See Also:
    • ES_OVERHEAD

      private static final int ES_OVERHEAD
      Overhead of an ES-encrypted payload, in bytes.
      See Also:
    • MIN_NS_SIZE

      static final int MIN_NS_SIZE
      Minimum new-session message size in bytes (103).
      See Also:
    • MIN_NS_N_SIZE

      private static final int MIN_NS_N_SIZE
      Smallest valid NS-N encrypted payload, in bytes.
      See Also:
    • MIN_NSR_SIZE

      private static final int MIN_NSR_SIZE
      Smallest valid NSR-encrypted payload, in bytes.
      See Also:
    • MIN_ES_SIZE

      private static final int MIN_ES_SIZE
      Smallest valid ES-encrypted payload, in bytes.
      See Also:
    • MIN_ENCRYPTED_SIZE

      private static final int MIN_ENCRYPTED_SIZE
      Smallest payload any encryption type accepts.
      See Also:
    • NULLPK

      private static final byte[] NULLPK
      All-zero public key for comparisons.
    • MAXPAD

      private static final int MAXPAD
      Maximum padding added to an encrypted payload.
      See Also:
    • MAX_NS_AGE

      static final long MAX_NS_AGE
      Maximum age of a New Session request in ms.
      See Also:
    • MAX_NS_FUTURE

      private static final long MAX_NS_FUTURE
      An NS datetime may be up to 2 minutes in the future.
      See Also:
    • ACKREQ_IN_ES

      private static final boolean ACKREQ_IN_ES
      Debug flag to send an ACKREQ in every ES.
      See Also:
    • NO_GARLIC

      private static final GarlicClove[] NO_GARLIC
      Empty clove array for failed ElGamal decryptions.
    • NO_CLOVES

      private static final CloveSet NO_CLOVES
      Empty clove set returned on failure.
    • INFO_6

      private static final String INFO_6
      HKDF info string for the attach payload key.
      See Also:
    • RATES

      private static final long[] RATES
      Rate stat period for the decryption statistics.
    • NS_MLKEM_OVERHEAD

      private static final int NS_MLKEM_OVERHEAD
      Next session overhead for the ML-KEM types: 112 bytes.
      See Also:
    • MIN_NS_MLKEM512_SIZE

      static final int MIN_NS_MLKEM512_SIZE
      Minimum ML-KEM-512 new-session message size, 800 + 112 + 7 = 919 bytes.
    • MIN_NS_MLKEM768_SIZE

      static final int MIN_NS_MLKEM768_SIZE
      Minimum ML-KEM-768 new-session message size, 1184 + 112 + 7 = 1303 bytes.
    • MIN_NS_MLKEM1024_SIZE

      static final int MIN_NS_MLKEM1024_SIZE
      Minimum ML-KEM-1024 new-session message size, 1568 + 112 + 7 = 1687 bytes.
    • MIN_NSR_MLKEM512_SIZE

      private static final int MIN_NSR_MLKEM512_SIZE
      Smallest next session request with ML-KEM-512: 856 bytes.
    • MIN_NSR_MLKEM768_SIZE

      private static final int MIN_NSR_MLKEM768_SIZE
      Smallest next session request with ML-KEM-768: 1176 bytes.
    • MIN_NSR_MLKEM1024_SIZE

      private static final int MIN_NSR_MLKEM1024_SIZE
      Smallest next session request with ML-KEM-1024: 1656 bytes.
    • _chachaLocal

      private static final ThreadLocal<ChaChaPolyCipherState> _chachaLocal
      Per-thread ChaCha-Poly cipher state, reused to avoid per-decrypt allocation.
    • B1

      private static final int B1
      First size bucket for the padding distribution.
      See Also:
    • B2

      private static final int B2
      Second size bucket for the padding distribution.
      See Also:
    • B3

      private static final int B3
      Third size bucket for the padding distribution.
      See Also:
    • _blockPool

      private static final ThreadLocal<ECIESAEADEngine.BlockPool> _blockPool
      Per-thread pool of ratchet payload blocks.
  • Constructor Details

    • ECIESAEADEngine

      public ECIESAEADEngine(RouterContext ctx)
      Caller MUST call startup() to get threaded generation. Will still work without, will just generate inline.

      startup() is called from RatchetSKM constructor so it's deferred until we need it.

      Parameters:
      ctx - the router context used to obtain the log, stats and sub-engines
  • Method Details

    • startup

      public void startup()
      May be called multiple times.
    • shutdown

      public void shutdown()
      Cannot be restarted.
    • decrypt

      public CloveSet decrypt(byte[] data, PrivateKey elgKey, PrivateKey ecKey, MuxedSKM keyManager) throws DataFormatException
      Try to decrypt the message with one or both of the given private keys.
      Parameters:
      data - the encrypted CloveSet to decrypt
      elgKey - must be ElG, non-null
      ecKey - must be EC, non-null
      keyManager - holds the session key material and ratchet preference
      Returns:
      decrypted data or null on failure
      Throws:
      DataFormatException - if the underlying garlic parse fails and cannot be recovered by trying the remaining crypto schemes
    • decrypt

      public CloveSet decrypt(byte[] data, PrivateKey ecKey, PrivateKey pqKey, MuxedPQSKM keyManager) throws DataFormatException
      Try to decrypt the message with one or both of the given private keys.
      Parameters:
      data - the encrypted CloveSet to decrypt
      ecKey - must be EC, non-null
      pqKey - must be PQ, non-null
      keyManager - holds the session key material and ratchet preference
      Returns:
      decrypted data or null on failure
      Throws:
      DataFormatException - if the data is malformed
    • decrypt

      public CloveSet decrypt(byte[] data, PrivateKey targetPrivateKey, RatchetSKM keyManager) throws DataFormatException
      Decrypt the message using the given private key and using tags from the specified key manager. This works according to the ECIES+AEAD algorithm in the data structure spec.

      Warning - use the correct SessionKeyManager. Clients should instantiate their own. Clients using I2PAppContext.sessionKeyManager() may be correlated with the router, unless you are careful to use different keys.

      Parameters:
      data - the encrypted CloveSet to decrypt
      targetPrivateKey - private key matching the encryption type of the data
      keyManager - holds the session tags and key material used to decrypt
      Returns:
      decrypted data or null on failure
      Throws:
      DataFormatException - if the underlying garlic parse fails and cannot be recovered by trying the remaining crypto schemes
    • x_decrypt

      private CloveSet x_decrypt(byte[] data, PrivateKey targetPrivateKey, RatchetSKM keyManager) throws DataFormatException
      Decrypts a received message into cloves.
      Parameters:
      data - the message bytes
      targetPrivateKey - the key to decrypt with
      keyManager - the manager of the session keys
      Returns:
      the decrypted clove set
      Throws:
      DataFormatException - if the message is invalid
    • decryptFast

      CloveSet decryptFast(byte[] data, PrivateKey targetPrivateKey, RatchetSKM keyManager) throws DataFormatException
      NSR/ES only. For MuxedEngine use only.
      Parameters:
      data - the encrypted CloveSet to decrypt
      targetPrivateKey - private key matching the encryption type of the data
      keyManager - holds the session tags and key material used to decrypt
      Returns:
      the decrypted cloves, null if no key was found for the tag, or an empty set if the decrypt or the payload parse failed
      Throws:
      DataFormatException - if the payload cannot be parsed as a garlic clove set
    • x_decryptFast

      private CloveSet x_decryptFast(byte[] data, PrivateKey targetPrivateKey, RatchetSKM keyManager) throws DataFormatException
      NSR/ES only.
      Parameters:
      data - the encrypted NewSessionReply or ExistingSession message
      targetPrivateKey - our private key matching the message's encryption type
      keyManager - the key manager whose session tags are searched for the tag
      Returns:
      the decrypted cloves, or null if the 8-byte tag is unknown or the data is below the minimum size
      Throws:
      DataFormatException - if the payload cannot be parsed as a garlic clove set
    • xx_decryptFast

      private CloveSet xx_decryptFast(byte[] tag, RatchetSessionTag st, SessionKeyAndNonce key, byte[] data, PrivateKey targetPrivateKey, RatchetSKM keyManager) throws DataFormatException
      NSR/ES only.
      Parameters:
      tag - the 8-byte session tag copied out of the start of data
      st - the session tag object built from those 8 bytes
      key - non-null key and nonce the key manager holds for that tag
      data - the encrypted NewSessionReply or ExistingSession message
      targetPrivateKey - our private key matching the message's encryption type
      keyManager - holds the session tags and key material used to decrypt
      Returns:
      the decrypted cloves, or null if the reply is too short or the MAC check fails
      Throws:
      DataFormatException - if the payload cannot be parsed as a garlic clove set
    • decryptSlow

      CloveSet decryptSlow(byte[] data, PrivateKey targetPrivateKey, RatchetSKM keyManager) throws DataFormatException
      NS only. For MuxedEngine use only.
      Parameters:
      data - the encrypted CloveSet to decrypt
      targetPrivateKey - private key matching the encryption type of the data
      keyManager - holds the session tags and key material used to decrypt
      Returns:
      decrypted data or null on failure
      Throws:
      DataFormatException - if the payload cannot be parsed as a garlic clove set
    • x_decryptSlow

      private CloveSet x_decryptSlow(byte[] data, PrivateKey targetPrivateKey, RatchetSKM keyManager) throws DataFormatException
      NS only.
      Parameters:
      data - the encrypted NewSession or NewSession/LeaseSet message
      targetPrivateKey - our private key matching the message's encryption type
      keyManager - holds the session tags and key material; a null destination marks the router variant, NewSession_N
      Returns:
      the decrypted cloves, or null if the data is below the minimum size for the key type or the decrypt fails
      Throws:
      DataFormatException - if the payload cannot be parsed as a garlic clove set
    • checkType

      private static void checkType(EncType type)
      Verify the encryption type is supported by this engine.
      Parameters:
      type - the encryption type this engine must be able to handle
      Throws:
      IllegalArgumentException - if type is not one this engine handles
    • getNoisePattern

      private static NoiseInit.PatternID getNoisePattern(EncType type)
      The Noise handshake pattern for the given encryption type.
      Parameters:
      type - the encryption type to select a handshake pattern for
      Returns:
      IK for X25519, or IKHFS_n for the matching ML-KEM hybrid type
      Throws:
      IllegalArgumentException - if no pattern is defined for the type
    • getHybridKeyFactory

      public KeyFactory getHybridKeyFactory(EncType type)
      The hybrid key factory for the given encryption type, or null if not a hybrid type.
      Parameters:
      type - the hybrid encryption type to get a key factory for
      Returns:
      the hybrid key factory
    • getMinNSSize

      private static int getMinNSSize(EncType type)
      The minimum New Session message size for the given encryption type.
      Parameters:
      type - the encryption type whose New Session minimum is wanted
      Returns:
      the minimum new-session message size in bytes for this type
      Throws:
      IllegalArgumentException - if no minimum is defined for the type
    • getMinNSRSize

      private static int getMinNSRSize(EncType type)
      The minimum New Session Reply message size for the given encryption type.
      Parameters:
      type - the encryption type whose reply minimum is wanted
      Returns:
      the minimum new-session-reply message size in bytes for this type
      Throws:
      IllegalArgumentException - if no minimum is defined for the type
    • getEncTypeSet

      private static Set<EncType> getEncTypeSet(EncType type)
      The lease set key types that go with the given encryption type.
      Parameters:
      type - the encryption type to map to a lease set key set
      Returns:
      the LeaseSetKeys set for that type, one of SET_EC, SET_PQ1, SET_PQ2 or SET_PQ3
      Throws:
      IllegalArgumentException - if no set is defined for the type
    • decryptNewSession

      private CloveSet decryptNewSession(byte[] data, PrivateKey targetPrivateKey, RatchetSKM keyManager) throws DataFormatException
      Scenario 1: New Session Message

      Begin with 80 bytes, ECIES encrypted, containing:

      - 32 byte Elligator2 key
      - 32 byte static key
      - 16 byte MAC
      
      And then the data:
      - payload (7 bytes minimum for DateTime block)
      - 16 byte MAC
      
      Parameters:
      data - 103 bytes minimum
      targetPrivateKey - our private key matching the message's encryption type
      keyManager - holds the ephemeral-key replay cache and receives the new session on success
      Returns:
      the decrypted cloves, null if the Elligator2 decode or the handshake fails, or an empty set for a replayed key or a payload with no garlic
      Throws:
      DataFormatException - if the decrypted payload blocks cannot be parsed
    • decryptNewSession_N

      private CloveSet decryptNewSession_N(byte[] data, PrivateKey targetPrivateKey, RatchetSKM keyManager) throws DataFormatException
      Scenario 1A: New Session Message Anonymous.
      - 32 byte ephemeral key (NOT Elligator2)
      - payload (7 bytes minimum for DateTime block)
      - 16 byte MAC
      
      Parameters:
      data - 55 bytes minimum
      targetPrivateKey - our private key matching the message's encryption type
      keyManager - holds the ephemeral-key replay cache checked before the DH work
      Returns:
      the decrypted cloves, null if the key or the handshake check fails, or an empty set for a replayed key or a payload with no garlic
      Throws:
      DataFormatException - if the decrypted payload blocks cannot be parsed
    • decryptNewSessionReply

      private CloveSet decryptNewSessionReply(byte[] tag, byte[] data, HandshakeState oldState, RatchetSKM keyManager) throws DataFormatException
      Scenario 2: New Session Reply Message

      Begin with 56 bytes, containing:

      - 8 byte SessionTag
      - 32 byte Elligator2 key
      - 16 byte MAC
      
      And then the data:
      - payload
      - 16 byte MAC
      
      Parameters:
      tag - 8 bytes, same as first 8 bytes of data
      data - 72 bytes minimum
      oldState - will be cloned here, then destroyed on failure
      keyManager - the session key manager for this handshake
      Returns:
      the decrypted cloves, null if the state clone, the Elligator2 decode or part 1 fails, or an empty set if the payload MAC fails or the payload has no garlic block
      Throws:
      DataFormatException - if the decrypted payload blocks cannot be parsed
    • decryptExistingSession

      private CloveSet decryptExistingSession(byte[] tag, byte[] data, SessionKeyAndNonce key, PrivateKey _targetPrivateKey, RatchetSKM keyManager) throws DataFormatException
      Scenario 3: Existing Session Message.
      - 8 byte SessionTag
      - payload
      - 16 byte MAC
      

      If anything doesn't match up in decryption, it returns null

      Parameters:
      tag - 8 bytes for ad, same as first 8 bytes of data
      data - 24 bytes minimum, first 8 bytes will be skipped
      key - the session key and nonce the key manager holds for that tag
      _targetPrivateKey - our private key, unused as the session key is set up
      keyManager - for ack callbacks
      Returns:
      the decrypted cloves, null if the MAC check fails, or an empty set if the payload is empty or carries no garlic block
      Throws:
      DataFormatException - if the decrypted payload blocks cannot be parsed
    • decryptAEADBlock

      private boolean decryptAEADBlock(byte[] ad, byte[] encrypted, int offset, int encryptedLen, SessionKey key, long n)
      With optional AD. Decrypts IN PLACE. Decrypted data will be at encrypted[offset:offset + len - 16].
      Parameters:
      ad - optional associated data, may be null
      encrypted - the ciphertext, overwritten in place with the plaintext
      offset - where the ciphertext starts in encrypted
      encryptedLen - bytes to decrypt at offset, including the 16-byte MAC
      key - the 32-byte ChaCha20-Poly1305 key to decrypt with
      n - the nonce for this message, taken from the session key's counter
      Returns:
      true if the MAC verified and the data was decrypted in place
    • encrypt

      public byte[] encrypt(CloveSet cloves, PublicKey target, Destination to, PrivateKey priv, RatchetSKM keyManager, ReplyCallback callback)
      Encrypt the data to the target using the given key and deliver the specified tags No new session key This is the one called from GarlicMessageBuilder and is the primary entry point.
      Parameters:
      cloves - the cloves to encrypt and send
      target - public key to which the data should be encrypted.
      to - destination to encrypt for, required when priv is non-null
      priv - local private key to encrypt with, from the leaseset may be null for anonymous (N-in-IK)
      keyManager - session key manager, required when priv is non-null
      callback - may be null, if non-null an ack will be requested (except NS/NSR), not used when priv is null
      Returns:
      encrypted data or null on failure
    • x_encrypt

      private byte[] x_encrypt(CloveSet cloves, PublicKey target, Destination to, PrivateKey priv, RatchetSKM keyManager, ReplyCallback callback)
      Encrypt the cloves to the target, selecting New Session, New Session Reply, or Existing Session encryption as appropriate.
      Parameters:
      cloves - the cloves to encrypt and send
      target - the peer's static public key to encrypt to, never the all-zero key
      to - destination to encrypt for, required when priv is non-null
      priv - local private key to encrypt with, from the leaseset may be null for anonymous (N-in-IK)
      keyManager - session key manager, required when priv is non-null
      callback - may be null, not used when priv is null
      Returns:
      the encrypted message, or null if the target is the all-zero key or the selected scheme fails
    • encryptNewSession

      private byte[] encryptNewSession(CloveSet cloves, PublicKey target, Destination to, PrivateKey priv, RatchetSKM keyManager, ReplyCallback callback)
      Scenario 1: New Session Message

      Begin with 80 bytes, ECIES encrypted, containing:

      - 32 byte Elligator2 key
      - 32 byte static key
      - 16 byte MAC
      
      And then the data:
      - payload
      - 16 byte MAC
      
      Parameters:
      cloves - the cloves to encrypt and send
      target - the peer's static public key to encrypt to
      to - destination to encrypt for, required when priv is non-null
      priv - local private key to encrypt with, from the leaseset may be null for anonymous (N-in-IK)
      keyManager - session key manager, required when priv is non-null
      callback - may be null, not used when priv is null
      Returns:
      the encrypted NewSession message, or null if the handshake or the Elligator2 encoding fails
    • encryptNewSession

      private byte[] encryptNewSession(CloveSet cloves, PublicKey target)
      Scenario 1A: New Session Message from an anonymous source.
      - 32 byte ephemeral key (NOT Elligator2)
      - payload
      - 16 byte MAC
      
      Parameters:
      cloves - the cloves to encrypt and send
      target - the peer's static public key to encrypt to
      Returns:
      the encrypted anonymous NewSession message, or null if the handshake fails
    • encryptNewSessionReply

      private byte[] encryptNewSessionReply(CloveSet cloves, PublicKey target, HandshakeState state, RatchetSessionTag currentTag, RatchetSKM keyManager, ReplyCallback callback)
      Scenario 2: New Session Reply Message

      Begin with 56 bytes, containing:

      - 8 byte SessionTag
      - 32 byte Elligator2 key
      - 16 byte MAC
      
      And then the data:
      - payload
      - 16 byte MAC
      
      Parameters:
      cloves - the cloves to encrypt and send
      target - the peer's static public key we are replying to
      state - must have already been cloned
      currentTag - the 8-byte session tag to prefix the message with, mixed into the handshake hash
      keyManager - updated with the split keys and the callback on success
      callback - may be null
      Returns:
      the encrypted NewSessionReply, or null if either part of the encrypt fails
    • encryptExistingSession

      private byte[] encryptExistingSession(CloveSet cloves, PublicKey target, RatchetEntry re, ReplyCallback callback, RatchetSKM keyManager)
      Scenario 3: Existing Session Message.
      - 8 byte SessionTag
      - payload
      - 16 byte MAC
      
      Parameters:
      cloves - the cloves to encrypt and send
      target - only used if callback is non-null to register it
      re - the tag, key and pending next keys and acks taken from the key manager
      callback - may be null, if non-null an ack is requested and the callback registered for this tag
      keyManager - registers the callback for this tag when callback is non-null
      Returns:
      the encrypted ExistingSession message, or null if the AEAD encrypt fails
    • encrypt

      public byte[] encrypt(CloveSet cloves, SessionKey key, RatchetSessionTag tag)
      Create an Existing Session Message to an anonymous target using the given session key and tag, for netdb DSM/DSRM replies. Called from MessageWrapper.

      No datetime, no next key, no acks, no ack requests. n=0, ad = the 8-byte session tag.

      - 8 byte SessionTag
      - payload
      - 16 byte MAC
      
      Parameters:
      cloves - the cloves to encrypt and send
      key - existing session key for the ES scheme
      tag - session tag to prefix the block with, naming the key to the receiver
      Returns:
      encrypted data or null on failure
    • encrypt

      public byte[] encrypt(CloveSet cloves, PublicKey target)
      Encrypt the data to the target using the given key from an anonymous source, for netdb lookups. Called from MessageWrapper.
      Parameters:
      cloves - the cloves to encrypt and send
      target - public key to which the data should be encrypted.
      Returns:
      encrypted data or null on failure
    • encryptAEADBlock

      private final byte[] encryptAEADBlock(byte[] ad, byte[] data, SessionKey key, long n)
      Encrypt the data with the given key and nonce.
      Parameters:
      ad - may be null
      data - the payload to encrypt
      key - the 32-byte ChaCha20-Poly1305 session key
      n - the nonce for this message, 0 for the anonymous netdb replies
      Returns:
      a buffer with room for the ad, then the ciphertext and the 16-byte MAC, or null if the cipher fails
    • doDH

      static final PrivateKey doDH(PrivateKey privkey, PublicKey pubkey)
      Compute the Curve25519 Diffie-Hellman shared secret for the given key pair.
      Parameters:
      privkey - local ECIES_X25519 private key
      pubkey - remote ECIES_X25519 public key
      Returns:
      the 32 byte shared secret wrapped as an ECIES_X25519 private key
    • createPayload

      private byte[] createPayload(CloveSet cloves, long expiration, int overhead)
      Create the payload, adding a DateTime block if expiration is greater than zero.
      Parameters:
      cloves - the garlic cloves to include as payload blocks
      expiration - if greater than zero, add a DateTime block
      overhead - bytes to be added later, to assist in padding calculation
      Returns:
      the padded payload blocks, ready for the handshake or AEAD layer
    • createPayload

      private byte[] createPayload(CloveSet cloves, long expiration, boolean ackreq, NextSessionKey nextKey1, NextSessionKey nextKey2, List<Integer> acksToSend, int overhead)
      Create the payload from the given cloves and optional blocks.
      Parameters:
      cloves - the garlic cloves to include as payload blocks
      expiration - if greater than zero, add a DateTime block
      ackreq - to request an ack, must be false for NS/NSR
      nextKey1 - next session key block to include, may be null
      nextKey2 - second next session key block, may be null
      acksToSend - acknowledgement ids to send, may be null
      overhead - bytes to be added later, to assist in padding calculation
      Returns:
      the payload blocks, padded to stay under the tunnel message size boundaries of 944, 1936 or 2932 bytes
    • setResponseTimerNS

      private void setResponseTimerNS(PublicKey from, List<GarlicClove> cloveSet, RatchetSKM skm)
      Schedules the delayed reply to an NS message.
      Parameters:
      from - the sender's ratchet key
      cloveSet - the decrypted cloves to reply with
      skm - the session key manager for the sender
    • setResponseTimer

      private void setResponseTimer(PublicKey from, List<GarlicClove> cloveSet, RatchetSKM skm)
      Schedules the delayed reply to an NSR message.
      Parameters:
      from - the sender's ratchet key
      cloveSet - the decrypted cloves to reply with
      skm - the session key manager for the sender