Class GenericJcaMessageAgreementContext

java.lang.Object
zeroecho.core.alg.common.agreement.GenericJcaMessageAgreementContext
All Implemented Interfaces:
Closeable, AutoCloseable, AgreementContext, CryptoContext, MessageAgreementContext

public final class GenericJcaMessageAgreementContext extends Object implements MessageAgreementContext
Message-oriented JCA key agreement context where the handshake message is a public key encoding.

This context provides a MessageAgreementContext view over a classical JCA Diffie–Hellman style agreement (e.g., ECDH, XDH). The protocol "to-be-sent" data for such agreements is the party's public key. This class therefore maps:

Encoding

The message format is the standard X.509 SubjectPublicKeyInfo encoding returned by Key.getEncoded(). This format is stable, widely interoperable and avoids ad-hoc or algorithm-specific wire formats.

Algorithm and provider selection

The underlying key agreement algorithm name (for KeyAgreement) and the key factory algorithm name (for KeyFactory) are supplied explicitly by the algorithm registration code. This keeps algorithm-specific knowledge in *Algorithm classes rather than embedding naming heuristics into shared code.

Lifecycle

  1. Create the context with the local key pair wrapper.
  2. Send getPeerMessage() to the remote party.
  3. Receive the remote party's message and call setPeerMessage(byte[]).
  4. Derive the raw shared secret with deriveSecret().

Security considerations

  • The message returned by getPeerMessage() contains only public key material.
  • The output of deriveSecret() is a raw shared secret and must be processed with a KDF by higher protocol layers before use as symmetric keying material.
  • This class does not log, persist, or otherwise expose private key material.

Thread safety

Instances are not thread-safe and are intended for single-use, single-threaded protocol executions.

Since:
1.0
  • Constructor Details

    • GenericJcaMessageAgreementContext

      public GenericJcaMessageAgreementContext(CryptoAlgorithm alg, KeyPairKey keyPairKey, String jcaAgreementName, String agreementProvider, String keyFactoryAlg, String keyFactoryProvider)
      Creates a message-oriented agreement context over a JCA key agreement.

      The wrapped KeyPairKey supplies both local private and public key components: the private key is used for the underlying agreement computation, while the public key is exported as the handshake message via getPeerMessage().

      Parameters:
      alg - algorithm descriptor that owns this context
      keyPairKey - local key pair wrapper; must contain both a private and a public key
      jcaAgreementName - JCA KeyAgreement algorithm name (e.g., "ECDH", "X25519")
      agreementProvider - optional JCA provider name for KeyAgreement, or null for default provider selection
      keyFactoryAlg - JCA KeyFactory algorithm name used to import peer public keys (e.g., "EC", "XDH")
      keyFactoryProvider - optional JCA provider name for KeyFactory, or null for default provider selection
      Throws:
      NullPointerException - if any required argument is null
      Since:
      1.0
  • Method Details

    • getPeerMessage

      public byte[] getPeerMessage()
      Returns the local party's handshake message.

      For DH/XDH-style agreements, the handshake message is the local public key encoding. The returned array is a defensive copy and may be safely transmitted over untrusted channels.

      The encoding is the standard X.509 SubjectPublicKeyInfo bytes returned by Key.getEncoded().

      Specified by:
      getPeerMessage in interface MessageAgreementContext
      Returns:
      a defensive copy of the local public key encoding (never null)
      Throws:
      IllegalStateException - if the local public key does not provide an encoding
      Since:
      1.0
    • setPeerMessage

      public void setPeerMessage(byte[] message)
      Supplies the peer party's handshake message.

      The provided message is interpreted as an X.509 SubjectPublicKeyInfo encoding of the peer public key. The key is imported using KeyFactory and then assigned as the peer key for the underlying agreement computation.

      Passing null resets the peer binding and makes deriveSecret() unusable until a new peer message is provided.

      Specified by:
      setPeerMessage in interface MessageAgreementContext
      Parameters:
      message - peer public key encoding (SPKI), or null to reset the peer state
      Throws:
      IllegalArgumentException - if the message cannot be imported as a public key using the configured KeyFactory algorithm/provider
      Since:
      1.0
    • setPeerPublic

      public void setPeerPublic(PublicKey peer)
      Sets the peer's public key to be used in the key agreement.

      This method must be called before AgreementContext.deriveSecret(). Implementations may validate that the provided key is suitable for the underlying algorithm (e.g., curve membership checks).

      Specified by:
      setPeerPublic in interface AgreementContext
      Parameters:
      peer - the peer's public key
    • deriveSecret

      public byte[] deriveSecret()
      Performs the key agreement and returns the derived raw shared secret.

      The returned byte array contains secret material and should be used immediately in a KDF. Callers are responsible for clearing or zeroizing the array after use to reduce the risk of leakage.

      Specified by:
      deriveSecret in interface AgreementContext
      Returns:
      a new byte array containing the raw shared secret
    • algorithm

      public CryptoAlgorithm algorithm()
      Returns the algorithm that created this context.
      Specified by:
      algorithm in interface CryptoContext
      Returns:
      the algorithm definition that owns this context
    • key

      public Key key()
      Returns the key bound to this context.

      For unkeyed contexts such as digests, this may be NullKey.INSTANCE.

      Specified by:
      key in interface CryptoContext
      Returns:
      the cryptographic key or sentinel bound to this context
    • close

      public void close()
      Completes the context's implementation-specific cleanup.

      Implementations release resources they explicitly own; cleanup can be a no-op for contexts holding only borrowed or garbage-collected state. The bound key remains caller-owned: closing a context never destroys the key. Callers that own a destroyable key must destroy it explicitly after all contexts and other consumers have released it. Streams returned by the context have independent lifecycles: callers must complete and close those streams before closing the context. This method does not promise to finalize stream output or verify authentication tags.

      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
      Specified by:
      close in interface CryptoContext