From 4e680657f0f59dae07dbb5a388d3205dd67dfe0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Wed, 17 Jun 2026 13:20:12 -0700 Subject: [PATCH 1/6] fix ECDSA P-256 private key construction panic on Go 1.26 --- ecdsa.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ecdsa.go b/ecdsa.go index 091dc4b9..6a2ae135 100644 --- a/ecdsa.go +++ b/ecdsa.go @@ -223,9 +223,19 @@ func goecdsaPrivateKey(curve elliptic.Curve, d *big.Int) (*ecdsa.PrivateKey, err // compute the crypto/ecdsa public key if curve == elliptic.P256() { - // use crypto/ecdh implementation to perform base scalar multiplication - // of an ECDH private key, because crypto/elliptic deprecated `ScalarBaseMult` - ecdhPriv, err := priv.ECDH() + // Perform the base scalar multiplication using crypto/ecdh, + // because crypto/elliptic deprecated `ScalarBaseMult`. + // + // We build the ecdh.PrivateKey directly from the scalar bytes + // instead of going through `priv.ECDH()`: since Go 1.26, + // ecdsa's `(*PrivateKey).ECDH` serializes the key via `(*PrivateKey).Bytes`, + // which reads the public affine coordinates `X`/`Y`. + // Those are not set yet at this point (we are computing them), + // so that path dereferences nil and panics. + // Constructing the ecdh key from the scalar avoids reading `X`/`Y` + // and works across Go versions. + scalarLen := bitsToBytes(curve.Params().N.BitLen()) + ecdhPriv, err := ecdh.P256().NewPrivateKey(d.FillBytes(make([]byte, scalarLen))) if err != nil { // at this point, no error is expected because the function can't be called // with a zero scalar modulo `n` From 311158551f01c671bb1cd09243fe604ac3234791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 22 Jun 2026 13:17:58 -0700 Subject: [PATCH 2/6] update to Go 1.26 --- .github/workflows/ci.yml | 2 +- README.md | 2 +- go.mod | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 875cf64a..067eee19 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ on: - v[0-9]+.[0-9]+ env: - GO_VERSION: "1.25" + GO_VERSION: "1.26" LINT_VERSION: "v2.4.0" concurrency: diff --git a/README.md b/README.md index e938f036..0c78ecac 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Notes: ## Module import -🚧 Flow cryptography package is tested for Go version 1.25. +🚧 Flow cryptography package is tested for Go version 1.26. It is recommended to not build the package with a later Go version. The package is not guaranteed to behave as expected with later Go versions. 🚧 diff --git a/go.mod b/go.mod index 82e322d3..344580d9 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/onflow/crypto -go 1.25.1 +go 1.26.0 require ( github.com/btcsuite/btcd/btcec/v2 v2.3.4 From 66bf13920e4d556dda78808b8da085c40923af32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 22 Jun 2026 13:27:07 -0700 Subject: [PATCH 3/6] add regression test for P-256 private-key construction panic in Go 1.26 --- ecdsa_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/ecdsa_test.go b/ecdsa_test.go index fe6c338b..30ba13d4 100644 --- a/ecdsa_test.go +++ b/ecdsa_test.go @@ -24,6 +24,7 @@ import ( "crypto/elliptic" crand "crypto/rand" + "math/big" "github.com/btcsuite/btcd/btcec/v2" "github.com/stretchr/testify/assert" @@ -269,6 +270,51 @@ func TestECDSAPublicKeyComputation(t *testing.T) { } } +// TestGoECDSAP256PrivateKeyConstruction exercises `goecdsaPrivateKey` for P-256 directly. +// +// This is a regression test for a panic that surfaced on Go 1.26: +// when constructing the key, the public affine coordinates `X`/`Y` are still nil +// (we are in the middle of computing them via base scalar multiplication). +// Since Go 1.26, `(*ecdsa.PrivateKey).ECDH` serializes the key through +// `(*PrivateKey).Bytes`, which reads `X`/`Y` and therefore panicked on the nil deref. +// The fix builds the ecdh key from the scalar bytes instead. +// +// The test asserts the construction does not panic and that the computed public key +// matches a known test vector, so it guards both the crash and the correctness of the +// scalar-based code path. +func TestGoECDSAP256PrivateKeyConstruction(t *testing.T) { + // scalar / expected public key pair, identical to the P-256 vector in + // TestECDSAPublicKeyComputation + const skHex = "6e37a39c31a05181bf77919ace790efd0bdbcaf42b5a52871fc112fceb918c95" + const xHex = "78a80dfe190a6068be8ddf05644c32d2540402ffc682442f6a9eeb96125d8681" + const yHex = "3789f92cf4afabf719aaba79ecec54b27e33a188f83158f6dd15ecb231b49808" + + skBytes, err := hex.DecodeString(skHex) + require.NoError(t, err) + d := new(big.Int).SetBytes(skBytes) + + // the call panicked on Go 1.26 before the fix + require.NotPanics(t, func() { + priv, err := goecdsaPrivateKey(elliptic.P256(), d) + require.NoError(t, err) + require.NotNil(t, priv) + + // the scalar must be preserved + assert.Equal(t, 0, priv.D.Cmp(d)) + + // the computed public affine coordinates must match the known vector + expectedX, ok := new(big.Int).SetString(xHex, 16) + require.True(t, ok) + expectedY, ok := new(big.Int).SetString(yHex, 16) + require.True(t, ok) + assert.Equal(t, 0, priv.PublicKey.X.Cmp(expectedX)) + assert.Equal(t, 0, priv.PublicKey.Y.Cmp(expectedY)) + + // the computed point must be on the curve + assert.True(t, elliptic.P256().IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y)) + }) +} + func TestSignatureFormatCheck(t *testing.T) { for _, curve := range ecdsaCurves { From afaedb5a92c31d7f9f92f639aaabea0ae46bac9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 22 Jun 2026 13:35:57 -0700 Subject: [PATCH 4/6] update to latest golangci-lint, compatible with Go 1.26 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 067eee19..a4f66357 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ on: env: GO_VERSION: "1.26" - LINT_VERSION: "v2.4.0" + LINT_VERSION: "v2.12.2" concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} From e7e054e596aed1ba6c278b2dff2ed771a2754016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 22 Jun 2026 14:07:53 -0700 Subject: [PATCH 5/6] ignore use of API deprecated in Go 1.26 for now --- .golangci.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index ca737b81..d73fb864 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,6 +10,17 @@ linters: - linters: - govet text: "unsafeptr" # disable flagging unsafeptr usage + # ecdsa.go wraps crypto/ecdsa, whose Sign/Verify still consume the raw + # PrivateKey.D and PublicKey.X/Y fields. + # Go 1.26 deprecated direct access to those fields, but the recommended + # replacement API (ecdsa.ParseRawPrivateKey / ParseUncompressedPublicKey / + # (*PrivateKey).Bytes / (*PublicKey).Bytes) supports only the NIST curves and + # rejects secp256k1, which this package supports via btcec's custom + # elliptic.Curve, so the package has to keep using the low-level fields. + - path: (^|/)ecdsa(_test)?\.go$ + linters: + - staticcheck + text: "SA1019" formatters: exclusions: paths: From c456e7277998640e0a1b379c295bf4dae406779b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 22 Jun 2026 14:16:34 -0700 Subject: [PATCH 6/6] go fix ./... --- bls12381_utils_test.go | 6 +++--- bls_test.go | 34 +++++++++++++++++----------------- bls_thresholdsign_test.go | 22 +++++++++++----------- common.go | 6 +++--- dkg.go | 4 ++-- dkg_test.go | 16 ++++++++-------- hash/hash_test.go | 12 ++++++------ hash/keccak.go | 5 +---- hash/xor_generic.go | 2 +- random/chacha20.go | 2 +- random/rand.go | 4 ++-- random/rand_test.go | 6 +++--- sign_test_utils.go | 8 ++++---- thresholdsign.go | 4 ++-- 14 files changed, 64 insertions(+), 67 deletions(-) diff --git a/bls12381_utils_test.go b/bls12381_utils_test.go index 5fd58471..f392be05 100644 --- a/bls12381_utils_test.go +++ b/bls12381_utils_test.go @@ -176,7 +176,7 @@ func TestMapToG1(t *testing.T) { // Hashing to G1 bench func BenchmarkMapToG1(b *testing.B) { input := make([]byte, expandMsgOutput) - for i := 0; i < len(input); i++ { + for i := range input { input[i] = byte(i) } b.ResetTimer() @@ -248,7 +248,7 @@ func TestReadWriteG1(t *testing.T) { // and compare it the original point t.Run("random points", func(t *testing.T) { iterations := 50 - for i := 0; i < iterations; i++ { + for range iterations { var p, q pointE1 _, err := prg.Read(seed) unsafeMapToG1(&p, seed) @@ -326,7 +326,7 @@ func BenchmarkPairing(b *testing.B) { pointsG1 := make([]pointE1, pairingsNumber) pointsG2 := make([]pointE2, pairingsNumber) - for i := 0; i < pairingsNumber; i++ { + for i := range pairingsNumber { unsafeMapToG1(&pointsG1[i], seed[i*frBytesLen:(i+1)*frBytesLen]) unsafeMapToG2(&pointsG2[i], seed[i*frBytesLen:(i+1)*frBytesLen]) } diff --git a/bls_test.go b/bls_test.go index 7a4902dd..f7e7893d 100644 --- a/bls_test.go +++ b/bls_test.go @@ -296,7 +296,7 @@ func TestBLSPOP(t *testing.T) { t.Run("PoP tests", func(t *testing.T) { loops := 10 - for j := 0; j < loops; j++ { + for range loops { n, err := rand.Read(seed) require.Equal(t, n, KeyGenSeedMinLen) require.NoError(t, err) @@ -360,7 +360,7 @@ func TestBLSAggregateSignatures(t *testing.T) { var aggSig, expectedSig Signature // create the signatures - for i := 0; i < sigsNum; i++ { + for range sigsNum { sk := randomSK(t, rand) s, err := sk.Sign(input, kmac) require.NoError(t, err) @@ -477,7 +477,7 @@ func TestBLSAggregatePublicKeys(t *testing.T) { sks := make([]PrivateKey, 0, pkNum) // create the signatures - for i := 0; i < pkNum; i++ { + for range pkNum { sk := randomSK(t, rand) sks = append(sks, sk) pks = append(pks, sk.PublicKey()) @@ -599,7 +599,7 @@ func TestBLSRemovePubKeys(t *testing.T) { pks := make([]PublicKey, 0, pkNum) // generate public keys - for i := 0; i < pkNum; i++ { + for range pkNum { sk := randomSK(t, rand) pks = append(pks, sk.PublicKey()) } @@ -695,7 +695,7 @@ func TestBLSBatchVerify(t *testing.T) { expectedValid := make([]bool, 0, sigsNum) // create the signatures - for i := 0; i < sigsNum; i++ { + for range sigsNum { sk := randomSK(t, rand) s, err := sk.Sign(input, kmac) require.NoError(t, err) @@ -761,7 +761,7 @@ func TestBLSBatchVerify(t *testing.T) { // generate a random permutation of indices to pick the // invalid signatures. indices := make([]int, 0, sigsNum) - for i := 0; i < sigsNum; i++ { + for i := range sigsNum { indices = append(indices, i) } rand.Shuffle(sigsNum, func(i, j int) { @@ -770,7 +770,7 @@ func TestBLSBatchVerify(t *testing.T) { // some signatures are invalid t.Run("some signatures are invalid", func(t *testing.T) { - for i := 0; i < invalidSigsNum; i++ { // alter invalidSigsNum random signatures + for i := range invalidSigsNum { // alter invalidSigsNum random signatures alterSignature(sigs[indices[i]]) expectedValid[indices[i]] = false } @@ -805,7 +805,7 @@ func TestBLSBatchVerify(t *testing.T) { // test incorrect inputs t.Run("inconsistent inputs", func(t *testing.T) { - for i := 0; i < sigsNum; i++ { + for i := range sigsNum { expectedValid[i] = false } valid, err := BatchVerifyBLSSignaturesOneMessage(pks[:len(pks)-1], sigs, input, kmac) @@ -816,7 +816,7 @@ func TestBLSBatchVerify(t *testing.T) { // test wrong hasher t.Run("invalid hasher", func(t *testing.T) { - for i := 0; i < sigsNum; i++ { + for i := range sigsNum { expectedValid[i] = false } valid, err := BatchVerifyBLSSignaturesOneMessage(pks, sigs, input, nil) @@ -828,7 +828,7 @@ func TestBLSBatchVerify(t *testing.T) { // test wrong key t.Run("wrong key", func(t *testing.T) { - for i := 0; i < sigsNum; i++ { + for i := range sigsNum { expectedValid[i] = false } pks[0] = invalidSK(t).PublicKey() @@ -870,7 +870,7 @@ func BenchmarkBatchVerify(b *testing.B) { seed := make([]byte, KeyGenSeedMinLen) // create the signatures - for i := 0; i < sigsNum; i++ { + for range sigsNum { _, err := crand.Read(seed) require.NoError(b, err) sk, err := GeneratePrivateKey(BLSBLS12381, seed) @@ -927,7 +927,7 @@ func TestBLSAggregateSignaturesManyMessages(t *testing.T) { keysNum := rand.Intn(sigsNum) + 1 sks := make([]PrivateKey, 0, keysNum) // generate the keys - for i := 0; i < keysNum; i++ { + for range keysNum { sk := randomSK(t, rand) sks = append(sks, sk) } @@ -935,7 +935,7 @@ func TestBLSAggregateSignaturesManyMessages(t *testing.T) { // number of messages (could be larger or smaller than the number of keys) msgsNum := rand.Intn(sigsNum) + 1 messages := make([][20]byte, msgsNum) - for i := 0; i < msgsNum; i++ { + for i := range msgsNum { _, err := rand.Read(messages[i][:]) require.NoError(t, err) } @@ -945,7 +945,7 @@ func TestBLSAggregateSignaturesManyMessages(t *testing.T) { inputKmacs := make([]hash.Hasher, 0, sigsNum) // create the signatures - for i := 0; i < sigsNum; i++ { + for range sigsNum { kmac := NewExpandMsgXOFKMAC128("test tag") // pick a key randomly from the list skRand := rand.Intn(keysNum) @@ -1041,7 +1041,7 @@ func TestBLSAggregateSignaturesManyMessages(t *testing.T) { pks := make([]PublicKey, 0, N) kmacs := make([]hash.Hasher, 0, N) kmac := NewExpandMsgXOFKMAC128("test tag") - for i := 0; i < N; i++ { + for range N { // distinct message msg := make([]byte, 20) msgs = append(msgs, msg) @@ -1112,7 +1112,7 @@ func BenchmarkVerifySignatureManyMessages(b *testing.B) { seed := make([]byte, KeyGenSeedMinLen) // create the signatures - for i := 0; i < sigsNum; i++ { + for range sigsNum { input := make([]byte, 100) _, err := crand.Read(input) require.NoError(b, err) @@ -1155,7 +1155,7 @@ func BenchmarkAggregate(b *testing.B) { pks := make([]PublicKey, 0, sigsNum) // create the signatures - for i := 0; i < sigsNum; i++ { + for range sigsNum { _, err := crand.Read(seed) require.NoError(b, err) sk, err := GeneratePrivateKey(BLSBLS12381, seed) diff --git a/bls_thresholdsign_test.go b/bls_thresholdsign_test.go index 745d8d87..a69155bf 100644 --- a/bls_thresholdsign_test.go +++ b/bls_thresholdsign_test.go @@ -61,7 +61,7 @@ func testCentralizedStatefulAPI(t *testing.T) { // hasher kmac := NewExpandMsgXOFKMAC128(thresholdSignatureTag) // fill the signers list and shuffle it - for i := 0; i < n; i++ { + for i := range n { signers = append(signers, i) } rand.Shuffle(n, func(i, j int) { @@ -343,7 +343,7 @@ func testDistributedStatefulAPI_FeldmanVSS(t *testing.T) { processors := make([]testDKGProcessor, 0, n) // create n processors for all participants - for current := 0; current < n; current++ { + for current := range n { processors = append(processors, testDKGProcessor{ current: current, chans: chans, @@ -357,7 +357,7 @@ func testDistributedStatefulAPI_FeldmanVSS(t *testing.T) { } // create the participant (buffered) communication channels - for i := 0; i < n; i++ { + for i := range n { chans[i] = make(chan *message, 2*n) } // start DKG in all participants @@ -366,7 +366,7 @@ func testDistributedStatefulAPI_FeldmanVSS(t *testing.T) { require.Equal(t, read, KeyGenSeedMinLen) require.NoError(t, err) sync.Add(n) - for current := 0; current < n; current++ { + for current := range n { err := processors[current].dkg.Start(seed) require.NoError(t, err) go tsDkgRunChan(&processors[current], &sync, t, 2) @@ -381,7 +381,7 @@ func testDistributedStatefulAPI_FeldmanVSS(t *testing.T) { // Start TS log.Info("TS starts") sync.Add(n) - for i := 0; i < n; i++ { + for i := range n { go tsRunChan(&processors[i], &sync, t) } // synchronize the main thread to end TS @@ -403,7 +403,7 @@ func testDistributedStatefulAPI_JointFeldman(t *testing.T) { processors := make([]testDKGProcessor, 0, n) // create n processors for all participants - for current := 0; current < n; current++ { + for current := range n { processors = append(processors, testDKGProcessor{ current: current, chans: chans, @@ -417,7 +417,7 @@ func testDistributedStatefulAPI_JointFeldman(t *testing.T) { } // create the participant (buffered) communication channels - for i := 0; i < n; i++ { + for i := range n { chans[i] = make(chan *message, 2*n) } // start DKG in all participants but the @@ -426,7 +426,7 @@ func testDistributedStatefulAPI_JointFeldman(t *testing.T) { require.Equal(t, read, KeyGenSeedMinLen) require.NoError(t, err) sync.Add(n) - for current := 0; current < n; current++ { + for current := range n { err := processors[current].dkg.Start(seed) require.NoError(t, err) go tsDkgRunChan(&processors[current], &sync, t, 0) @@ -436,7 +436,7 @@ func testDistributedStatefulAPI_JointFeldman(t *testing.T) { for phase := 1; phase <= 2; phase++ { sync.Wait() sync.Add(n) - for current := 0; current < n; current++ { + for current := range n { go tsDkgRunChan(&processors[current], &sync, t, phase) } } @@ -451,7 +451,7 @@ func testDistributedStatefulAPI_JointFeldman(t *testing.T) { // Start TS log.Info("TS starts") sync.Add(n) - for current := 0; current < n; current++ { + for current := range n { go tsRunChan(&processors[current], &sync, t) } // synchronize the main thread to end TS @@ -577,7 +577,7 @@ func testCentralizedStatelessAPI(t *testing.T) { signShares := make([]Signature, 0, n) signers := make([]int, 0, n) // fill the signers list and shuffle it - for i := 0; i < n; i++ { + for i := range n { signers = append(signers, i) } rand.Shuffle(n, func(i, j int) { diff --git a/common.go b/common.go index 960b2085..dc74e5d2 100644 --- a/common.go +++ b/common.go @@ -45,7 +45,7 @@ func overwrite(data []byte) { _, err := rand.Read(data) // checking err is enough if err != nil { // zero the buffer if randomizing failed - for i := 0; i < len(data); i++ { + for i := range data { data[i] = 0 } } @@ -63,7 +63,7 @@ func (e invalidInputsError) Unwrap() error { } // invalidInputsErrorf constructs a new invalidInputsError -func invalidInputsErrorf(msg string, args ...interface{}) error { +func invalidInputsErrorf(msg string, args ...any) error { return &invalidInputsError{ error: fmt.Errorf(msg, args...), } @@ -97,7 +97,7 @@ func (e invalidHasherSizeError) Unwrap() error { } // invalidHasherSizeErrorf constructs a new invalidHasherSizeError -func invalidHasherSizeErrorf(msg string, args ...interface{}) error { +func invalidHasherSizeErrorf(msg string, args ...any) error { return &invalidHasherSizeError{ error: fmt.Errorf(msg, args...), } diff --git a/dkg.go b/dkg.go index f080f471..2709fb6f 100644 --- a/dkg.go +++ b/dkg.go @@ -98,7 +98,7 @@ type dkgFailureError struct { } // dkgFailureErrorf constructs a new dkgFailureError -func dkgFailureErrorf(msg string, args ...interface{}) error { +func dkgFailureErrorf(msg string, args ...any) error { return &dkgFailureError{ error: fmt.Errorf(msg, args...), } @@ -121,7 +121,7 @@ func (e dkgInvalidStateTransitionError) Unwrap() error { } // dkgInvalidStateTransitionErrorf constructs a new dkgInvalidStateTransitionError -func dkgInvalidStateTransitionErrorf(msg string, args ...interface{}) error { +func dkgInvalidStateTransitionErrorf(msg string, args ...any) error { return &dkgInvalidStateTransitionError{ error: fmt.Errorf(msg, args...), } diff --git a/dkg_test.go b/dkg_test.go index d9dab748..e225d5b9 100644 --- a/dkg_test.go +++ b/dkg_test.go @@ -181,7 +181,7 @@ func dkgCommonTest(t *testing.T, dkg int, n int, threshold int, test testCase) { chans := make([]chan *message, n) lateChansTimeout1 := make([]chan *message, n) lateChansTimeout2 := make([]chan *message, n) - for i := 0; i < n; i++ { + for i := range n { chans[i] = make(chan *message, 5*n) lateChansTimeout1[i] = make(chan *message, 5*n) lateChansTimeout2[i] = make(chan *message, 5*n) @@ -197,7 +197,7 @@ func dkgCommonTest(t *testing.T, dkg int, n int, threshold int, test testCase) { // create n processors for all participants processors := make([]testDKGProcessor, 0, n) - for current := 0; current < n; current++ { + for current := range n { list := make([]bool, dealers) processors = append(processors, testDKGProcessor{ current: current, @@ -295,7 +295,7 @@ func dkgCommonTest(t *testing.T, dkg int, n int, threshold int, test testCase) { var sync sync.WaitGroup // create DKG in all participants - for current := 0; current < n; current++ { + for current := range n { var err error processors[current].dkg, err = newDKG(dkg, n, threshold, current, &processors[current], lead) @@ -314,12 +314,12 @@ func dkgCommonTest(t *testing.T, dkg int, n int, threshold int, test testCase) { log.Info("DKG protocol starts") - for current := 0; current < n; current++ { + for current := range n { processors[current].startSync.Add(1) go dkgRunChan(&processors[current], &sync, t, phase) } - for current := 0; current < n; current++ { + for current := range n { // start dkg in parallel // ( one common PRG is used internally for all instances which causes a race // in generating randoms and leads to non-deterministic keys. If deterministic keys @@ -340,7 +340,7 @@ func dkgCommonTest(t *testing.T, dkg int, n int, threshold int, test testCase) { // post processing required for timeout edge case tests go timeoutPostProcess(processors, t, phase) sync.Add(n) - for current := 0; current < n; current++ { + for current := range n { go dkgRunChan(&processors[current], &sync, t, phase) } } @@ -434,7 +434,7 @@ func dkgRunChan(proc *testDKGProcessor, func timeoutPostProcess(processors []testDKGProcessor, t *testing.T, phase int) { switch phase { case 1: - for i := 0; i < len(processors); i++ { + for i := range processors { go func(i int) { for len(processors[0].lateChansTimeout1[i]) != 0 { // to test timeouted messages, late messages are copied to the main channels @@ -444,7 +444,7 @@ func timeoutPostProcess(processors []testDKGProcessor, t *testing.T, phase int) }(i) } case 2: - for i := 0; i < len(processors); i++ { + for i := range processors { go func(i int) { for len(processors[0].lateChansTimeout2[i]) != 0 { // to test timeouted messages, late messages are copied to the main channels diff --git a/hash/hash_test.go b/hash/hash_test.go index 1c0c1b7d..09de08d8 100644 --- a/hash/hash_test.go +++ b/hash/hash_test.go @@ -107,7 +107,7 @@ func TestSanityKmac128(t *testing.T) { hash := alg.SumHash() assert.Equal(t, expected[0], hash) - for i := 0; i < len(customizers); i++ { + for i := range customizers { alg, err = NewKMAC_128(key, customizers[i], outputSize) require.Nil(t, err) hash = alg.ComputeHash(input) @@ -183,7 +183,7 @@ func TestHashersAPI(t *testing.T) { func TestSHA2(t *testing.T) { t.Run("SHA2_256", func(t *testing.T) { - for i := 0; i < 5000; i++ { + for i := range 5000 { value := make([]byte, i) _, err := rand.Read(value) require.NoError(t, err) @@ -202,7 +202,7 @@ func TestSHA2(t *testing.T) { }) t.Run("SHA2_384", func(t *testing.T) { - for i := 0; i < 5000; i++ { + for i := range 5000 { value := make([]byte, i) _, err := rand.Read(value) require.NoError(t, err) @@ -220,7 +220,7 @@ func TestSHA2(t *testing.T) { // the output of standard Go sha3. func TestSHA3(t *testing.T) { t.Run("SHA3_256", func(t *testing.T) { - for i := 0; i < 5000; i++ { + for i := range 5000 { value := make([]byte, i) _, err := rand.Read(value) require.NoError(t, err) @@ -239,7 +239,7 @@ func TestSHA3(t *testing.T) { }) t.Run("SHA3_384", func(t *testing.T) { - for i := 0; i < 5000; i++ { + for i := range 5000 { value := make([]byte, i) _, err := rand.Read(value) require.NoError(t, err) @@ -256,7 +256,7 @@ func TestSHA3(t *testing.T) { // It compares the hashes of random data of different lengths to // the output of Go LegacyKeccak. func TestKeccak(t *testing.T) { - for i := 0; i < 5000; i++ { + for i := range 5000 { value := make([]byte, i) _, err := rand.Read(value) require.NoError(t, err) diff --git a/hash/keccak.go b/hash/keccak.go index 0a980fbb..aa2752ae 100644 --- a/hash/keccak.go +++ b/hash/keccak.go @@ -171,10 +171,7 @@ func (d *spongeState) write(p []byte) { keccakF1600(&d.a) } else { // The slow path; buffer the input until we can fill the sponge, and then xor it in. - todo := d.rate - d.bufSize - if todo > len(p) { - todo = len(p) - } + todo := min(d.rate-d.bufSize, len(p)) d.appendBuf(p[:todo]) p = p[todo:] diff --git a/hash/xor_generic.go b/hash/xor_generic.go index 613691f9..308b7dd6 100644 --- a/hash/xor_generic.go +++ b/hash/xor_generic.go @@ -65,7 +65,7 @@ func (b *storageBuf) asBytes() *[maxRate]byte { func xorIn(d *spongeState, buf []byte) { n := len(buf) / 8 - for i := 0; i < n; i++ { + for i := range n { a := binary.LittleEndian.Uint64(buf) d.a[i] ^= a buf = buf[8:] diff --git a/random/chacha20.go b/random/chacha20.go index 001310ac..6792f697 100644 --- a/random/chacha20.go +++ b/random/chacha20.go @@ -140,7 +140,7 @@ func (c *chachaCore) Read(buffer []byte) { } else { // when buffer is large, use is as the message to encrypt, // but this requires clearing it first. - for i := 0; i < len(buffer); i++ { + for i := range buffer { buffer[i] = 0 } message = buffer diff --git a/random/rand.go b/random/rand.go index 7c61af26..31fdd661 100644 --- a/random/rand.go +++ b/random/rand.go @@ -133,7 +133,7 @@ func (p *genericPRG) Permutation(n int) ([]int, error) { return nil, fmt.Errorf("population size cannot be negative") } items := make([]int, n) - for i := 0; i < n; i++ { + for i := range n { j := p.UintN(uint64(i + 1)) items[i] = items[j] items[j] = i @@ -183,7 +183,7 @@ func (p *genericPRG) Samples(n int, m int, swap func(i, j int)) error { if n < m { return fmt.Errorf("sample size (%d) cannot be larger than entire population (%d)", m, n) } - for i := 0; i < m; i++ { + for i := range m { j := p.UintN(uint64(n - i)) swap(i, i+int(j)) } diff --git a/random/rand_test.go b/random/rand_test.go index e4f6f9bb..7a29ebaa 100644 --- a/random/rand_test.go +++ b/random/rand_test.go @@ -176,7 +176,7 @@ func TestSubPermutation(t *testing.T) { orderingDistribution := make([]float64, subsetSize) testElement := rand.Intn(listSize) - for i := 0; i < sampleSize; i++ { + for range sampleSize { shuffledlist, err := rng.SubPermutation(listSize, subsetSize) require.NoError(t, err) require.Equal(t, len(shuffledlist), subsetSize) @@ -329,11 +329,11 @@ func TestSamples(t *testing.T) { testElement := rand.Intn(listSize) // Slice to shuffle list := make([]int, 0, listSize) - for i := 0; i < listSize; i++ { + for i := range listSize { list = append(list, i) } - for i := 0; i < sampleSize; i++ { + for range sampleSize { err = rng.Samples(listSize, samplesSize, func(i, j int) { list[i], list[j] = list[j], list[i] }) diff --git a/sign_test_utils.go b/sign_test_utils.go index 55789351..b0f2a7ae 100644 --- a/sign_test_utils.go +++ b/sign_test_utils.go @@ -79,7 +79,7 @@ func testGenSignVerify(t *testing.T, salg SigningAlgorithm, halg hash.Hasher) { rand := getPRG(t) loops := 50 - for j := 0; j < loops; j++ { + for range loops { n, err := rand.Read(seed) require.Equal(t, n, KeyGenSeedMinLen) require.NoError(t, err) @@ -179,7 +179,7 @@ func testEncodeDecode(t *testing.T, salg SigningAlgorithm) { t.Run("happy path tests", func(t *testing.T) { loops := 50 - for j := 0; j < loops; j++ { + for range loops { // generate a private key seed := make([]byte, KeyGenSeedMinLen) read, err := rand.Read(seed) @@ -319,7 +319,7 @@ func testKeySize(t *testing.T, sk PrivateKey, skLen int, pkLen int) { func benchVerify(b *testing.B, algo SigningAlgorithm, halg hash.Hasher) { b.Run(fmt.Sprintf("verify %s", algo), func(b *testing.B) { seed := make([]byte, 48) - for j := 0; j < len(seed); j++ { + for j := range seed { seed[j] = byte(j) } sk, err := GeneratePrivateKey(algo, seed) @@ -346,7 +346,7 @@ func benchVerify(b *testing.B, algo SigningAlgorithm, halg hash.Hasher) { func benchSign(b *testing.B, algo SigningAlgorithm, halg hash.Hasher) { b.Run(fmt.Sprintf("Single sign %s", algo), func(b *testing.B) { seed := make([]byte, 48) - for j := 0; j < len(seed); j++ { + for j := range seed { seed[j] = byte(j) } sk, err := GeneratePrivateKey(algo, seed) diff --git a/thresholdsign.go b/thresholdsign.go index fef64f01..c245f74f 100644 --- a/thresholdsign.go +++ b/thresholdsign.go @@ -184,7 +184,7 @@ type duplicatedSignerError struct { } // duplicatedSignerErrorf constructs a new duplicatedSignerError. -func duplicatedSignerErrorf(msg string, args ...interface{}) error { +func duplicatedSignerErrorf(msg string, args ...any) error { return &duplicatedSignerError{error: fmt.Errorf(msg, args...)} } @@ -201,7 +201,7 @@ type notEnoughSharesError struct { } // notEnoughSharesErrorf constructs a new notEnoughSharesError. -func notEnoughSharesErrorf(msg string, args ...interface{}) error { +func notEnoughSharesErrorf(msg string, args ...any) error { return ¬EnoughSharesError{error: fmt.Errorf(msg, args...)} }