| Constructor and Description |
|---|
XMSSMTSigner() |
| Modifier and Type | Method and Description |
|---|---|
byte[] |
generateSignature()
generate a signature for the message we've been loaded with using
the key we were initialised with.
|
AsymmetricKeyParameter |
getUpdatedPrivateKey() |
long |
getUsagesRemaining()
Return the number of signatures the key this signer holds can still produce.
|
void |
init(boolean forSigning,
CipherParameters param)
Initialise for signing or verification.
|
void |
reset()
reset the internal state
|
void |
update(byte b)
Absorb a byte of the message to be signed or verified.
|
void |
update(byte[] in,
int off,
int len)
update the internal digest with the byte array in
|
boolean |
verifySignature(byte[] signature)
Verify the buffered message against the passed in signature.
|
public void init(boolean forSigning,
CipherParameters param)
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.init in interface SignerforSigning - true for signing, false for verification.param - the key, optionally wrapped in ParametersWithRandom.public byte[] generateSignature()
SignergenerateSignature in interface Signerpublic boolean verifySignature(byte[] 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.
verifySignature in interface Signerpublic long getUsagesRemaining()
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.
public void update(byte b)
generateSignature() / verifySignature(byte[]), which reset the buffer.public void update(byte[] in,
int off,
int len)
Signerpublic void reset()
Signerpublic AsymmetricKeyParameter getUpdatedPrivateKey()