Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
f80deee
fixAfterAPIBreak
ValeriodeSa Jul 17, 2025
e1a1bf1
ThreesholdsArePositive
ValeriodeSa Jul 17, 2025
64dd821
ThreesholdsArePositive
thehoul Nov 14, 2025
37c622b
compatibleAndMergeReports
ValeriodeSa Jul 24, 2025
20d789c
Copied over filosottile/bigmod
ValeriodeSa Aug 4, 2025
938d80b
Added build tags for non-constant time algorithms
ValeriodeSa Aug 4, 2025
00d00d6
Refactor Const and Vartime Tests and GroupOrder becomes a big/Int
ValeriodeSa Aug 4, 2025
fe602df
Compatible_Mod
ValeriodeSa Aug 5, 2025
0ad50f8
Mod Int Migrates to compatible
ValeriodeSa Aug 5, 2025
529bc5a
fix rebase error
thehoul Nov 14, 2025
5b987f1
fixAfterAPIBreak
ValeriodeSa Jul 17, 2025
88e3a5b
ThreesholdsArePositive
ValeriodeSa Jul 17, 2025
3bfa1e9
compatibleInt
ValeriodeSa Jul 22, 2025
8db7444
compatibleAndMergeReports
ValeriodeSa Jul 24, 2025
f03b092
Added build tags for non-constant time algorithms
ValeriodeSa Aug 4, 2025
21d1177
Compatible_Mod
ValeriodeSa Aug 5, 2025
03d4c8a
Mod Int's Value becomes a Pointer
ValeriodeSa Aug 6, 2025
21d4bc1
Use big/Int instead of compatible/Int in vartime only files
ValeriodeSa Aug 11, 2025
e408ebb
Mod/Int's V, CompatibleMod/Mod and Compatible/Int have direct values
ValeriodeSa Aug 11, 2025
d13f03b
Constant Time Int also gets a direct value
ValeriodeSa Aug 11, 2025
d563ec9
Refactoring for constant-time compatibility
ValeriodeSa Aug 11, 2025
c5f879e
const_int: +3 functions to implement and a sketch for Bytes
ValeriodeSa Aug 11, 2025
da4bc81
Refactoring for constant-time compatibility
ValeriodeSa Aug 11, 2025
eeacbe2
Implemented FillBytes as in saferith.Nat
ValeriodeSa Aug 15, 2025
68ea487
SetString gets a new modulus parameter to define its size for constan…
ValeriodeSa Aug 18, 2025
76378b7
Bytes gets a new modulus parameter to define its size for constant-time
ValeriodeSa Aug 18, 2025
b8d2253
ModInverse gets a constant-time implementation, from edwards25519/sca…
ValeriodeSa Aug 18, 2025
b48d7e5
rand/Int uses big/Int again
ValeriodeSa Aug 18, 2025
382f7cb
took Bit(i) implementation from big.nat
ValeriodeSa Aug 19, 2025
d8e1bc9
Tests and debug for constant-time operations
ValeriodeSa Aug 20, 2025
a22c303
Clean-up of mod/constant_time_int.go Pick function, implemented using…
ValeriodeSa Aug 20, 2025
124c580
small fixes in mod/constant_time_int.go operations
ValeriodeSa Aug 20, 2025
d7a3d4b
Tests and debug for group/mod/constant_time_int.go
ValeriodeSa Aug 21, 2025
1db4f70
More fixes and tests for the constant-time implementation
ValeriodeSa Aug 24, 2025
2fd346b
modify twoExp256 related internal constants to adapt to a larger need…
ValeriodeSa Aug 24, 2025
b55bcca
Fixed compatible.Prime
ValeriodeSa Aug 24, 2025
4b09c27
SetBytesBigBuffer to create a bigmod/nat from a longer buffer
ValeriodeSa Aug 26, 2025
8c0c223
Fixed a bug in pub_nat/SetBytesBigBuffer
ValeriodeSa Aug 29, 2025
27dff2f
fix rebase error
thehoul Nov 17, 2025
cdecc7e
remove duplicate line in test.yml and use matrix for constant vs var …
thehoul Nov 24, 2025
08eda3b
fix failing test
thehoul Nov 24, 2025
b6fc9c2
fix build with constantTime tag failling
thehoul Nov 24, 2025
3e9a84c
simplify test workflow
thehoul Nov 24, 2025
96194b6
fix obvious comments from the PR
thehoul Nov 27, 2025
dbaec73
Add build target to Makefile
thehoul Nov 27, 2025
8b8c27e
Add !constantTime build tag to edwards25519/scalar.go
thehoul Nov 27, 2025
027da7f
fix building with constantTime tag failing
thehoul Nov 27, 2025
72bbc54
make rand.Int() use compatible.Int and compatible_mod.Mod instead of …
thehoul Nov 27, 2025
695dccf
Remove SetBytes and replace by SetBytesMod and SetBytesWithCheck
thehoul Dec 1, 2025
bab8707
Make primeOrder and fullOrder a compatible_mod.Mod in const.go
thehoul Dec 9, 2025
f049c80
fix const_int.go Mod function
thehoul Dec 9, 2025
3958132
fix SetBytesMod constant time
thehoul Dec 9, 2025
0f207c4
fix encoding_test.go
thehoul Dec 9, 2025
a03c234
fix lll and forbidigo lint complaints
thehoul Dec 9, 2025
406d787
exclude compatible/bigmod from lint checks
thehoul Dec 9, 2025
2822e2b
fix receiver name consistency (lint complaints)
thehoul Dec 9, 2025
abde829
fix int and scalar tests using fmt (lint complaints)
thehoul Dec 10, 2025
ffcee46
rename comptabile_mod to compatiblemod (lint complaint)
thehoul Dec 10, 2025
783b398
update compatible_test.go
thehoul Dec 11, 2025
697de7b
fix tag use in test workflow
thehoul Dec 11, 2025
d0f6e28
change test workflow to use pull_request and not pull_request_target
thehoul Dec 11, 2025
5ff2640
Add int32-repro-cpy to push branches
thehoul Dec 12, 2025
d409aec
Fix formatting in tests.yml for TAG assignment
thehoul Dec 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: v2.6.1
version: v2.6.1
18 changes: 15 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name: Go Tests

