Class XMSSMTSigner

java.lang.Object
org.bouncycastle.crypto.signers.XMSSMTSigner
All Implemented Interfaces:
Signer

public class XMSSMTSigner extends Object implements Signer
XMSS^MT Signer class.
  • Constructor Details

    • XMSSMTSigner

      public XMSSMTSigner()
  • Method Details

    • init

      public void init(boolean forSigning, CipherParameters param)
      Initialise for signing or verification. A ParametersWithRandom wrapper is accepted and unwrapped before either branch is entered, the way LMSSigner.init accepts it, so a caller that wraps its key once and drives both sides is not refused by the verification one; the random the wrapper carries is not used. The randomizer r is derived from the key itself - r = PRF(SK_PRF, toByte(idx, 32)), RFC 8391 sec. 4.2.7 - so a SecureRandom supplied here has nothing to drive and is discarded, the way SPHINCS256Signer discards it. On the signing side accepting the wrapper is what BC itself needs: XMSSMTSignatureSpi.engineInitSign(PrivateKey, SecureRandom) wraps the key whenever a random is supplied, so initSign(key, random) used to fail on the cast.
      Specified by:
      init in interface Signer
      Parameters:
      forSigning - true for signing, false for verification.
      param - the key, optionally wrapped in ParametersWithRandom.
    • generateSignature

      public byte[] generateSignature()
      Description copied from interface: Signer
      generate a signature for the message we've been loaded with using the key we were initialised with.
      Specified by:
      generateSignature in interface Signer
    • verifySignature

      public boolean verifySignature(byte[] signature)
      Verify the buffered message against the passed in signature.

      No monitor is taken here, the way the legacy signer and LMSSigner take none. This reads the public key and the mode flag, spends no one-time key and advances no traversal state, so there is nothing for a lock to serialize; and it could not serialize the message in any case, since update(byte) and reset() write the buffer without one, so a monitor held over the read alone excludes nothing a caller sharing one signer across threads is doing. What the signing side takes this monitor for is the private key field, which getUpdatedPrivateKey() reassigns; nothing reassigns the public key but init(boolean, CipherParameters), and re-initialising a signer under a running operation is the caller error it is in every other signer here.

      Specified by:
      verifySignature in interface Signer
    • getUsagesRemaining

      public long getUsagesRemaining()
      Return the number of signatures the key this signer holds can still produce. A signer that has never been initialised for signing, or one whose key has already been handed back by getUpdatedPrivateKey(), holds no key and so reports zero - reading the absent key would otherwise raise a NullPointerException.

      Initialising for verification is not one of those cases: init(boolean, org.bouncycastle.crypto.CipherParameters) deliberately leaves the private key in place, so that sign then verify then collect stays a legitimate sequence, and a signer that has signed and then been re-initialised to verify goes on reporting that key's count. What this answers is what the key it holds has left, not whether the signer is currently able to sign.

      No monitor is taken, the way the legacy signer takes none and the two key parameter classes LMS was promoted as leave their own getUsagesRemaining() unsynchronized. What this returns is a count and not a reservation: it is out of date the moment any monitor held over it is dropped, because the next signature made on that key - by this signer or by another holding it - moves it. The field read is of a reference and so cannot tear, and the key's own accessor takes the key's monitor for the traversal state the count is derived from.

    • update

      public void update(byte b)
      Absorb a byte of the message to be signed or verified. The buffered message is consumed by generateSignature() / verifySignature(byte[]), which reset the buffer.
      Specified by:
      update in interface Signer
    • update

      public void update(byte[] in, int off, int len)
      Description copied from interface: Signer
      update the internal digest with the byte array in
      Specified by:
      update in interface Signer
    • reset

      public void reset()
      Description copied from interface: Signer
      reset the internal state
      Specified by:
      reset in interface Signer
    • getUpdatedPrivateKey

      public AsymmetricKeyParameter getUpdatedPrivateKey()