Direct Known Subclasses:
RedDSAEngine

public class EdDSAEngineextends Signature
EdDSA signature engine implementing the Java Signature API. Supports both standard streaming and one-shot operation modes for efficiency.
  • Field Details

    • SIGNATURE_ALGORITHM

      public static final String SIGNATURE_ALGORITHM
      The signature algorithm name.
      See Also:
    • digest

      protected MessageDigest digest
      The message digest used for signing/verification.
    • baos

      private ByteArrayOutputStream baos
      Collects the data to be signed.
    • key

      private EdDSAKey key
      The key used to sign or verify.
    • oneShotMode

      private boolean oneShotMode
      True when the data is given in one call.
    • oneShotBytes

      private byte[] oneShotBytes
      The data given in one call.
    • oneShotOffset

      private int oneShotOffset
      Offset in the one call data.
    • oneShotLength

      private int oneShotLength
      Length of the one call data.
    • ONE_SHOT_MODE

      public static final AlgorithmParameterSpec ONE_SHOT_MODE
      To efficiently sign or verify data in one shot, pass this to setParameters() after initSign() or initVerify() but BEFORE THE FIRST AND ONLY update(data) or update(data, off, len). The data reference will be saved and then used in sign() or verify() without copying the data. Violate these rules and you will get a SignatureException.
    • _ble

      private static final BigIntegerLittleEndianEncoding _ble
      Encoder of big integers in little endian.
    • ORDER_LITTLE_ENDIAN

      private static final byte[] ORDER_LITTLE_ENDIAN
      EdDSABlinding.ORDER as 32 little-endian bytes, so that the RFC 8032 range check on S can be done by subtraction instead of building a BigInteger. Verified against BigInteger.compareTo().
    • sBuf

      private byte[] sBuf
      Reusable buffer for the S half of a signature, to avoid allocating a fresh array for every verification. Only valid within one call, and never retained by any callee. Like the digest, baos and oneShotBytes state this class already keeps, it assumes the instance is used by one thread at a time - callers that care create a fresh engine per operation.
  • Constructor Details

    • EdDSAEngine

      public EdDSAEngine()
      No specific EdDSA-internal hash requested, allows any EdDSA key.
    • EdDSAEngine

      public EdDSAEngine(MessageDigest digest)
      Specific EdDSA-internal hash requested, only matching keys will be allowed.
      Parameters:
      digest - the hash algorithm that keys must have to sign or verify.
  • Method Details

    • reset

      private void reset()
      Reset the signer and verifier state.
    • engineInitSign

      protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException
      Specified by:
      engineInitSign in class SignatureSpi
      Throws:
      InvalidKeyException
    • digestInitSign

      protected void digestInitSign(EdDSAPrivateKey privKey)
      Initialize the digest for signing.
      Parameters:
      privKey - the private key
    • engineInitVerify

      protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException
      Specified by:
      engineInitVerify in class SignatureSpi
      Throws:
      InvalidKeyException
    • engineUpdate

      protected void engineUpdate(byte b) throws SignatureException
      Update the signature with one byte.
      Specified by:
      engineUpdate in class SignatureSpi
      Throws:
      SignatureException - if in one-shot mode
    • engineUpdate

      protected void engineUpdate(byte[] b, int off, int len) throws SignatureException
      Update the signature with the given bytes.
      Specified by:
      engineUpdate in class SignatureSpi
      Throws:
      SignatureException - if one-shot rules are violated
    • engineSign

      protected byte[] engineSign() throws SignatureException
      Specified by:
      engineSign in class SignatureSpi
      Throws:
      SignatureException
    • x_engineSign

      private byte[] x_engineSign() throws SignatureException
      Signs the collected data.
      Returns:
      the signature bytes
      Throws:
      SignatureException - if the signing fails
    • engineVerify

      protected boolean engineVerify(byte[] sigBytes) throws SignatureException
      Specified by:
      engineVerify in class SignatureSpi
      Throws:
      SignatureException
    • x_engineVerify

      private boolean x_engineVerify(byte[] sigBytes) throws SignatureException
      Checks the signature of the collected data.
      Parameters:
      sigBytes - the signature to check
      Returns:
      true if the signature is valid
      Throws:
      SignatureException - if the checking fails
    • isBelowOrder

      private static boolean isBelowOrder(byte[] s)
      Is the 32 byte little-endian value in s strictly less than EdDSABlinding.ORDER?

      Equivalent to _ble.toBigInteger(s).compareTo(EdDSABlinding.ORDER) < 0 without allocating a BigInteger and a reversed copy of the input. This is a fixed 32 iteration borrow chain: every byte is read and every byte is subtracted, and the only carry is folded into the next iteration with arithmetic, so there is no data-dependent branch or memory access. That makes it strictly better than BigInteger.compareTo(), which exits early on the first differing magnitude word. A short-circuiting byte compare would be a timing oracle here; DataHelper.eq()/MessageDigest.isEqual(byte[], byte[]) are equality tests and cannot express an ordering, so they don't apply.

      Parameters:
      s - the value to test, 32 bytes, little-endian
      Returns:
      true if s is less than the group order
    • signOneShot

      public byte[] signOneShot(byte[] data) throws SignatureException
      To efficiently sign all the data in one shot, if it is available, use this method, which will avoid copying the data.

      Same as:

      setParameter(ONE_SHOT_MODE)
      update(data)
      sig = sign()
      
      Parameters:
      data - the message to be signed
      Returns:
      the R and S components, 2 * b/4 bytes long
      Throws:
      SignatureException - if update() already called
      See Also:
    • signOneShot

      public byte[] signOneShot(byte[] data, int off, int len) throws SignatureException
      To efficiently sign all the data in one shot, if it is available, use this method, which will avoid copying the data.

      Same as:

      setParameter(ONE_SHOT_MODE)
      update(data, off, len)
      sig = sign()
      
      Parameters:
      data - byte array containing the message to be signed
      off - the start of the message inside data
      len - the length of the message
      Returns:
      the R and S components, 2 * b/4 bytes long
      Throws:
      SignatureException - if update() already called
      See Also:
    • verifyOneShot

      public boolean verifyOneShot(byte[] data, byte[] signature) throws SignatureException
      To efficiently verify all the data in one shot, if it is available, use this method, which will avoid copying the data.

      Same as:

      setParameter(ONE_SHOT_MODE)
      update(data)
      ok = verify(signature)
      
      Parameters:
      data - the message that was signed
      signature - of the message
      Returns:
      true if the signature is valid, false otherwise
      Throws:
      SignatureException - if update() already called
      See Also:
    • verifyOneShot

      public boolean verifyOneShot(byte[] data, int off, int len, byte[] signature) throws SignatureException
      To efficiently verify all the data in one shot, if it is available, use this method, which will avoid copying the data.

      Same as:

      setParameter(ONE_SHOT_MODE)
      update(data, off, len)
      ok = verify(signature)
      
      Parameters:
      data - byte array containing the message that was signed
      off - the start of the message inside data
      len - the length of the message
      signature - of the message
      Returns:
      true if the signature is valid, false otherwise
      Throws:
      SignatureException - if update() already called
      See Also:
    • verifyOneShot

      public boolean verifyOneShot(byte[] data, byte[] signature, int sigoff, int siglen) throws SignatureException
      To efficiently verify all the data in one shot, if it is available, use this method, which will avoid copying the data.

      Same as:

      setParameter(ONE_SHOT_MODE)
      update(data)
      ok = verify(signature, sigoff, siglen)
      
      Parameters:
      data - the message that was signed
      signature - byte array containing the signature
      sigoff - the start of the signature
      siglen - the length of the signature
      Returns:
      true if the signature is valid, false otherwise
      Throws:
      SignatureException - if update() already called
      See Also:
    • verifyOneShot

      public boolean verifyOneShot(byte[] data, int off, int len, byte[] signature, int sigoff, int siglen) throws SignatureException
      To efficiently verify all the data in one shot, if it is available, use this method, which will avoid copying the data.

      Same as:

      setParameter(ONE_SHOT_MODE)
      update(data, off, len)
      ok = verify(signature, sigoff, siglen)
      
      Parameters:
      data - byte array containing the message that was signed
      off - the start of the message inside data
      len - the length of the message
      signature - byte array containing the signature
      sigoff - the start of the signature
      siglen - the length of the signature
      Returns:
      true if the signature is valid, false otherwise
      Throws:
      SignatureException - if update() already called
      See Also:
    • engineSetParameter

      protected void engineSetParameter(AlgorithmParameterSpec spec) throws InvalidAlgorithmParameterException
      Only the one-shot mode parameter specification is supported.
      Overrides:
      engineSetParameter in class SignatureSpi
      Throws:
      InvalidAlgorithmParameterException - if spec is ONE_SHOT_MODE and update() already called
      See Also: