fix: gofmt -s across repo (CI format check)

This commit is contained in:
Hanzo AI
2026-06-02 11:39:06 -07:00
parent 79bc183c6e
commit 158edb279c
28 changed files with 119 additions and 126 deletions
+6 -6
View File
@@ -71,14 +71,14 @@ type SignatureConfig struct {
PreferredType SignatureType `json:"preferredType"` PreferredType SignatureType `json:"preferredType"`
// Enable specific signature types // Enable specific signature types
EnableBLS bool `json:"enableBLS"` EnableBLS bool `json:"enableBLS"`
EnableCorona bool `json:"enableCorona"` EnableCorona bool `json:"enableCorona"`
EnableCGGMP21 bool `json:"enableCGGMP21"` EnableCGGMP21 bool `json:"enableCGGMP21"`
// Fee configuration (in nLUX - nano LUX) // Fee configuration (in nLUX - nano LUX)
BLSFee uint64 `json:"blsFee"` // 0 = free BLSFee uint64 `json:"blsFee"` // 0 = free
CoronaFee uint64 `json:"coronaFee"` // Premium for enhanced privacy CoronaFee uint64 `json:"coronaFee"` // Premium for enhanced privacy
CGGMP21Fee uint64 `json:"cggmp21Fee"` // Premium for threshold signatures CGGMP21Fee uint64 `json:"cggmp21Fee"` // Premium for threshold signatures
// Performance settings // Performance settings
ParallelAggregation bool `json:"parallelAggregation"` ParallelAggregation bool `json:"parallelAggregation"`
-1
View File
@@ -188,4 +188,3 @@ func TestEnvOverride(t *testing.T) {
t.Errorf("env override: Default() = %v; want Vanilla", got) t.Errorf("env override: Default() = %v; want Vanilla", got)
} }
} }
+4 -4
View File
@@ -22,10 +22,10 @@ type kat struct {
Key string `json:"key"` Key string `json:"key"`
ContextString string `json:"context_string"` ContextString string `json:"context_string"`
Cases []struct { Cases []struct {
InputLen int `json:"input_len"` InputLen int `json:"input_len"`
Hash string `json:"hash"` Hash string `json:"hash"`
KeyedHash string `json:"keyed_hash"` KeyedHash string `json:"keyed_hash"`
DeriveKey string `json:"derive_key"` DeriveKey string `json:"derive_key"`
} `json:"cases"` } `json:"cases"`
} }
+4 -4
View File
@@ -68,8 +68,8 @@ type rngState struct {
} }
var ( var (
rngMu sync.Mutex rngMu sync.Mutex
activeRNG *rngState activeRNG *rngState
) )
// installRNG takes the cgo lock and registers `r` as the entropy // installRNG takes the cgo lock and registers `r` as the entropy
@@ -92,12 +92,12 @@ func clearRNG() error {
return s.err return s.err
} }
//export hqcGoRandombytes
//
// Called from randombytes_shim.c. Reads exactly `n` bytes from the // Called from randombytes_shim.c. Reads exactly `n` bytes from the
// installed RNG into the buffer at `buf`. Returns 0 on full read, // installed RNG into the buffer at `buf`. Returns 0 on full read,
// non-zero on partial read or reader error (PQClean checks the // non-zero on partial read or reader error (PQClean checks the
// return value of randombytes() == 0). // return value of randombytes() == 0).
//
//export hqcGoRandombytes
func hqcGoRandombytes(buf *C.uint8_t, n C.size_t) C.int { func hqcGoRandombytes(buf *C.uint8_t, n C.size_t) C.int {
if activeRNG == nil { if activeRNG == nil {
// Misuse — no RNG installed. Fail loudly via non-zero return // Misuse — no RNG installed. Fail loudly via non-zero return
+8 -7
View File
@@ -34,10 +34,11 @@ import (
// amortises the cgo crossover across slots. // amortises the cgo crossover across slots.
// //
// Measured on Apple M1 Max (HQC-128 encaps): // Measured on Apple M1 Max (HQC-128 encaps):
// 1-item batch: accel = 35 us, direct = 30 us (direct wins) //
// 4-item batch: accel = 110 us, direct = 120 us (parity) // 1-item batch: accel = 35 us, direct = 30 us (direct wins)
// 16-item batch: accel = 410 us, direct = 480 us (accel ~17% win) // 4-item batch: accel = 110 us, direct = 120 us (parity)
// 128-item batch: accel = 1.7 ms, direct = 3.8 ms (accel ~2.2x) // 16-item batch: accel = 410 us, direct = 480 us (accel ~17% win)
// 128-item batch: accel = 1.7 ms, direct = 3.8 ms (accel ~2.2x)
// //
// The exact threshold is workload-dependent. We pick 4 (the first // The exact threshold is workload-dependent. We pick 4 (the first
// batch size where accel matches direct) so the API remains useful // batch size where accel matches direct) so the API remains useful
@@ -53,9 +54,9 @@ const batchSizeThreshold = 4
// OpenMP at the C++ level. That parallelism is independent of whether // OpenMP at the C++ level. That parallelism is independent of whether
// a "real" GPU device is present — the kernels share the same C++ // a "real" GPU device is present — the kernels share the same C++
// host loop. We therefore key dispatch on: // host loop. We therefore key dispatch on:
// 1. backend.IsVanilla() is false — i.e. the caller did NOT explicitly // 1. backend.IsVanilla() is false — i.e. the caller did NOT explicitly
// pick the pure-Go fallback. // pick the pure-Go fallback.
// 2. The batch is large enough to amortise the cgo crossover. // 2. The batch is large enough to amortise the cgo crossover.
// //
// We do NOT consult a session handle here — accel/ops/code parallelises via // We do NOT consult a session handle here — accel/ops/code parallelises via
// OpenMP at the C++ level whether or not a Metal/CUDA device exists, so the // OpenMP at the C++ level whether or not a Metal/CUDA device exists, so the
+3 -3
View File
@@ -153,10 +153,10 @@ func karatsuba(o, a, b []uint64, size int, stack []uint64) {
ah := a[sizeL:] ah := a[sizeL:]
bh := b[sizeL:] bh := b[sizeL:]
karatsuba(o, a, b, sizeL, rest) // o[0:2*sizeL] = a_L * b_L karatsuba(o, a, b, sizeL, rest) // o[0:2*sizeL] = a_L * b_L
karatsuba(tmp2, ah, bh, sizeH, rest) // tmp2 = a_H * b_H karatsuba(tmp2, ah, bh, sizeH, rest) // tmp2 = a_H * b_H
karatsubaAdd1(alh, blh, a, b, sizeL, sizeH) karatsubaAdd1(alh, blh, a, b, sizeL, sizeH)
karatsuba(tmp1, alh, blh, sizeL, rest) // tmp1 = (a_L+a_H)*(b_L+b_H) karatsuba(tmp1, alh, blh, sizeL, rest) // tmp1 = (a_L+a_H)*(b_L+b_H)
karatsubaAdd2(o, tmp1, tmp2, sizeL, sizeH) karatsubaAdd2(o, tmp1, tmp2, sizeL, sizeH)
} }
+5 -5
View File
@@ -18,11 +18,11 @@ import (
// CPU PQClean reference. The two paths share the same canonical // CPU PQClean reference. The two paths share the same canonical
// kernels via accel/ops/code so the test asserts that: // kernels via accel/ops/code so the test asserts that:
// //
// 1. The GPU batch path returns valid (ct, ss) pairs (decap-able by // 1. The GPU batch path returns valid (ct, ss) pairs (decap-able by
// the canonical PQClean reference). // the canonical PQClean reference).
// 2. The byte layout matches what PQClean produces with the same // 2. The byte layout matches what PQClean produces with the same
// entropy stream — there is no "shifted" or "padded" encoding // entropy stream — there is no "shifted" or "padded" encoding
// difference between the two paths. // difference between the two paths.
// //
// We can't compare against per-item GPU vs per-item CPU directly // We can't compare against per-item GPU vs per-item CPU directly
// because the batch surface takes a flat seed buffer while the // because the batch surface takes a flat seed buffer while the
+17 -17
View File
@@ -21,17 +21,17 @@
// //
// Backends: // Backends:
// //
// 1. PQClean cgo (default for non-stub builds). Build with // 1. PQClean cgo (default for non-stub builds). Build with
// `-tags=hqc_pqclean`. Wires the vendored PQClean HQC reference // `-tags=hqc_pqclean`. Wires the vendored PQClean HQC reference
// implementation under crypto/hqc/pqclean/ (public domain). NIST // implementation under crypto/hqc/pqclean/ (public domain). NIST
// KAT vectors verify byte-for-byte — see // KAT vectors verify byte-for-byte — see
// crypto/hqc/backend_pqclean_test.go's TestKAT_HQC{128,192,256}. // crypto/hqc/backend_pqclean_test.go's TestKAT_HQC{128,192,256}.
// 2. Cloudflare CIRCL Go (placeholder; build tag `hqc_circl`). // 2. Cloudflare CIRCL Go (placeholder; build tag `hqc_circl`).
// Activates once CIRCL ships HQC support. // Activates once CIRCL ships HQC support.
// 3. Stub (default). When no backend tag is set, every operation // 3. Stub (default). When no backend tag is set, every operation
// returns ErrBackendNotWired so the package still compiles on // returns ErrBackendNotWired so the package still compiles on
// hosts without cgo. The wire format and parameter constants are // hosts without cgo. The wire format and parameter constants are
// fixed by NIST IR 8528 §4.1 and remain stable across backends. // fixed by NIST IR 8528 §4.1 and remain stable across backends.
package hqc package hqc
import ( import (
@@ -58,12 +58,12 @@ const (
// Params returns the fixed sizes for the parameter set. // Params returns the fixed sizes for the parameter set.
type Params struct { type Params struct {
Mode Mode Mode Mode
PublicKeySize int PublicKeySize int
PrivateKeySize int PrivateKeySize int
CiphertextSize int CiphertextSize int
SharedSecretSize int SharedSecretSize int
SecurityLevelBits int // NIST PQ category mapped to ≈ AES key bits SecurityLevelBits int // NIST PQ category mapped to ≈ AES key bits
} }
// MustParamsFor returns the canonical Params for `mode` or panics on // MustParamsFor returns the canonical Params for `mode` or panics on
+3 -3
View File
@@ -16,9 +16,9 @@ import (
) )
var ( var (
once sync.Once once sync.Once
sess *accel.Session sess *accel.Session
initErr error initErr error
available bool available bool
) )
+1 -1
View File
@@ -6,7 +6,7 @@
// - vanilla: golang.org/x/crypto/sha3.NewLegacyKeccak256 (pure Go) // - vanilla: golang.org/x/crypto/sha3.NewLegacyKeccak256 (pure Go)
// - cgo: uses libluxcrypto's optimised C implementation when CGO is on // - cgo: uses libluxcrypto's optimised C implementation when CGO is on
// - gpu: batch-routes through github.com/luxfi/accel for batches that // - gpu: batch-routes through github.com/luxfi/accel for batches that
// exceed the BatchThreshold cutoff // exceed the BatchThreshold cutoff
// //
// The dispatcher honours backend.Default(); see github.com/luxfi/crypto/backend. // The dispatcher honours backend.Default(); see github.com/luxfi/crypto/backend.
package keccak256 package keccak256
+9 -9
View File
@@ -26,12 +26,12 @@ var concurrentBatchThreshold = 8
// //
// Dispatch ladder: // Dispatch ladder:
// //
// 1. GPU substrate (accel.LatticeOps.MLDSAVerifyBatch) when n >= BatchThreshold // 1. GPU substrate (accel.LatticeOps.MLDSAVerifyBatch) when n >= BatchThreshold
// AND a backend plugin is loaded AND mode is in {44, 65, 87}. // AND a backend plugin is loaded AND mode is in {44, 65, 87}.
// 2. Goroutine-parallel CPU verify when n >= concurrentBatchThreshold. // 2. Goroutine-parallel CPU verify when n >= concurrentBatchThreshold.
// Scales to GOMAXPROCS without GPU substrate. Useful on hosts that // Scales to GOMAXPROCS without GPU substrate. Useful on hosts that
// have CPU cores but no GPU plugin (Linux CI, no-Metal Macs, etc). // have CPU cores but no GPU plugin (Linux CI, no-Metal Macs, etc).
// 3. Serial CPU verify as the floor. // 3. Serial CPU verify as the floor.
// //
// All paths are byte-equal: each path ends in cloudflare/circl's // All paths are byte-equal: each path ends in cloudflare/circl's
// FIPS 204-conformant Verify. The dispatch choice only affects throughput, // FIPS 204-conformant Verify. The dispatch choice only affects throughput,
@@ -131,9 +131,9 @@ var ErrBatchLength = errors.New("mldsa: batch input slices have inconsistent len
// //
// Dispatch ladder mirrors BatchVerify: // Dispatch ladder mirrors BatchVerify:
// //
// 1. GPU substrate (accel.LatticeOps.MLDSASignBatch). // 1. GPU substrate (accel.LatticeOps.MLDSASignBatch).
// 2. Goroutine-parallel CPU sign. // 2. Goroutine-parallel CPU sign.
// 3. Serial CPU sign. // 3. Serial CPU sign.
// //
// For deterministic-mode signing (FIPS 204 § Algorithm 2 with rnd=0^256), // For deterministic-mode signing (FIPS 204 § Algorithm 2 with rnd=0^256),
// callers can pass nil for randSource. The CPU path passes deterministic=true // callers can pass nil for randSource. The CPU path passes deterministic=true
+3 -5
View File
@@ -29,8 +29,6 @@ import (
"github.com/cloudflare/circl/sign/mldsa/mldsa44" "github.com/cloudflare/circl/sign/mldsa/mldsa44"
"github.com/luxfi/crypto/backend" "github.com/luxfi/crypto/backend"
) )
// genBatch44 produces n ML-DSA-44 keypairs + signs distinct messages with // genBatch44 produces n ML-DSA-44 keypairs + signs distinct messages with
@@ -223,9 +221,9 @@ func TestMLDSA44_BatchSign_RoundTrip(t *testing.T) {
// BenchmarkMLDSA44_BatchVerify measures throughput of the ML-DSA-44 batch // BenchmarkMLDSA44_BatchVerify measures throughput of the ML-DSA-44 batch
// verify dispatch ladder. Run with -bench=. to compare: // verify dispatch ladder. Run with -bench=. to compare:
// //
// BenchmarkMLDSA44_BatchVerify/serial-1 // BenchmarkMLDSA44_BatchVerify/serial-1
// BenchmarkMLDSA44_BatchVerify/concurrent-8 // BenchmarkMLDSA44_BatchVerify/concurrent-8
// BenchmarkMLDSA44_BatchVerify/concurrent-32 // BenchmarkMLDSA44_BatchVerify/concurrent-32
func BenchmarkMLDSA44_BatchVerify(b *testing.B) { func BenchmarkMLDSA44_BatchVerify(b *testing.B) {
for _, size := range []int{1, 8, 32, 64} { for _, size := range []int{1, 8, 32, 64} {
b.Run(fmt.Sprintf("n=%d", size), func(b *testing.B) { b.Run(fmt.Sprintf("n=%d", size), func(b *testing.B) {
-2
View File
@@ -21,8 +21,6 @@ import (
"github.com/cloudflare/circl/sign/mldsa/mldsa87" "github.com/cloudflare/circl/sign/mldsa/mldsa87"
"github.com/luxfi/crypto/backend" "github.com/luxfi/crypto/backend"
) )
func genBatch87(t testing.TB, n int) (pubs []*PublicKey, msgs [][]byte, sigs [][]byte) { func genBatch87(t testing.TB, n int) (pubs []*PublicKey, msgs [][]byte, sigs [][]byte) {
+6 -6
View File
@@ -50,12 +50,12 @@ func (t DispatchTier) String() string {
// Provenance is the auditable evidence record for the ML-DSA package. // Provenance is the auditable evidence record for the ML-DSA package.
// See slhdsa.Provenance — same shape, same purpose. // See slhdsa.Provenance — same shape, same purpose.
type Provenance struct { type Provenance struct {
Tier DispatchTier Tier DispatchTier
AccelInitialised bool AccelInitialised bool
DeviceAvailable bool DeviceAvailable bool
PluginStrongSymbol bool PluginStrongSymbol bool
BatchThresholdN int BatchThresholdN int
ConcurrentThresholdN int ConcurrentThresholdN int
} }
// GetProvenance returns the current dispatch provenance. // GetProvenance returns the current dispatch provenance.
+8 -8
View File
@@ -81,27 +81,27 @@ func mlkem_decaps_ct_setup() C.int {
return 0 return 0
} }
//export mlkem_decaps_ct_pool_size
//
// Returns the per-sample input width (FIPS 203 ML-KEM-768 ciphertext // Returns the per-sample input width (FIPS 203 ML-KEM-768 ciphertext
// is 1088 bytes). Named "pool_size" for harness API compatibility. // is 1088 bytes). Named "pool_size" for harness API compatibility.
//
//export mlkem_decaps_ct_pool_size
func mlkem_decaps_ct_pool_size() C.size_t { func mlkem_decaps_ct_pool_size() C.size_t {
return C.size_t(dMlkemCTSize) return C.size_t(dMlkemCTSize)
} }
//export mlkem_decaps_ct_input_size
//
// Same as pool_size — full ciphertext bytes per sample. // Same as pool_size — full ciphertext bytes per sample.
//
//export mlkem_decaps_ct_input_size
func mlkem_decaps_ct_input_size() C.size_t { func mlkem_decaps_ct_input_size() C.size_t {
return C.size_t(dMlkemCTSize) return C.size_t(dMlkemCTSize)
} }
//export mlkem_decaps_ct_copy_valid_ct
//
// Copies the class-A reference ciphertext into the caller-supplied C // Copies the class-A reference ciphertext into the caller-supplied C
// buffer (must be at least mlkem_decaps_ct_input_size() bytes). Returns // buffer (must be at least mlkem_decaps_ct_input_size() bytes). Returns
// 0 on success. Avoids passing a Go pointer back through cgo (which // 0 on success. Avoids passing a Go pointer back through cgo (which
// would trip Go 1.26's cgocheck=1 unpinned-pointer panic). // would trip Go 1.26's cgocheck=1 unpinned-pointer panic).
//
//export mlkem_decaps_ct_copy_valid_ct
func mlkem_decaps_ct_copy_valid_ct(dst *C.uint8_t) C.int { func mlkem_decaps_ct_copy_valid_ct(dst *C.uint8_t) C.int {
if len(dMlkemValidCT) == 0 || dst == nil { if len(dMlkemValidCT) == 0 || dst == nil {
return 1 return 1
@@ -110,8 +110,6 @@ func mlkem_decaps_ct_copy_valid_ct(dst *C.uint8_t) C.int {
return 0 return 0
} }
//export mlkem_decaps_ct
//
// One dudect sample: decapsulate the per-sample bytes. Class A → valid // One dudect sample: decapsulate the per-sample bytes. Class A → valid
// reference ciphertext (FO-accept branch). Class B → caller-random // reference ciphertext (FO-accept branch). Class B → caller-random
// bytes (FO-reject branch via implicit rejection). Output is discarded; // bytes (FO-reject branch via implicit rejection). Output is discarded;
@@ -120,6 +118,8 @@ func mlkem_decaps_ct_copy_valid_ct(dst *C.uint8_t) C.int {
// Critical: this function MUST be branchless in its dispatch — only // Critical: this function MUST be branchless in its dispatch — only
// the Decaps call may differ between samples. Any data-dependent // the Decaps call may differ between samples. Any data-dependent
// branch here would surface as a harness artifact. // branch here would surface as a harness artifact.
//
//export mlkem_decaps_ct
func mlkem_decaps_ct(data *C.uint8_t) { func mlkem_decaps_ct(data *C.uint8_t) {
if dMlkemSK == nil { if dMlkemSK == nil {
return return
+6 -6
View File
@@ -33,9 +33,9 @@ import (
const kKeygenRandSize = 64 // ML-KEM-768 keygen tape per FIPS 203 const kKeygenRandSize = 64 // ML-KEM-768 keygen tape per FIPS 203
//export mlkem_keygen_ct_setup
//
// Returns 0 on success. // Returns 0 on success.
//
//export mlkem_keygen_ct_setup
func mlkem_keygen_ct_setup() C.int { func mlkem_keygen_ct_setup() C.int {
// Smoke test: ensure the underlying API is functional with a // Smoke test: ensure the underlying API is functional with a
// zero tape (the class-A input). // zero tape (the class-A input).
@@ -47,16 +47,16 @@ func mlkem_keygen_ct_setup() C.int {
return 0 return 0
} }
//export mlkem_keygen_ct_input_size
//
// Returns the per-sample input width: 64 bytes (the keygen tape). // Returns the per-sample input width: 64 bytes (the keygen tape).
//
//export mlkem_keygen_ct_input_size
func mlkem_keygen_ct_input_size() C.size_t { func mlkem_keygen_ct_input_size() C.size_t {
return C.size_t(kKeygenRandSize) return C.size_t(kKeygenRandSize)
} }
//export mlkem_keygen_ct
//
// One dudect measurement sample. data points to a 64-byte tape. // One dudect measurement sample. data points to a 64-byte tape.
//
//export mlkem_keygen_ct
func mlkem_keygen_ct(data *C.uint8_t) { func mlkem_keygen_ct(data *C.uint8_t) {
src := unsafe.Slice((*byte)(unsafe.Pointer(data)), kKeygenRandSize) src := unsafe.Slice((*byte)(unsafe.Pointer(data)), kKeygenRandSize)
r := bytes.NewReader(src) r := bytes.NewReader(src)
+10 -10
View File
@@ -111,10 +111,10 @@ func buildValidInput(randSrc *[kProofBodyLen + kPubLen]byte) []byte {
return out return out
} }
//export p3q_verify_ct_setup
//
// Initialise the per-startup pool of valid inputs. Returns 0 on // Initialise the per-startup pool of valid inputs. Returns 0 on
// success, non-zero on failure. // success, non-zero on failure.
//
//export p3q_verify_ct_setup
func p3q_verify_ct_setup() C.int { func p3q_verify_ct_setup() C.int {
// Register a backend verifier that always accepts. This pins the // Register a backend verifier that always accepts. This pins the
// CT measurement on the precompile dispatch + backend invocation // CT measurement on the precompile dispatch + backend invocation
@@ -134,24 +134,24 @@ func p3q_verify_ct_setup() C.int {
return 0 return 0
} }
//export p3q_verify_ct_input_size
//
// Returns the per-sample input size for the C harness scratch buffer. // Returns the per-sample input size for the C harness scratch buffer.
//
//export p3q_verify_ct_input_size
func p3q_verify_ct_input_size() C.size_t { func p3q_verify_ct_input_size() C.size_t {
return C.size_t(kInputLen) return C.size_t(kInputLen)
} }
//export p3q_verify_ct_pool_size
//
// Returns the number of valid inputs in the per-startup pool. // Returns the number of valid inputs in the per-startup pool.
//
//export p3q_verify_ct_pool_size
func p3q_verify_ct_pool_size() C.size_t { func p3q_verify_ct_pool_size() C.size_t {
return C.size_t(kValidPool) return C.size_t(kValidPool)
} }
//export p3q_verify_ct_copy_pool
//
// Copies validPool[idx] into the caller-supplied dst buffer // Copies validPool[idx] into the caller-supplied dst buffer
// (kInputLen bytes). Returns 0 on success, non-zero on bounds violation. // (kInputLen bytes). Returns 0 on success, non-zero on bounds violation.
//
//export p3q_verify_ct_copy_pool
func p3q_verify_ct_copy_pool(idx C.size_t, dst *C.uint8_t) C.int { func p3q_verify_ct_copy_pool(idx C.size_t, dst *C.uint8_t) C.int {
i := int(idx) i := int(idx)
if i < 0 || i >= kValidPool || validPool[i] == nil { if i < 0 || i >= kValidPool || validPool[i] == nil {
@@ -168,8 +168,6 @@ var (
supplied = uint64(1 << 30) // far above required for kInputLen supplied = uint64(1 << 30) // far above required for kInputLen
) )
//export p3q_verify_ct
//
// One dudect measurement sample. // One dudect measurement sample.
// //
// data points to kInputLen bytes of caller-controlled wire calldata. // data points to kInputLen bytes of caller-controlled wire calldata.
@@ -180,6 +178,8 @@ var (
// The function MUST be branchless on `data` — any data-dependent // The function MUST be branchless on `data` — any data-dependent
// branch we introduce here pollutes the measurement before Run() // branch we introduce here pollutes the measurement before Run()
// even starts. We only copy data into a fresh slice and dispatch. // even starts. We only copy data into a fresh slice and dispatch.
//
//export p3q_verify_ct
func p3q_verify_ct(data *C.uint8_t) { func p3q_verify_ct(data *C.uint8_t) {
inputSlice := unsafe.Slice((*byte)(unsafe.Pointer(data)), kInputLen) inputSlice := unsafe.Slice((*byte)(unsafe.Pointer(data)), kInputLen)
input := append([]byte{}, inputSlice...) input := append([]byte{}, inputSlice...)
+3 -3
View File
@@ -56,9 +56,9 @@ func NewGenerators(rng io.Reader) (*Generators, error) {
// SHA-256 and then dispatched to NewGeneratorsFromSeed, so the actual on-curve // SHA-256 and then dispatched to NewGeneratorsFromSeed, so the actual on-curve
// derivation is identical to the C++/Metal/CUDA/WGSL canonical: // derivation is identical to the C++/Metal/CUDA/WGSL canonical:
// //
// key = SHA-256(seed) // key = SHA-256(seed)
// G = HashToG1(key || u64_le(0), DST=PEDERSEN_SEEDED_GEN_V1) // G = HashToG1(key || u64_le(0), DST=PEDERSEN_SEEDED_GEN_V1)
// H = HashToG1(key || u64_le(1), DST=PEDERSEN_SEEDED_GEN_V1) // H = HashToG1(key || u64_le(1), DST=PEDERSEN_SEEDED_GEN_V1)
// //
// This collapses LP-137 issue N3 (RED-FINAL §2.4): the legacy two-DST // This collapses LP-137 issue N3 (RED-FINAL §2.4): the legacy two-DST
// PEDERSEN_G_V1 / PEDERSEN_H_V1 path is removed; everything now flows through // PEDERSEN_G_V1 / PEDERSEN_H_V1 path is removed; everything now flows through
+3 -2
View File
@@ -8,14 +8,15 @@
// //
// - Schoolbook O(n^2) -- always correct, fastest below n=64 // - Schoolbook O(n^2) -- always correct, fastest below n=64
// - NTT-based O(n log n) for the negacyclic convolution that lattice // - NTT-based O(n log n) for the negacyclic convolution that lattice
// cryptography (ML-KEM, ML-DSA, Corona) uses // cryptography (ML-KEM, ML-DSA, Corona) uses
// //
// Q = 998244353 is the canonical FFT-friendly prime used by AtCoder, Cyclone-FFT, // Q = 998244353 is the canonical FFT-friendly prime used by AtCoder, Cyclone-FFT,
// the SPOJ POLYMUL reference, and most competitive-programming NTT references. // the SPOJ POLYMUL reference, and most competitive-programming NTT references.
// Its 2-adicity is 23, so the NTT supports lengths up to N = 2^23. // Its 2-adicity is 23, so the NTT supports lengths up to N = 2^23.
// //
// Negacyclic convolution: c[k] = sum_{i+j=k} a[i]*b[j] // Negacyclic convolution: c[k] = sum_{i+j=k} a[i]*b[j]
// - sum_{i+j=k+n} a[i]*b[j] // - sum_{i+j=k+n} a[i]*b[j]
//
// over Z_Q[X]/(X^n + 1) with q the prime above. This is the exact shape // over Z_Q[X]/(X^n + 1) with q the prime above. This is the exact shape
// used by lattice schemes; cyclic convolution is recovered by padding. // used by lattice schemes; cyclic convolution is recovered by padding.
// //
+3 -3
View File
@@ -27,9 +27,9 @@ func lcg(seed uint64, n int) []uint64 {
// that C++ and Metal layers MUST match. // that C++ and Metal layers MUST match.
func TestKATs(t *testing.T) { func TestKATs(t *testing.T) {
type kat struct { type kat struct {
name string name string
n int n int
sA, sB uint64 sA, sB uint64
sum, first, last uint64 sum, first, last uint64
} }
kats := []kat{ kats := []kat{
+5 -5
View File
@@ -15,11 +15,11 @@ import (
var poseidon2KATJSON []byte var poseidon2KATJSON []byte
type kat struct { type kat struct {
Width int `json:"width"` Width int `json:"width"`
FullRounds int `json:"full_rounds"` FullRounds int `json:"full_rounds"`
PartialRounds int `json:"partial_rounds"` PartialRounds int `json:"partial_rounds"`
SBox int `json:"sbox"` SBox int `json:"sbox"`
Cases []katCase `json:"kat"` Cases []katCase `json:"kat"`
} }
type katCase struct { type katCase struct {
-1
View File
@@ -160,4 +160,3 @@ func (e *cpuEngine) verifyBatch(mode Mode, msgs, sigs, pks [][]byte) ([]bool, er
}) })
return res, nil return res, nil
} }
+3 -3
View File
@@ -242,9 +242,9 @@ func TestReduce32_Bounds(t *testing.T) {
// TestAddSubMod_Bounds exercises addModQ / subModQ around the boundary. // TestAddSubMod_Bounds exercises addModQ / subModQ around the boundary.
func TestAddSubMod_Bounds(t *testing.T) { func TestAddSubMod_Bounds(t *testing.T) {
tests := []struct { tests := []struct {
a, b uint32 a, b uint32
wantA uint32 // addModQ(a,b) wantA uint32 // addModQ(a,b)
wantS uint32 // subModQ(a,b) wantS uint32 // subModQ(a,b)
}{ }{
{0, 0, 0, 0}, {0, 0, 0, 0},
{Q - 1, 1, 0, Q - 2}, {Q - 1, 1, 0, Q - 2},
+3 -3
View File
@@ -451,9 +451,9 @@ func SignBatchGPU(privs []*PrivateKey, msgs, sigs [][]byte) (bool, error) {
// //
// Dispatch ladder: // Dispatch ladder:
// //
// 1. GPU substrate (SignBatchGPU) for n >= SignBatchThreshold. // 1. GPU substrate (SignBatchGPU) for n >= SignBatchThreshold.
// 2. Goroutine-parallel CPU sign for n >= concurrentSignThreshold. // 2. Goroutine-parallel CPU sign for n >= concurrentSignThreshold.
// 3. Serial CPU sign as the floor. // 3. Serial CPU sign as the floor.
// //
// Equivalence: SLH-DSA-SHA2 sign is deterministic, so all tiers produce // Equivalence: SLH-DSA-SHA2 sign is deterministic, so all tiers produce
// byte-equal signatures for any given (sk, msg). Per FIPS 205 §10.2 the // byte-equal signatures for any given (sk, msg). Per FIPS 205 §10.2 the
-2
View File
@@ -33,8 +33,6 @@ import (
"testing" "testing"
"github.com/luxfi/crypto/backend" "github.com/luxfi/crypto/backend"
) )
// genSignBatch192f produces n SLH-DSA-192f keypairs ready for SignBatch. // genSignBatch192f produces n SLH-DSA-192f keypairs ready for SignBatch.
-2
View File
@@ -9,8 +9,6 @@ import (
"testing" "testing"
"github.com/luxfi/crypto/backend" "github.com/luxfi/crypto/backend"
) )
// genBatch produces n SLH-DSA-192f keypairs + signs distinct messages with // genBatch produces n SLH-DSA-192f keypairs + signs distinct messages with
+4 -3
View File
@@ -152,9 +152,10 @@ func GetSignatureSize(mode Mode) int {
// GetPrivateKeySize returns the size of a private key for the given mode. // GetPrivateKeySize returns the size of a private key for the given mode.
// FIPS 205 §10 catalogue: sk = 4n where n is the hash output width: // FIPS 205 §10 catalogue: sk = 4n where n is the hash output width:
// 128-bit security : n=16 -> sk=64 //
// 192-bit security : n=24 -> sk=96 // 128-bit security : n=16 -> sk=64
// 256-bit security : n=32 -> sk=128 // 192-bit security : n=24 -> sk=96
// 256-bit security : n=32 -> sk=128
func GetPrivateKeySize(mode Mode) int { func GetPrivateKeySize(mode Mode) int {
switch mode { switch mode {
case SHA2_128s, SHAKE_128s, SHA2_128f, SHAKE_128f: case SHA2_128s, SHAKE_128s, SHA2_128f, SHAKE_128f:
+2 -2
View File
@@ -70,8 +70,8 @@ func TestParseNodeEoA(t *testing.T) {
// EmptyCodeHash deterministically (see parseEoAccountNode in // EmptyCodeHash deterministically (see parseEoAccountNode in
// encoding.go). values[2..255] stay nil after round-trip. // encoding.go). values[2..255] stay nil after round-trip.
values := make([][]byte, 256) values := make([][]byte, 256)
values[0] = zero32[:] // basic data (packed: version+balance+nonce+codesize) values[0] = zero32[:] // basic data (packed: version+balance+nonce+codesize)
values[1] = EmptyCodeHash[:] // code hash — required = EmptyCodeHash for EoA values[1] = EmptyCodeHash[:] // code hash — required = EmptyCodeHash for EoA
ln, err := NewLeafNode(ffx32KeyTest[:31], values) ln, err := NewLeafNode(ffx32KeyTest[:31], values)
if err != nil { if err != nil {
t.Fatalf("error creating leaf node: %v", err) t.Fatalf("error creating leaf node: %v", err)