Skip to content

Commit

Permalink
big update (security)
Browse files Browse the repository at this point in the history
updating security against replay attacks, changing parameters for enhanced robustness, faster.
  • Loading branch information
twingdev committed Apr 9, 2024
1 parent 5a5e1db commit 711ec10
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 63 deletions.
6 changes: 6 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added cpu.prof
Binary file not shown.
8 changes: 7 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@ go 1.22

require github.com/zeebo/blake3 v0.2.3

require github.com/klauspost/cpuid/v2 v2.0.12 // indirect
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.9.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
9 changes: 9 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
89 changes: 71 additions & 18 deletions libzk13.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ import (
"crypto/rand"
"crypto/subtle"
"fmt"
"math/big"

"github.com/davecgh/go-spew/spew"
"github.com/zeebo/blake3"
"math/big"
)

const GENERATOR = 7
const PubKeyRange = 2044 // Size of k, ensure the range is suitable

type ZK13 struct {
p, g, Hs *big.Int
p, g, q, Hs *big.Int
}

// NewZK13 initializes the ZK13 structure with a prime number, generator, and hashed secret.
Expand All @@ -23,11 +22,18 @@ func NewZK13(secretBaggage string, bits int) *ZK13 {
var err error
z := &ZK13{}
p, err = GenerateLargePrime(bits)

if err != nil {
panic(fmt.Sprintf("Failed to generate a large prime: %v", err))
}
g := big.NewInt(GENERATOR)
q, err := GenerateLargePrime(bits / 2)
if err != nil {
panic(fmt.Sprintf("Failed to generate a large prime: %v", err))
}
g, err := GenerateGenerator(p, q)
if err != nil {
panic(fmt.Sprintf("Failed to generate a generator: %v", err))
}
z.q = q
z.g = g
z.p = p
if !z.ValidateParameters(big.NewInt(224)) {
Expand All @@ -37,29 +43,49 @@ func NewZK13(secretBaggage string, bits int) *ZK13 {
}
hash := blake3.Sum512([]byte(secretBaggage))
Hs := new(big.Int).SetBytes(hash[:])

z.Hs = Hs
spew.Dump(z)
return z
}

func (z *ZK13) Prover() (*big.Int, *big.Int) {
k, _ := rand.Int(rand.Reader, z.p) // Prover's random secret
type Proof struct {
R, P, Nonce *big.Int
}

func (z *ZK13) Prover(nonce *big.Int) (*Proof, error) {
k, err := rand.Int(rand.Reader, z.p) // Prover's random secret
if err != nil {
return nil, err
}
r := new(big.Int).Exp(z.g, k, z.p) // r = g^k mod p
F := new(big.Int).Mul(z.Hs, k) // F = Hs*k (simplified, not modulo p-1 for this example)
F := new(big.Int).Mul(z.Hs, k) // F = Hs*k
pMinusOne := new(big.Int).Sub(z.p, big.NewInt(1))
F.Mod(F, pMinusOne) // F = Hs*k mod (p-1)
P := new(big.Int).Exp(z.g, F, z.p) // P = g^F mod p
return r, P
proof := &Proof{
R: r,
P: P,
Nonce: nonce,
}
spew.Dump(proof)
return proof, nil
}

// Verifier checks if the provided proof (r, P) is valid Verifier checks the proof using constant-time comparison
func (z *ZK13) Verifier(r, P *big.Int) bool {

V := new(big.Int).Exp(r, z.Hs, z.p)
// Verifier checks if the provided proof (r, P, nonce) is valid Verifier checks the proof using constant-time comparison
func (z *ZK13) Verifier(proof *Proof) bool {
V := new(big.Int).Exp(proof.R, z.Hs, z.p)
// Convert V and P to byte slices for comparison
VBytes := V.Bytes()
PBytes := P.Bytes()

PBytes := proof.P.Bytes()
// Use subtle.ConstantTimeCompare to prevent timing attacks
return subtle.ConstantTimeCompare(VBytes, PBytes) == 1
if subtle.ConstantTimeCompare(VBytes, PBytes) != 1 {
return false
}
// Check that the nonce is valid
if proof.Nonce.Cmp(big.NewInt(0)) <= 0 {
return false
}
return true
}

func GenerateLargePrime(bit int) (*big.Int, error) {
Expand All @@ -86,6 +112,11 @@ func (z *ZK13) calculateP(F *big.Int) *big.Int {
return new(big.Int).Exp(z.g, F, z.p)
}

func (z *ZK13) GenerateNonce() *big.Int {
b, _ := randBigInt(z.p)
return b
}

// Verify checks if the given P matches r^Hs mod p, validating the proof.
func Verify(r, Hs, P, p *big.Int) bool {
V := new(big.Int).Exp(r, Hs, p)
Expand Down Expand Up @@ -116,3 +147,25 @@ func SetupZK13Verifier(z *ZK13) *Verifier {
type Verifier struct {
k, r, F, P *big.Int
}

// GenerateGenerator generates a generator of the form g = h^((p-1)/q) where
// h is a random element in the field and q is a large prime factor of p-1.
func GenerateGenerator(p, q *big.Int) (*big.Int, error) {
// Generate a random element h in the field
h, err := rand.Int(rand.Reader, p)
if err != nil {
return nil, err
}
// Ensure that h is not a multiple of q
for h.Mod(h, q).Cmp(big.NewInt(0)) == 0 {
h, err = rand.Int(rand.Reader, p)
if err != nil {
return nil, err
}
}
// Compute g = h^((p-1)/q)
pMinusOne := new(big.Int).Sub(p, big.NewInt(1))
pMinusOneOverQ := new(big.Int).Div(pMinusOne, q)
g := new(big.Int).Exp(h, pMinusOneOverQ, p)
return g, nil
}
12 changes: 9 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
)

func main() {
runtime.GOMAXPROCS(7)
// Start a goroutine with an HTTP server for runtime profiling
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
Expand All @@ -28,11 +29,15 @@ func main() {
defer pprof.StopCPUProfile()

// Test different prime lengths
for _, bits := range []int{512, 1024, 2048} {
for _, bits := range []int{512, 1024, 2048, 2048 + 32} {
fmt.Printf("Testing with prime length: %d bits\n", bits)
zk13 := NewZK13("shared secret", bits) // Adjust NewZK13 to accept prime length as an argument
r, P := zk13.Prover()
isValid := zk13.Verifier(r, P)
nonce := zk13.GenerateNonce() // Generate a nonce for replay attack protection
proof, err := zk13.Prover(nonce)
if err != nil {
log.Fatalf("Error generating proof: %v", err)
}
isValid := zk13.Verifier(proof)
fmt.Printf("Verification with %d bits prime: %v\n", bits, isValid)
}

Expand All @@ -46,4 +51,5 @@ func main() {
if err := pprof.WriteHeapProfile(mf); err != nil {
log.Fatal("could not write memory profile: ", err)
}

}
Binary file added mem.prof
Binary file not shown.
Binary file added zk13
Binary file not shown.
41 changes: 0 additions & 41 deletions zk13_test.go
Original file line number Diff line number Diff line change
@@ -1,42 +1 @@
package main

import (
"math/big"
"testing"
)

func BenchmarkCalculateR(b *testing.B) {
g := big.NewInt(7)
k, _ := randBigInt(big.NewInt(100))
p := big.NewInt(2741)

for i := 0; i < b.N; i++ {
calculateR(g, k, p)
}
}

func BenchmarkCalculateP(b *testing.B) {
g := big.NewInt(7)
Hs := big.NewInt(88) // Simulating the hash result for benchmarking
k, _ := randBigInt(big.NewInt(100))
p := big.NewInt(2741)
F := calculateF(Hs, k, p)

for i := 0; i < b.N; i++ {
calculateP(g, F, p)
}
}

func BenchmarkVerify(b *testing.B) {
g := big.NewInt(7)
k, _ := randBigInt(big.NewInt(100))
p := big.NewInt(2741)
Hs := big.NewInt(88) // Simulating the hash result for benchmarking
r := calculateR(g, k, p)
F := calculateF(Hs, k, p)
P := calculateP(g, F, p)

for i := 0; i < b.N; i++ {
verify(r, Hs, P, p)
}
}

0 comments on commit 711ec10

Please sign in to comment.