Class HawkSigner

java.lang.Object
org.bouncycastle.pqc.crypto.hawk.HawkSigner
All Implemented Interfaces:
MessageSigner

public class HawkSigner extends Object implements MessageSigner
Lightweight Hawk signer / verifier. Implements MessageSigner: initialise with a HawkPrivateKeyParameters (optionally wrapped in ParametersWithRandom) for signing, or with a HawkPublicKeyParameters for verification, then call generateSignature(byte[]) / verifySignature(byte[], byte[]).

generateSignature(byte[]) returns the signature bytes only; the NIST crypto_sign "signed message" form (msg || sig) is reconstructed by callers when needed.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
     
    static final int
     
    static final int
     
    static final int
     
    static final int
     
    static final int
     
    static final short[]
     
    static final short[]
     
    static final short[]
     
    static final long[]
     
    static final long[]
     
    static final long[]
     
    static final int
     
    static final int
     
    static final int
     
    static final int
     
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    static void
    basisM2Mul(int logn, byte[] t0, int t0Offset, byte[] t1, int t1Offset, byte[] h0, int h0Offset, byte[] h1, int h1Offset, byte[] f2, int f2Offset, byte[] g2, int g2Offset, byte[] F2, int F2Offset, byte[] G2, int G2Offset, byte[] tmp, int tmpOffset)
     
    static long
    bpMul32(int x, int y)
    Optimized binary polynomial multiplication of two 32-bit values in GF(2) Returns 64-bit product (carry-less multiplication)
    static void
    bpMuladd(int size, byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset, byte[] tmp, int tmpOffset)
    Binary polynomial multiplication using Karatsuba algorithm d += a * b (polynomial multiplication in GF(2))
    static void
    bpMuladd128(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset, byte[] tmp, int tmpOffset)
     
    static void
    bpMuladd256(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset, byte[] tmp, int tmpOffset)
    Binary polynomial multiplication and accumulation for 256-bit polynomials Uses Karatsuba algorithm with 128-bit halves
    static void
    bpMuladd512(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset, byte[] tmp, int tmpOffset)
    Binary polynomial multiplication and accumulation for 512-bit polynomials Uses Karatsuba algorithm with 256-bit halves
    static void
    bpMuladd64(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset, byte[] tmp, int tmpOffset)
    Binary polynomial multiplication and accumulation for 64-bit polynomials d += a * b (polynomial multiplication in GF(2))
    static void
    bpXor128(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset)
     
    static void
    bpXor64(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset)
     
    int
    cryptoSign(byte[] sm, long[] smlen, byte[] m, long mlen, byte[] sk, int logn)
    Main signing function compatible with the crypto_sign API
    static int
    dec16le(byte[] src, int srcOffset)
     
    static int
    dec32le(byte[] src, int srcOffset)
    Decode 32-bit little-endian value from byte array This is a direct translation of the C dec32le function
    static long
    dec64le(byte[] src, int srcOffset)
     
    static void
    enc32le(byte[] dst, int dstOffset, int x)
     
    static void
    enc64le(byte[] dst, int dstOffset, long x)
    Encode 64-bit value as little-endian bytes This is a direct translation of the C enc64le function
    static boolean
    encodeSig(int logn, byte[] sig, int sigOffset, int sigLen, byte[] salt, int saltOffset, int saltLen, short[] s1, int s1Offset)
    Encode the signature, with output length exactly sigLen bytes.
    byte[]
    generateSignature(byte[] message)
    sign the passed in message (usually the output of a hash function).
    static org.bouncycastle.pqc.crypto.hawk.HawkSigner.GaussianTable
    getGaussianTable(int logn)
     
    static int
    getTmpSize(int polynomialSize)
     
    static int
    hawkPrivKeySize(int logn)
     
    int
    hawkSignFinish(int logn, byte[] sig, SHAKEDigest scData, byte[] priv, byte[] tmp, int tmpLen)
     
     
    static void
    Start the signing process - initialize SHAKE context
    static int
    hawkSigSize(int logn)
     
    static int
    hawkTmpSizeSign(int logn)
     
    void
    init(boolean forSigning, CipherParameters param)
    initialise the signer for signature generation or signature verification.
    int
    mq18433Add(int x, int y)
    Modular addition: (x + y) mod Q, result in [1..Q] where Q represents 0 mod Q.
    int
    mq18433Half(int x)
    Compute half: x/2 mod Q.
    int
    Alternative half implementation using modular inverse of 2
    void
    mq18433INTT(int logn, short[] a, int aOffset)
    Inverse NTT matching C mq18433_iNTT exactly. 1/n normalization is embedded in the iGM twiddle factors.
    void
    mq18433INTTWithScaling(int logn, short[] a, int aOffset)
    Alias for mq18433INTT kept for compatibility.
    int
    mq18433MontyMul(int x, int y)
    Montgomery multiplication: returns (x * y) mod Q in Montgomery form
    int
    Montgomery reduction.
    void
    mq18433NTT(int logn, short[] a, int aOffset)
    Number Theoretic Transform (NTT) for modulus 18433
    void
    mq18433NTTSafe(int logn, short[] a, int aOffset)
    Alternative NTT implementation with explicit bounds checking
    void
    mq18433PolySetSmall(int logn, short[] d, int dOffset, byte[] a, int aOffset)
    Convert a small polynomial (signed 8-bit coefficients) to mod q representation.
    void
    mq18433PolySetSmallBatch(int logn, short[][] dArray, int[] dOffsets, byte[][] aArray, int[] aOffsets)
    Batch conversion for multiple polynomials
    void
    mq18433PolySetSmallInplaceHigh(int logn, short[] d, int dOffset)
    Convert a small polynomial (signed 8-bit coefficients) to a mod q representation that _ends_ at the same address (i.e. the n last bytes of d are read, and 2*n bytes are written into d).
    void
    mq18433PolySetSmallInplaceLow(int logn, short[] d, int dOffset)
    Convert a small polynomial in-place from packed bytes to mod q representation.
    void
    mq18433PolySetSmallInplaceLowBatch(int logn, short[][] dArray, int[] dOffsets)
    In-place conversion for multiple polynomials
    static void
    mq18433PolySnorm(int logn, short[] d, int dOffset)
    Apply signed normalization to polynomial coefficients
    short
    Convert a signed byte to a mod q value in the range [0, q-1] This is the equivalent of Zq(set_small)
    short
    Alternative implementation with bounds checking
    static int
    mq18433Snorm(int x)
    Signed normalization: convert to range [-floor((Q-1)/2), floor((Q-1)/2)].
    static int
    Alternative signed normalization with proper bounds
    int
    mq18433Sub(int x, int y)
    Modular subtraction: (x - y) mod Q, result in [1..Q] where Q represents 0 mod Q.
    int
    Convert a number to Montgomery form
    static int
    polySymBreak(int logn, short[] s, int sOffset)
    Returned value: 1 first non-zero coefficient of s is positive -1 first non-zero coefficient of s is negative 0 s is entirely zero
    static int
    polySymBreakExplicit(int logn, short[] s, int sOffset)
    Alternative implementation with explicit sign detection
    int
    sigGauss(int logn, SHAKEDigest scExtra, byte[] x, int xOffset, byte[] t, int tOffset)
    Generate x with the right Gaussian, for the specified parity bits. x is formally generated with center t/2 and standard deviation sigma_sign (with sigma_sign = 1.010, 1.278 or 1.299, depending on degree); this function generates 2*x.
    int
    sigGaussAlt(int logn, byte[] x, int xOffset, byte[] t, int tOffset)
    Alternate function for sampling x; the same mechanism is used, but the provided RNG is used directly instead of instantiating four SHAKE instances in parallel.
    byte[]
    sign(byte[] message, byte[] privateKey, int logn)
    Alternative signature with simpler Java-style API
    int
    signFinishInner(int logn, int useShake, byte[] sig, SHAKEDigest scData, byte[] priv, int privLen, byte[] tmp, int tmpLen)
     
    boolean
    verifySignature(byte[] message, byte[] signature)
    verify the message message against the signature value.

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • SIG_GAUSS_HI_HAWK_256

      public static final short[] SIG_GAUSS_HI_HAWK_256
    • SG_MAX_HI_HAWK_256

      public static final int SG_MAX_HI_HAWK_256
    • SIG_GAUSS_LO_HAWK_256

      public static final long[] SIG_GAUSS_LO_HAWK_256
    • SG_MAX_LO_HAWK_256

      public static final int SG_MAX_LO_HAWK_256
    • SIG_GAUSS_HI_HAWK_512

      public static final short[] SIG_GAUSS_HI_HAWK_512
    • SG_MAX_HI_HAWK_512

      public static final int SG_MAX_HI_HAWK_512
    • SIG_GAUSS_LO_HAWK_512

      public static final long[] SIG_GAUSS_LO_HAWK_512
    • SG_MAX_LO_HAWK_512

      public static final int SG_MAX_LO_HAWK_512
    • SIG_GAUSS_HI_HAWK_1024

      public static final short[] SIG_GAUSS_HI_HAWK_1024
    • SG_MAX_HI_HAWK_1024

      public static final int SG_MAX_HI_HAWK_1024
    • SIG_GAUSS_LO_HAWK_1024

      public static final long[] SIG_GAUSS_LO_HAWK_1024
    • SG_MAX_LO_HAWK_1024

      public static final int SG_MAX_LO_HAWK_1024
    • SIZE_64

      public static final int SIZE_64
      See Also:
    • SIZE_128

      public static final int SIZE_128
      See Also:
    • SIZE_256

      public static final int SIZE_256
      See Also:
    • SIZE_512

      public static final int SIZE_512
      See Also:
  • Constructor Details

    • HawkSigner

      public HawkSigner()
  • Method Details

    • init

      public void init(boolean forSigning, CipherParameters param)
      Description copied from interface: MessageSigner
      initialise the signer for signature generation or signature verification.
      Specified by:
      init in interface MessageSigner
      Parameters:
      forSigning - true if we are generating a signature, false otherwise.
      param - key parameters for signature generation.
    • generateSignature

      public byte[] generateSignature(byte[] message)
      Description copied from interface: MessageSigner
      sign the passed in message (usually the output of a hash function).
      Specified by:
      generateSignature in interface MessageSigner
      Parameters:
      message - the message to be signed.
      Returns:
      the signature of the message
    • verifySignature

      public boolean verifySignature(byte[] message, byte[] signature)
      Description copied from interface: MessageSigner
      verify the message message against the signature value.
      Specified by:
      verifySignature in interface MessageSigner
      Parameters:
      message - the message that was supposed to have been signed.
      signature - the signature of the message
    • hawkSignStart

      public static SHAKEDigest hawkSignStart()
    • hawkSignFinish

      public int hawkSignFinish(int logn, byte[] sig, SHAKEDigest scData, byte[] priv, byte[] tmp, int tmpLen)
    • basisM2Mul

      public static void basisM2Mul(int logn, byte[] t0, int t0Offset, byte[] t1, int t1Offset, byte[] h0, int h0Offset, byte[] h1, int h1Offset, byte[] f2, int f2Offset, byte[] g2, int g2Offset, byte[] F2, int F2Offset, byte[] G2, int G2Offset, byte[] tmp, int tmpOffset)
    • bpMuladd

      public static void bpMuladd(int size, byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset, byte[] tmp, int tmpOffset)
      Binary polynomial multiplication using Karatsuba algorithm d += a * b (polynomial multiplication in GF(2))
    • bpMuladd128

      public static void bpMuladd128(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset, byte[] tmp, int tmpOffset)
    • bpXor64

      public static void bpXor64(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset)
    • bpXor128

      public static void bpXor128(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset)
    • getTmpSize

      public static int getTmpSize(int polynomialSize)
    • bpMuladd64

      public static void bpMuladd64(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset, byte[] tmp, int tmpOffset)
      Binary polynomial multiplication and accumulation for 64-bit polynomials d += a * b (polynomial multiplication in GF(2))

      This is a direct translation of the C function that uses 32-bit halves for efficient polynomial multiplication in GF(2)

    • dec32le

      public static int dec32le(byte[] src, int srcOffset)
      Decode 32-bit little-endian value from byte array This is a direct translation of the C dec32le function
    • bpMul32

      public static long bpMul32(int x, int y)
      Optimized binary polynomial multiplication of two 32-bit values in GF(2) Returns 64-bit product (carry-less multiplication)

      This implements the same "classic technique" as the C code using the 4-way decomposition with masks

    • enc64le

      public static void enc64le(byte[] dst, int dstOffset, long x)
      Encode 64-bit value as little-endian bytes This is a direct translation of the C enc64le function
    • bpMuladd256

      public static void bpMuladd256(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset, byte[] tmp, int tmpOffset)
      Binary polynomial multiplication and accumulation for 256-bit polynomials Uses Karatsuba algorithm with 128-bit halves
    • bpMuladd512

      public static void bpMuladd512(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset, byte[] tmp, int tmpOffset)
      Binary polynomial multiplication and accumulation for 512-bit polynomials Uses Karatsuba algorithm with 256-bit halves
    • enc32le

      public static void enc32le(byte[] dst, int dstOffset, int x)
    • dec64le

      public static long dec64le(byte[] src, int srcOffset)
    • dec16le

      public static int dec16le(byte[] src, int srcOffset)
    • sigGauss

      public int sigGauss(int logn, SHAKEDigest scExtra, byte[] x, int xOffset, byte[] t, int tOffset)
      Generate x with the right Gaussian, for the specified parity bits. x is formally generated with center t/2 and standard deviation sigma_sign (with sigma_sign = 1.010, 1.278 or 1.299, depending on degree); this function generates 2*x.

      Returned value is the squared norm of x.

    • getGaussianTable

      public static org.bouncycastle.pqc.crypto.hawk.HawkSigner.GaussianTable getGaussianTable(int logn)
    • sigGaussAlt

      public int sigGaussAlt(int logn, byte[] x, int xOffset, byte[] t, int tOffset)
      Alternate function for sampling x; the same mechanism is used, but the provided RNG is used directly instead of instantiating four SHAKE instances in parallel.

      Returned value is the squared norm of x.

    • mq18433PolySetSmall

      public void mq18433PolySetSmall(int logn, short[] d, int dOffset, byte[] a, int aOffset)
      Convert a small polynomial (signed 8-bit coefficients) to mod q representation. This is the equivalent of Zq(poly_set_small)
    • mq18433PolySetSmallInplaceLow

      public void mq18433PolySetSmallInplaceLow(int logn, short[] d, int dOffset)
      Convert a small polynomial in-place from packed bytes to mod q representation. This is the equivalent of Zq(poly_set_small_inplace_low)

      The input is stored as packed bytes in the first n/2 elements of d, and the output is written as mod q values in all n elements of d.

    • mq18433SetSmall

      public short mq18433SetSmall(byte x)
      Convert a signed byte to a mod q value in the range [0, q-1] This is the equivalent of Zq(set_small)
    • mq18433SetSmallSafe

      public short mq18433SetSmallSafe(byte x)
      Alternative implementation with bounds checking
    • mq18433PolySetSmallBatch

      public void mq18433PolySetSmallBatch(int logn, short[][] dArray, int[] dOffsets, byte[][] aArray, int[] aOffsets)
      Batch conversion for multiple polynomials
    • mq18433PolySetSmallInplaceLowBatch

      public void mq18433PolySetSmallInplaceLowBatch(int logn, short[][] dArray, int[] dOffsets)
      In-place conversion for multiple polynomials
    • mq18433PolySetSmallInplaceHigh

      public void mq18433PolySetSmallInplaceHigh(int logn, short[] d, int dOffset)
      Convert a small polynomial (signed 8-bit coefficients) to a mod q representation that _ends_ at the same address (i.e. the n last bytes of d are read, and 2*n bytes are written into d).
    • mq18433NTT

      public void mq18433NTT(int logn, short[] a, int aOffset)
      Number Theoretic Transform (NTT) for modulus 18433
    • mq18433NTTSafe

      public void mq18433NTTSafe(int logn, short[] a, int aOffset)
      Alternative NTT implementation with explicit bounds checking
    • mq18433MontyMul

      public int mq18433MontyMul(int x, int y)
      Montgomery multiplication: returns (x * y) mod Q in Montgomery form
    • mq18433MontyRed

      public int mq18433MontyRed(int x)
      Montgomery reduction. The Hawk protocol never feeds x == 0 here (NTT/INTT butterfly products in [1..Q] representation, where Q itself represents 0), but the original short-circuit `if (x == 0) return 0;` is a data-dependent branch on a secret-derived intermediate — replaced with a branchless mask to preserve byte-identity while removing the L1 timing channel.
    • mq18433Add

      public int mq18433Add(int x, int y)
      Modular addition: (x + y) mod Q, result in [1..Q] where Q represents 0 mod Q. Matches the C formula: d = Q-(x+y); d += Q & (d>>16); return Q-d;
    • mq18433Sub

      public int mq18433Sub(int x, int y)
      Modular subtraction: (x - y) mod Q, result in [1..Q] where Q represents 0 mod Q. Matches the C formula: d = y-x; d += Q & (d>>16); return Q-d;
    • mq18433INTT

      public void mq18433INTT(int logn, short[] a, int aOffset)
      Inverse NTT matching C mq18433_iNTT exactly. 1/n normalization is embedded in the iGM twiddle factors.
    • mq18433ToMonty

      public int mq18433ToMonty(int x)
      Convert a number to Montgomery form
    • mq18433INTTWithScaling

      public void mq18433INTTWithScaling(int logn, short[] a, int aOffset)
      Alias for mq18433INTT kept for compatibility.
    • mq18433Half

      public int mq18433Half(int x)
      Compute half: x/2 mod Q. Constant-time: x is a secret-derived INTT butterfly intermediate (each butterfly calls this O(n log n) per signing INTT), so the "is x odd" branch must not be data-dependent. Same pattern as HawkEngine.mpHalf — fold the conditional `+ Q` (only applied when x is odd, to keep the result an integer) into a branchless mask.
    • mq18433HalfMonty

      public int mq18433HalfMonty(int x)
      Alternative half implementation using modular inverse of 2
    • mq18433PolySnorm

      public static void mq18433PolySnorm(int logn, short[] d, int dOffset)
      Apply signed normalization to polynomial coefficients
    • mq18433Snorm

      public static int mq18433Snorm(int x)
      Signed normalization: convert to range [-floor((Q-1)/2), floor((Q-1)/2)]. Constant-time: x is a secret-derived NTT coefficient (signing computes f*x1 - g*x0 over secret f, g and sampled x), so the "is x > Q/2" branch must not be data-dependent. We compute a -1/0 mask from the sign of (Q/2 - x) and apply it; byte-identical to the original on all inputs in the polynomial's range.
    • mq18433SnormSafe

      public static int mq18433SnormSafe(int x)
      Alternative signed normalization with proper bounds
    • polySymBreak

      public static int polySymBreak(int logn, short[] s, int sOffset)
      Returned value: 1 first non-zero coefficient of s is positive -1 first non-zero coefficient of s is negative 0 s is entirely zero
    • polySymBreakExplicit

      public static int polySymBreakExplicit(int logn, short[] s, int sOffset)
      Alternative implementation with explicit sign detection
    • encodeSig

      public static boolean encodeSig(int logn, byte[] sig, int sigOffset, int sigLen, byte[] salt, int saltOffset, int saltLen, short[] s1, int s1Offset)
      Encode the signature, with output length exactly sigLen bytes. Padding is applied if necessary. Returned value is 1 on success, 0 on error; an error is reported if the signature does not fit in the provided buffer.
    • signFinishInner

      public int signFinishInner(int logn, int useShake, byte[] sig, SHAKEDigest scData, byte[] priv, int privLen, byte[] tmp, int tmpLen)
    • cryptoSign

      public int cryptoSign(byte[] sm, long[] smlen, byte[] m, long mlen, byte[] sk, int logn)
      Main signing function compatible with the crypto_sign API
    • sign

      public byte[] sign(byte[] message, byte[] privateKey, int logn)
      Alternative signature with simpler Java-style API
    • hawkSignStart

      public static void hawkSignStart(SHAKEDigest sc)
      Start the signing process - initialize SHAKE context
    • hawkPrivKeySize

      public static int hawkPrivKeySize(int logn)
    • hawkSigSize

      public static int hawkSigSize(int logn)
    • hawkTmpSizeSign

      public static int hawkTmpSizeSign(int logn)