Package org.bouncycastle.pqc.crypto.hawk
Class HawkSigner
- java.lang.Object
-
- org.bouncycastle.pqc.crypto.hawk.HawkSigner
-
- All Implemented Interfaces:
MessageSigner
public class HawkSigner extends java.lang.Object implements MessageSigner
Lightweight Hawk signer / verifier. ImplementsMessageSigner: initialise with aHawkPrivateKeyParameters(optionally wrapped inParametersWithRandom) for signing, or with aHawkPublicKeyParametersfor verification, then callgenerateSignature(byte[])/verifySignature(byte[], byte[]).generateSignature(byte[])returns the signature bytes only; the NISTcrypto_sign"signed message" form (msg || sig) is reconstructed by callers when needed.
-
-
Field Summary
Fields Modifier and Type Field Description static intSG_MAX_HI_HAWK_1024static intSG_MAX_HI_HAWK_256static intSG_MAX_HI_HAWK_512static intSG_MAX_LO_HAWK_1024static intSG_MAX_LO_HAWK_256static intSG_MAX_LO_HAWK_512static short[]SIG_GAUSS_HI_HAWK_1024static short[]SIG_GAUSS_HI_HAWK_256static short[]SIG_GAUSS_HI_HAWK_512static long[]SIG_GAUSS_LO_HAWK_1024static long[]SIG_GAUSS_LO_HAWK_256static long[]SIG_GAUSS_LO_HAWK_512static intSIZE_128static intSIZE_256static intSIZE_512static intSIZE_64
-
Constructor Summary
Constructors Constructor Description HawkSigner()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description static 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 SHAKEDigesthawkSignStart()static voidhawkSignStart(SHAKEDigest sc)Start 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.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 Detail
-
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:
- Constant Field Values
-
SIZE_128
public static final int SIZE_128
- See Also:
- Constant Field Values
-
SIZE_256
public static final int SIZE_256
- See Also:
- Constant Field Values
-
SIZE_512
public static final int SIZE_512
- See Also:
- Constant Field Values
-
-
Method Detail
-
init
public void init(boolean forSigning, CipherParameters param)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
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)
-
-