Class HawkSigner
java.lang.Object
org.bouncycastle.pqc.crypto.hawk.HawkSigner
- All Implemented Interfaces:
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
FieldsModifier and TypeFieldDescriptionstatic final intstatic final intstatic final intstatic final intstatic final intstatic final intstatic final short[]static final short[]static final short[]static final long[]static final long[]static final long[]static final intstatic final intstatic final intstatic final int -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic voidbasisM2Mul(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 longbpMul32(int x, int y) Optimized binary polynomial multiplication of two 32-bit values in GF(2) Returns 64-bit product (carry-less multiplication)static voidbpMuladd(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 voidbpMuladd128(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset, byte[] tmp, int tmpOffset) static voidbpMuladd256(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 halvesstatic voidbpMuladd512(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 halvesstatic voidbpMuladd64(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 voidbpXor128(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset) static voidbpXor64(byte[] d, int dOffset, byte[] a, int aOffset, byte[] b, int bOffset) intcryptoSign(byte[] sm, long[] smlen, byte[] m, long mlen, byte[] sk, int logn) Main signing function compatible with the crypto_sign APIstatic intdec16le(byte[] src, int srcOffset) static intdec32le(byte[] src, int srcOffset) Decode 32-bit little-endian value from byte array This is a direct translation of the C dec32le functionstatic longdec64le(byte[] src, int srcOffset) static voidenc32le(byte[] dst, int dstOffset, int x) static voidenc64le(byte[] dst, int dstOffset, long x) Encode 64-bit value as little-endian bytes This is a direct translation of the C enc64le functionstatic booleanencodeSig(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.GaussianTablegetGaussianTable(int logn) static intgetTmpSize(int polynomialSize) static inthawkPrivKeySize(int logn) inthawkSignFinish(int logn, byte[] sig, SHAKEDigest scData, byte[] priv, byte[] tmp, int tmpLen) static SHAKEDigeststatic voidStart the signing process - initialize SHAKE contextstatic inthawkSigSize(int logn) static inthawkTmpSizeSign(int logn) voidinit(boolean forSigning, CipherParameters param) initialise the signer for signature generation or signature verification.intmq18433Add(int x, int y) Modular addition: (x + y) mod Q, result in [1..Q] where Q represents 0 mod Q.intmq18433Half(int x) Compute half: x/2 mod Q.intmq18433HalfMonty(int x) Alternative half implementation using modular inverse of 2voidmq18433INTT(int logn, short[] a, int aOffset) Inverse NTT matching C mq18433_iNTT exactly. 1/n normalization is embedded in the iGM twiddle factors.voidmq18433INTTWithScaling(int logn, short[] a, int aOffset) Alias for mq18433INTT kept for compatibility.intmq18433MontyMul(int x, int y) Montgomery multiplication: returns (x * y) mod Q in Montgomery formintmq18433MontyRed(int x) Montgomery reduction.voidmq18433NTT(int logn, short[] a, int aOffset) Number Theoretic Transform (NTT) for modulus 18433voidmq18433NTTSafe(int logn, short[] a, int aOffset) Alternative NTT implementation with explicit bounds checkingvoidmq18433PolySetSmall(int logn, short[] d, int dOffset, byte[] a, int aOffset) Convert a small polynomial (signed 8-bit coefficients) to mod q representation.voidmq18433PolySetSmallBatch(int logn, short[][] dArray, int[] dOffsets, byte[][] aArray, int[] aOffsets) Batch conversion for multiple polynomialsvoidmq18433PolySetSmallInplaceHigh(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).voidmq18433PolySetSmallInplaceLow(int logn, short[] d, int dOffset) Convert a small polynomial in-place from packed bytes to mod q representation.voidmq18433PolySetSmallInplaceLowBatch(int logn, short[][] dArray, int[] dOffsets) In-place conversion for multiple polynomialsstatic voidmq18433PolySnorm(int logn, short[] d, int dOffset) Apply signed normalization to polynomial coefficientsshortmq18433SetSmall(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)shortmq18433SetSmallSafe(byte x) Alternative implementation with bounds checkingstatic intmq18433Snorm(int x) Signed normalization: convert to range [-floor((Q-1)/2), floor((Q-1)/2)].static intmq18433SnormSafe(int x) Alternative signed normalization with proper boundsintmq18433Sub(int x, int y) Modular subtraction: (x - y) mod Q, result in [1..Q] where Q represents 0 mod Q.intmq18433ToMonty(int x) Convert a number to Montgomery formstatic intpolySymBreak(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 zerostatic intpolySymBreakExplicit(int logn, short[] s, int sOffset) Alternative implementation with explicit sign detectionintsigGauss(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.intsigGaussAlt(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 APIintsignFinishInner(int logn, int useShake, byte[] sig, SHAKEDigest scData, byte[] priv, int privLen, byte[] tmp, int tmpLen) booleanverifySignature(byte[] message, byte[] signature) verify the message message against the signature value.
-
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
Description copied from interface:MessageSignerinitialise the signer for signature generation or signature verification.- Specified by:
initin interfaceMessageSigner- 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:MessageSignersign the passed in message (usually the output of a hash function).- Specified by:
generateSignaturein interfaceMessageSigner- 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:MessageSignerverify the message message against the signature value.- Specified by:
verifySignaturein interfaceMessageSigner- Parameters:
message- the message that was supposed to have been signed.signature- the signature of the message
-
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
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
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)
-