on:
pull_request_target:
pull_request:
types: [opened, synchronize, reopened, labeled]
push:
branches: [ master ]
branches: [ master, int32-repro-cpy ]

concurrency:
group: ci-${{ github.ref }}-test
Expand Down Expand Up @@ -40,6 +40,7 @@ jobs:
os: [windows-latest, ubuntu-latest, macos-latest]
size: ['64b', '32b']
golang: ['1.25.4']
tag : ['', 'constantTime']
exclude:
- os: windows-latest
size: '32b'
Expand Down Expand Up @@ -93,7 +94,18 @@ jobs:

- name: Test with coverage
if: ${{ matrix.os == 'ubuntu-latest' && matrix.size == '64b' }}
run: make coverage
run: |
TAG="${{ matrix.tag }}"
ARGS=""
if [ -n "${{ matrix.tag }}" ]; then
ARGS="-tags $TAG"
fi

go test $ARGS \
-json -covermode=count \
-coverprofile=profile.cov ./... \
> report.jsonl


- name: SonarQube Scan
if: ${{ matrix.os == 'ubuntu-latest' && matrix.size == '64b' }}
Expand Down
1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ linters:
- third_party$
- builtin$
- examples$
- compatible/bigmod/*
issues:
max-same-issues: 50
formatters:
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ test: tidy
go test ./...

coverage: tidy
go test -json -covermode=count -coverprofile=profile.cov ./... > report.json
go test -json -covermode=count -coverprofile=profile.cov ./... > report.jsonl

# target to run all the possible checks; it's a good habit to run it before
# pushing code
check: lint test
echo "check done"

build: tidy
go build ./...
go build -tags constantTime ./...
66 changes: 66 additions & 0 deletions astwalk/prova.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//go:build experimental
// +build experimental

package main

import (
"fmt"
"go/ast"
"go/types"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/singlechecker"
)

type Set struct {
m map[string]struct{}
}

var Analyzer = &analysis.Analyzer{
Name: "funcCallTypes",
Doc: "prints the types of the function calls",
Run: run,
}

func run(pass *analysis.Pass) (interface{}, error) {
var funcs = &Set{m: make(map[string]struct{})}
for _, file := range pass.Files {
ast.Inspect(file, func(node ast.Node) bool {
if fd, ok := node.(*ast.FuncDecl); ok {
if fd.Type.Params != nil {
for _, param := range fd.Type.Params.List {
if t := pass.TypesInfo.TypeOf(param.Type); t != nil {
if ptr, ok := t.(*types.Pointer); ok {
if named, ok := ptr.Elem().(*types.Named); ok {
if named.Obj().Pkg() != nil &&
named.Obj().Pkg().Path() == "math/big" &&
named.Obj().Name() == "Int" {
funcs.m[fd.Name.Name] = struct{}{}
}
}
}
}
}
}
}
return true
})
for f := range funcs.m {
fmt.Println(f)
}
//ast.Inspect(file, func(node ast.Node) bool {
// if call, ok := node.(*ast.CallExpr); ok {
// if t := pass.TypesInfo.TypeOf(call.Fun); t != nil {
// fmt.Printf("Function call type: %v\n", t)
// }
// }
// return true
//})
}
return nil, nil
}

func main() {
// Run the analyzer
singlechecker.Main(Analyzer)

}
2 changes: 2 additions & 0 deletions benchmark/benchmark.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build !constantTime

package main

import (
Expand Down
205 changes: 205 additions & 0 deletions benchmark/constant_benchmark.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
//go:build constantTime

package main

import (
"encoding/json"
"fmt"
"go.dedis.ch/kyber/v4/pairing/bls12381/circl"
"os"
"testing"

"go.dedis.ch/kyber/v4"
"go.dedis.ch/kyber/v4/group/edwards25519"
"go.dedis.ch/kyber/v4/sign/anon"
"go.dedis.ch/kyber/v4/sign/bls"
"go.dedis.ch/kyber/v4/util/test"
)

var (
outputFile = "../docs/benchmark-app/src/data/data.json"
suites = []kyber.Group{
edwards25519.NewBlakeSHA256Ed25519(),
circl.NewSuiteBLS12381(),
}
signatures = []string{"anon", "bls"}
)

// BenchmarkGroup runs benchmarks for the given group and writes the results to a JSON file.
func benchmarkGroup(name string, description string, gb *test.GroupBench) map[string]interface{} {
fmt.Printf("Running benchmarks for group %s...\n", name)
results := make(map[string]map[string]testing.BenchmarkResult)

// Scalar operations
results["scalar"] = make(map[string]testing.BenchmarkResult)
results["scalar"]["add"] = testing.Benchmark(func(b *testing.B) {
gb.ScalarAdd(b.N)
})
results["scalar"]["sub"] = testing.Benchmark(func(b *testing.B) {
gb.ScalarSub(b.N)
})
results["scalar"]["neg"] = testing.Benchmark(func(b *testing.B) {
gb.ScalarNeg(b.N)
})
results["scalar"]["mul"] = testing.Benchmark(func(b *testing.B) {
gb.ScalarMul(b.N)
})
results["scalar"]["div"] = testing.Benchmark(func(b *testing.B) {
gb.ScalarDiv(b.N)
})
results["scalar"]["inv"] = testing.Benchmark(func(b *testing.B) {
gb.ScalarInv(b.N)
})
results["scalar"]["pick"] = testing.Benchmark(func(b *testing.B) {
gb.ScalarPick(b.N)
})
results["scalar"]["encode"] = testing.Benchmark(func(b *testing.B) {
gb.ScalarEncode(b.N)
})
results["scalar"]["decode"] = testing.Benchmark(func(b *testing.B) {
gb.ScalarDecode(b.N)
})

// Point operations
results["point"] = make(map[string]testing.BenchmarkResult)
results["point"]["add"] = testing.Benchmark(func(b *testing.B) {
gb.PointAdd(b.N)
})
results["point"]["sub"] = testing.Benchmark(func(b *testing.B) {
gb.PointSub(b.N)
})
results["point"]["neg"] = testing.Benchmark(func(b *testing.B) {
gb.PointNeg(b.N)
})
results["point"]["mul"] = testing.Benchmark(func(b *testing.B) {
gb.PointMul(b.N)
})
results["point"]["baseMul"] = testing.Benchmark(func(b *testing.B) {
gb.PointBaseMul(b.N)
})
results["point"]["pick"] = testing.Benchmark(func(b *testing.B) {
gb.PointPick(b.N)
})
results["point"]["encode"] = testing.Benchmark(func(b *testing.B) {
gb.PointEncode(b.N)
})
results["point"]["decode"] = testing.Benchmark(func(b *testing.B) {
gb.PointDecode(b.N)
})

result := map[string]interface{}{
"group": name,
"description": description,
"benchmarks": results,
}

return result
}

// BenchmarkSign runs benchmarks for the some signature schemes.
func benchmarkSign(sigType string) map[string]interface{} {
fmt.Printf("Running benchmarks for %s signature scheme...\n", sigType)
results := make(map[string]map[string]testing.BenchmarkResult)
results["keygen"] = make(map[string]testing.BenchmarkResult)
results["sign"] = make(map[string]testing.BenchmarkResult)
results["verify"] = make(map[string]testing.BenchmarkResult)

benchMessage := []byte("Hello World!")
keys := []int{1, 10, 100}

if sigType == "anon" {
// Generate keys
for _, i := range keys {
results["keygen"][fmt.Sprintf("%d", i)] = testing.Benchmark(func(b *testing.B) {
for j := 0; j < b.N; j++ {
anon.BenchGenKeys(edwards25519.NewBlakeSHA256Ed25519(), i)
}
})
}
benchPubEd25519, benchPriEd25519 := anon.BenchGenKeys(edwards25519.NewBlakeSHA256Ed25519(), keys[len(keys)-1])

// Signing
for _, i := range keys {
results["sign"][fmt.Sprintf("%d", i)] = testing.Benchmark(func(b *testing.B) {
anon.BenchSign(edwards25519.NewBlakeSHA256Ed25519(), benchPubEd25519[:i], benchPriEd25519, b.N, benchMessage)
})
}

// Verification
for _, i := range keys {
results["verify"][fmt.Sprintf("%d", i)] = testing.Benchmark(func(b *testing.B) {
anon.BenchVerify(edwards25519.NewBlakeSHA256Ed25519(), benchPubEd25519[:i],
anon.BenchGenSig(edwards25519.NewBlakeSHA256Ed25519(), i, benchMessage, benchPubEd25519, benchPriEd25519),
b.N, benchMessage)
})
}
} else if sigType == "bls" {
// Key generation
for _, i := range keys {
scheme := bls.NewSchemeOnG1(circl.NewSuite())
results["keygen"][fmt.Sprintf("%d", i)] = testing.Benchmark(func(b *testing.B) {
test.BenchCreateKeys(b, scheme, i)
})
}

// Signing
for _, i := range keys {
results["sign"][fmt.Sprintf("%d", i)] = testing.Benchmark(func(b *testing.B) {
scheme, _, privates, _, _ := test.PrepareBLS(i)
test.BenchSign(b, scheme, benchMessage, privates)
})
}

// Verification
for _, i := range keys {
results["verify"][fmt.Sprintf("%d", i)] = testing.Benchmark(func(b *testing.B) {
scheme, publics, _, msgs, sigs := test.PrepareBLS(i)
test.BLSBenchVerify(b, sigs, scheme, publics, msgs)
})
}
}

result := map[string]interface{}{
"name": sigType,
"description": "",
"benchmarks": results,
}

return result
}

func main() {
// Write results to JSON file
results := make(map[string]map[string]map[string]interface{})

file, err := os.Create(outputFile)
if err != nil {
fmt.Println("Error creating output file:", err)
return
}
defer file.Close()

encoder := json.NewEncoder(file)
encoder.SetIndent("", " ")

// Run benchmarks for each group
results["groups"] = make(map[string]map[string]interface{})
for _, suite := range suites {
groupBench := test.NewGroupBench(suite)
result := benchmarkGroup(suite.String(), "Description", groupBench)
results["groups"][suite.String()] = result
}

// Run benchmarks for signatures
results["sign"] = make(map[string]map[string]interface{})
for _, sigType := range signatures {
result := benchmarkSign(sigType)
results["sign"][sigType] = result
}

if err := encoder.Encode(results); err != nil {
fmt.Println("Error encoding JSON:", err)
return
}
fmt.Printf("Benchmark results written to %s\n", outputFile)
}
27 changes: 27 additions & 0 deletions compatible/bigmod/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Copyright (c) 2009 The Go Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9 changes: 9 additions & 0 deletions compatible/bigmod/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Package bigmod implements constant-time big integer arithmetic modulo large
moduli. Unlike math/big, this package is suitable for implementing
security-sensitive cryptographic operations. It is a re-exported version the
standard library package crypto/internal/fips140/bigmod used to implement
crypto/rsa amongst others.

v0.1.0 is up to date with Go 1.24.

The API is NOT stable.
Loading
Loading