From fef2b26e59d1408219ff6fac871136b20cfabeb7 Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Wed, 25 Jan 2023 14:10:59 +0100 Subject: [PATCH 01/13] chore(templates): move ecdsa to signature dir --- ecc/bls12-377/{ => signature}/ecdsa/doc.go | 0 ecc/bls12-377/{ => signature}/ecdsa/ecdsa.go | 0 ecc/bls12-377/{ => signature}/ecdsa/ecdsa_test.go | 0 ecc/bls12-377/{ => signature}/ecdsa/marshal.go | 0 ecc/bls12-377/{ => signature}/ecdsa/marshal_test.go | 0 ecc/bls12-378/{ => signature}/ecdsa/doc.go | 0 ecc/bls12-378/{ => signature}/ecdsa/ecdsa.go | 0 ecc/bls12-378/{ => signature}/ecdsa/ecdsa_test.go | 0 ecc/bls12-378/{ => signature}/ecdsa/marshal.go | 0 ecc/bls12-378/{ => signature}/ecdsa/marshal_test.go | 0 ecc/bls12-381/{ => signature}/ecdsa/doc.go | 0 ecc/bls12-381/{ => signature}/ecdsa/ecdsa.go | 0 ecc/bls12-381/{ => signature}/ecdsa/ecdsa_test.go | 0 ecc/bls12-381/{ => signature}/ecdsa/marshal.go | 0 ecc/bls12-381/{ => signature}/ecdsa/marshal_test.go | 0 ecc/bls24-315/{ => signature}/ecdsa/doc.go | 0 ecc/bls24-315/{ => signature}/ecdsa/ecdsa.go | 0 ecc/bls24-315/{ => signature}/ecdsa/ecdsa_test.go | 0 ecc/bls24-315/{ => signature}/ecdsa/marshal.go | 0 ecc/bls24-315/{ => signature}/ecdsa/marshal_test.go | 0 ecc/bls24-317/{ => signature}/ecdsa/doc.go | 0 ecc/bls24-317/{ => signature}/ecdsa/ecdsa.go | 0 ecc/bls24-317/{ => signature}/ecdsa/ecdsa_test.go | 0 ecc/bls24-317/{ => signature}/ecdsa/marshal.go | 0 ecc/bls24-317/{ => signature}/ecdsa/marshal_test.go | 0 ecc/bn254/{ => signature}/ecdsa/doc.go | 0 ecc/bn254/{ => signature}/ecdsa/ecdsa.go | 0 ecc/bn254/{ => signature}/ecdsa/ecdsa_test.go | 0 ecc/bn254/{ => signature}/ecdsa/marshal.go | 0 ecc/bn254/{ => signature}/ecdsa/marshal_test.go | 0 ecc/bw6-633/{ => signature}/ecdsa/doc.go | 0 ecc/bw6-633/{ => signature}/ecdsa/ecdsa.go | 0 ecc/bw6-633/{ => signature}/ecdsa/ecdsa_test.go | 0 ecc/bw6-633/{ => signature}/ecdsa/marshal.go | 0 ecc/bw6-633/{ => signature}/ecdsa/marshal_test.go | 0 ecc/bw6-756/{ => signature}/ecdsa/doc.go | 0 ecc/bw6-756/{ => signature}/ecdsa/ecdsa.go | 0 ecc/bw6-756/{ => signature}/ecdsa/ecdsa_test.go | 0 ecc/bw6-756/{ => signature}/ecdsa/marshal.go | 0 ecc/bw6-756/{ => signature}/ecdsa/marshal_test.go | 0 ecc/bw6-761/{ => signature}/ecdsa/doc.go | 0 ecc/bw6-761/{ => signature}/ecdsa/ecdsa.go | 0 ecc/bw6-761/{ => signature}/ecdsa/ecdsa_test.go | 0 ecc/bw6-761/{ => signature}/ecdsa/marshal.go | 0 ecc/bw6-761/{ => signature}/ecdsa/marshal_test.go | 0 ecc/secp256k1/{ => signature}/ecdsa/doc.go | 0 ecc/secp256k1/{ => signature}/ecdsa/ecdsa.go | 0 ecc/secp256k1/{ => signature}/ecdsa/ecdsa_test.go | 0 ecc/secp256k1/{ => signature}/ecdsa/marshal.go | 0 ecc/secp256k1/{ => signature}/ecdsa/marshal_test.go | 0 ecc/stark-curve/{ => signature}/ecdsa/doc.go | 0 ecc/stark-curve/{ => signature}/ecdsa/ecdsa.go | 0 ecc/stark-curve/{ => signature}/ecdsa/ecdsa_test.go | 0 ecc/stark-curve/{ => signature}/ecdsa/marshal.go | 0 ecc/stark-curve/{ => signature}/ecdsa/marshal_test.go | 0 internal/generator/main.go | 4 ++-- internal/generator/{ => signature}/ecdsa/generate.go | 2 +- internal/generator/{ => signature}/ecdsa/template/doc.go.tmpl | 0 .../generator/{ => signature}/ecdsa/template/ecdsa.go.tmpl | 0 .../{ => signature}/ecdsa/template/ecdsa.test.go.tmpl | 0 .../generator/{ => signature}/ecdsa/template/marshal.go.tmpl | 0 .../{ => signature}/ecdsa/template/marshal.test.go.tmpl | 0 62 files changed, 3 insertions(+), 3 deletions(-) rename ecc/bls12-377/{ => signature}/ecdsa/doc.go (100%) rename ecc/bls12-377/{ => signature}/ecdsa/ecdsa.go (100%) rename ecc/bls12-377/{ => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bls12-377/{ => signature}/ecdsa/marshal.go (100%) rename ecc/bls12-377/{ => signature}/ecdsa/marshal_test.go (100%) rename ecc/bls12-378/{ => signature}/ecdsa/doc.go (100%) rename ecc/bls12-378/{ => signature}/ecdsa/ecdsa.go (100%) rename ecc/bls12-378/{ => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bls12-378/{ => signature}/ecdsa/marshal.go (100%) rename ecc/bls12-378/{ => signature}/ecdsa/marshal_test.go (100%) rename ecc/bls12-381/{ => signature}/ecdsa/doc.go (100%) rename ecc/bls12-381/{ => signature}/ecdsa/ecdsa.go (100%) rename ecc/bls12-381/{ => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bls12-381/{ => signature}/ecdsa/marshal.go (100%) rename ecc/bls12-381/{ => signature}/ecdsa/marshal_test.go (100%) rename ecc/bls24-315/{ => signature}/ecdsa/doc.go (100%) rename ecc/bls24-315/{ => signature}/ecdsa/ecdsa.go (100%) rename ecc/bls24-315/{ => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bls24-315/{ => signature}/ecdsa/marshal.go (100%) rename ecc/bls24-315/{ => signature}/ecdsa/marshal_test.go (100%) rename ecc/bls24-317/{ => signature}/ecdsa/doc.go (100%) rename ecc/bls24-317/{ => signature}/ecdsa/ecdsa.go (100%) rename ecc/bls24-317/{ => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bls24-317/{ => signature}/ecdsa/marshal.go (100%) rename ecc/bls24-317/{ => signature}/ecdsa/marshal_test.go (100%) rename ecc/bn254/{ => signature}/ecdsa/doc.go (100%) rename ecc/bn254/{ => signature}/ecdsa/ecdsa.go (100%) rename ecc/bn254/{ => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bn254/{ => signature}/ecdsa/marshal.go (100%) rename ecc/bn254/{ => signature}/ecdsa/marshal_test.go (100%) rename ecc/bw6-633/{ => signature}/ecdsa/doc.go (100%) rename ecc/bw6-633/{ => signature}/ecdsa/ecdsa.go (100%) rename ecc/bw6-633/{ => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bw6-633/{ => signature}/ecdsa/marshal.go (100%) rename ecc/bw6-633/{ => signature}/ecdsa/marshal_test.go (100%) rename ecc/bw6-756/{ => signature}/ecdsa/doc.go (100%) rename ecc/bw6-756/{ => signature}/ecdsa/ecdsa.go (100%) rename ecc/bw6-756/{ => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bw6-756/{ => signature}/ecdsa/marshal.go (100%) rename ecc/bw6-756/{ => signature}/ecdsa/marshal_test.go (100%) rename ecc/bw6-761/{ => signature}/ecdsa/doc.go (100%) rename ecc/bw6-761/{ => signature}/ecdsa/ecdsa.go (100%) rename ecc/bw6-761/{ => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bw6-761/{ => signature}/ecdsa/marshal.go (100%) rename ecc/bw6-761/{ => signature}/ecdsa/marshal_test.go (100%) rename ecc/secp256k1/{ => signature}/ecdsa/doc.go (100%) rename ecc/secp256k1/{ => signature}/ecdsa/ecdsa.go (100%) rename ecc/secp256k1/{ => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/secp256k1/{ => signature}/ecdsa/marshal.go (100%) rename ecc/secp256k1/{ => signature}/ecdsa/marshal_test.go (100%) rename ecc/stark-curve/{ => signature}/ecdsa/doc.go (100%) rename ecc/stark-curve/{ => signature}/ecdsa/ecdsa.go (100%) rename ecc/stark-curve/{ => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/stark-curve/{ => signature}/ecdsa/marshal.go (100%) rename ecc/stark-curve/{ => signature}/ecdsa/marshal_test.go (100%) rename internal/generator/{ => signature}/ecdsa/generate.go (90%) rename internal/generator/{ => signature}/ecdsa/template/doc.go.tmpl (100%) rename internal/generator/{ => signature}/ecdsa/template/ecdsa.go.tmpl (100%) rename internal/generator/{ => signature}/ecdsa/template/ecdsa.test.go.tmpl (100%) rename internal/generator/{ => signature}/ecdsa/template/marshal.go.tmpl (100%) rename internal/generator/{ => signature}/ecdsa/template/marshal.test.go.tmpl (100%) diff --git a/ecc/bls12-377/ecdsa/doc.go b/ecc/bls12-377/signature/ecdsa/doc.go similarity index 100% rename from ecc/bls12-377/ecdsa/doc.go rename to ecc/bls12-377/signature/ecdsa/doc.go diff --git a/ecc/bls12-377/ecdsa/ecdsa.go b/ecc/bls12-377/signature/ecdsa/ecdsa.go similarity index 100% rename from ecc/bls12-377/ecdsa/ecdsa.go rename to ecc/bls12-377/signature/ecdsa/ecdsa.go diff --git a/ecc/bls12-377/ecdsa/ecdsa_test.go b/ecc/bls12-377/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls12-377/ecdsa/ecdsa_test.go rename to ecc/bls12-377/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bls12-377/ecdsa/marshal.go b/ecc/bls12-377/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bls12-377/ecdsa/marshal.go rename to ecc/bls12-377/signature/ecdsa/marshal.go diff --git a/ecc/bls12-377/ecdsa/marshal_test.go b/ecc/bls12-377/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls12-377/ecdsa/marshal_test.go rename to ecc/bls12-377/signature/ecdsa/marshal_test.go diff --git a/ecc/bls12-378/ecdsa/doc.go b/ecc/bls12-378/signature/ecdsa/doc.go similarity index 100% rename from ecc/bls12-378/ecdsa/doc.go rename to ecc/bls12-378/signature/ecdsa/doc.go diff --git a/ecc/bls12-378/ecdsa/ecdsa.go b/ecc/bls12-378/signature/ecdsa/ecdsa.go similarity index 100% rename from ecc/bls12-378/ecdsa/ecdsa.go rename to ecc/bls12-378/signature/ecdsa/ecdsa.go diff --git a/ecc/bls12-378/ecdsa/ecdsa_test.go b/ecc/bls12-378/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls12-378/ecdsa/ecdsa_test.go rename to ecc/bls12-378/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bls12-378/ecdsa/marshal.go b/ecc/bls12-378/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bls12-378/ecdsa/marshal.go rename to ecc/bls12-378/signature/ecdsa/marshal.go diff --git a/ecc/bls12-378/ecdsa/marshal_test.go b/ecc/bls12-378/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls12-378/ecdsa/marshal_test.go rename to ecc/bls12-378/signature/ecdsa/marshal_test.go diff --git a/ecc/bls12-381/ecdsa/doc.go b/ecc/bls12-381/signature/ecdsa/doc.go similarity index 100% rename from ecc/bls12-381/ecdsa/doc.go rename to ecc/bls12-381/signature/ecdsa/doc.go diff --git a/ecc/bls12-381/ecdsa/ecdsa.go b/ecc/bls12-381/signature/ecdsa/ecdsa.go similarity index 100% rename from ecc/bls12-381/ecdsa/ecdsa.go rename to ecc/bls12-381/signature/ecdsa/ecdsa.go diff --git a/ecc/bls12-381/ecdsa/ecdsa_test.go b/ecc/bls12-381/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls12-381/ecdsa/ecdsa_test.go rename to ecc/bls12-381/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bls12-381/ecdsa/marshal.go b/ecc/bls12-381/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bls12-381/ecdsa/marshal.go rename to ecc/bls12-381/signature/ecdsa/marshal.go diff --git a/ecc/bls12-381/ecdsa/marshal_test.go b/ecc/bls12-381/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls12-381/ecdsa/marshal_test.go rename to ecc/bls12-381/signature/ecdsa/marshal_test.go diff --git a/ecc/bls24-315/ecdsa/doc.go b/ecc/bls24-315/signature/ecdsa/doc.go similarity index 100% rename from ecc/bls24-315/ecdsa/doc.go rename to ecc/bls24-315/signature/ecdsa/doc.go diff --git a/ecc/bls24-315/ecdsa/ecdsa.go b/ecc/bls24-315/signature/ecdsa/ecdsa.go similarity index 100% rename from ecc/bls24-315/ecdsa/ecdsa.go rename to ecc/bls24-315/signature/ecdsa/ecdsa.go diff --git a/ecc/bls24-315/ecdsa/ecdsa_test.go b/ecc/bls24-315/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls24-315/ecdsa/ecdsa_test.go rename to ecc/bls24-315/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bls24-315/ecdsa/marshal.go b/ecc/bls24-315/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bls24-315/ecdsa/marshal.go rename to ecc/bls24-315/signature/ecdsa/marshal.go diff --git a/ecc/bls24-315/ecdsa/marshal_test.go b/ecc/bls24-315/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls24-315/ecdsa/marshal_test.go rename to ecc/bls24-315/signature/ecdsa/marshal_test.go diff --git a/ecc/bls24-317/ecdsa/doc.go b/ecc/bls24-317/signature/ecdsa/doc.go similarity index 100% rename from ecc/bls24-317/ecdsa/doc.go rename to ecc/bls24-317/signature/ecdsa/doc.go diff --git a/ecc/bls24-317/ecdsa/ecdsa.go b/ecc/bls24-317/signature/ecdsa/ecdsa.go similarity index 100% rename from ecc/bls24-317/ecdsa/ecdsa.go rename to ecc/bls24-317/signature/ecdsa/ecdsa.go diff --git a/ecc/bls24-317/ecdsa/ecdsa_test.go b/ecc/bls24-317/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls24-317/ecdsa/ecdsa_test.go rename to ecc/bls24-317/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bls24-317/ecdsa/marshal.go b/ecc/bls24-317/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bls24-317/ecdsa/marshal.go rename to ecc/bls24-317/signature/ecdsa/marshal.go diff --git a/ecc/bls24-317/ecdsa/marshal_test.go b/ecc/bls24-317/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls24-317/ecdsa/marshal_test.go rename to ecc/bls24-317/signature/ecdsa/marshal_test.go diff --git a/ecc/bn254/ecdsa/doc.go b/ecc/bn254/signature/ecdsa/doc.go similarity index 100% rename from ecc/bn254/ecdsa/doc.go rename to ecc/bn254/signature/ecdsa/doc.go diff --git a/ecc/bn254/ecdsa/ecdsa.go b/ecc/bn254/signature/ecdsa/ecdsa.go similarity index 100% rename from ecc/bn254/ecdsa/ecdsa.go rename to ecc/bn254/signature/ecdsa/ecdsa.go diff --git a/ecc/bn254/ecdsa/ecdsa_test.go b/ecc/bn254/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bn254/ecdsa/ecdsa_test.go rename to ecc/bn254/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bn254/ecdsa/marshal.go b/ecc/bn254/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bn254/ecdsa/marshal.go rename to ecc/bn254/signature/ecdsa/marshal.go diff --git a/ecc/bn254/ecdsa/marshal_test.go b/ecc/bn254/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bn254/ecdsa/marshal_test.go rename to ecc/bn254/signature/ecdsa/marshal_test.go diff --git a/ecc/bw6-633/ecdsa/doc.go b/ecc/bw6-633/signature/ecdsa/doc.go similarity index 100% rename from ecc/bw6-633/ecdsa/doc.go rename to ecc/bw6-633/signature/ecdsa/doc.go diff --git a/ecc/bw6-633/ecdsa/ecdsa.go b/ecc/bw6-633/signature/ecdsa/ecdsa.go similarity index 100% rename from ecc/bw6-633/ecdsa/ecdsa.go rename to ecc/bw6-633/signature/ecdsa/ecdsa.go diff --git a/ecc/bw6-633/ecdsa/ecdsa_test.go b/ecc/bw6-633/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bw6-633/ecdsa/ecdsa_test.go rename to ecc/bw6-633/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bw6-633/ecdsa/marshal.go b/ecc/bw6-633/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bw6-633/ecdsa/marshal.go rename to ecc/bw6-633/signature/ecdsa/marshal.go diff --git a/ecc/bw6-633/ecdsa/marshal_test.go b/ecc/bw6-633/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bw6-633/ecdsa/marshal_test.go rename to ecc/bw6-633/signature/ecdsa/marshal_test.go diff --git a/ecc/bw6-756/ecdsa/doc.go b/ecc/bw6-756/signature/ecdsa/doc.go similarity index 100% rename from ecc/bw6-756/ecdsa/doc.go rename to ecc/bw6-756/signature/ecdsa/doc.go diff --git a/ecc/bw6-756/ecdsa/ecdsa.go b/ecc/bw6-756/signature/ecdsa/ecdsa.go similarity index 100% rename from ecc/bw6-756/ecdsa/ecdsa.go rename to ecc/bw6-756/signature/ecdsa/ecdsa.go diff --git a/ecc/bw6-756/ecdsa/ecdsa_test.go b/ecc/bw6-756/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bw6-756/ecdsa/ecdsa_test.go rename to ecc/bw6-756/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bw6-756/ecdsa/marshal.go b/ecc/bw6-756/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bw6-756/ecdsa/marshal.go rename to ecc/bw6-756/signature/ecdsa/marshal.go diff --git a/ecc/bw6-756/ecdsa/marshal_test.go b/ecc/bw6-756/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bw6-756/ecdsa/marshal_test.go rename to ecc/bw6-756/signature/ecdsa/marshal_test.go diff --git a/ecc/bw6-761/ecdsa/doc.go b/ecc/bw6-761/signature/ecdsa/doc.go similarity index 100% rename from ecc/bw6-761/ecdsa/doc.go rename to ecc/bw6-761/signature/ecdsa/doc.go diff --git a/ecc/bw6-761/ecdsa/ecdsa.go b/ecc/bw6-761/signature/ecdsa/ecdsa.go similarity index 100% rename from ecc/bw6-761/ecdsa/ecdsa.go rename to ecc/bw6-761/signature/ecdsa/ecdsa.go diff --git a/ecc/bw6-761/ecdsa/ecdsa_test.go b/ecc/bw6-761/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bw6-761/ecdsa/ecdsa_test.go rename to ecc/bw6-761/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bw6-761/ecdsa/marshal.go b/ecc/bw6-761/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bw6-761/ecdsa/marshal.go rename to ecc/bw6-761/signature/ecdsa/marshal.go diff --git a/ecc/bw6-761/ecdsa/marshal_test.go b/ecc/bw6-761/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bw6-761/ecdsa/marshal_test.go rename to ecc/bw6-761/signature/ecdsa/marshal_test.go diff --git a/ecc/secp256k1/ecdsa/doc.go b/ecc/secp256k1/signature/ecdsa/doc.go similarity index 100% rename from ecc/secp256k1/ecdsa/doc.go rename to ecc/secp256k1/signature/ecdsa/doc.go diff --git a/ecc/secp256k1/ecdsa/ecdsa.go b/ecc/secp256k1/signature/ecdsa/ecdsa.go similarity index 100% rename from ecc/secp256k1/ecdsa/ecdsa.go rename to ecc/secp256k1/signature/ecdsa/ecdsa.go diff --git a/ecc/secp256k1/ecdsa/ecdsa_test.go b/ecc/secp256k1/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/secp256k1/ecdsa/ecdsa_test.go rename to ecc/secp256k1/signature/ecdsa/ecdsa_test.go diff --git a/ecc/secp256k1/ecdsa/marshal.go b/ecc/secp256k1/signature/ecdsa/marshal.go similarity index 100% rename from ecc/secp256k1/ecdsa/marshal.go rename to ecc/secp256k1/signature/ecdsa/marshal.go diff --git a/ecc/secp256k1/ecdsa/marshal_test.go b/ecc/secp256k1/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/secp256k1/ecdsa/marshal_test.go rename to ecc/secp256k1/signature/ecdsa/marshal_test.go diff --git a/ecc/stark-curve/ecdsa/doc.go b/ecc/stark-curve/signature/ecdsa/doc.go similarity index 100% rename from ecc/stark-curve/ecdsa/doc.go rename to ecc/stark-curve/signature/ecdsa/doc.go diff --git a/ecc/stark-curve/ecdsa/ecdsa.go b/ecc/stark-curve/signature/ecdsa/ecdsa.go similarity index 100% rename from ecc/stark-curve/ecdsa/ecdsa.go rename to ecc/stark-curve/signature/ecdsa/ecdsa.go diff --git a/ecc/stark-curve/ecdsa/ecdsa_test.go b/ecc/stark-curve/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/stark-curve/ecdsa/ecdsa_test.go rename to ecc/stark-curve/signature/ecdsa/ecdsa_test.go diff --git a/ecc/stark-curve/ecdsa/marshal.go b/ecc/stark-curve/signature/ecdsa/marshal.go similarity index 100% rename from ecc/stark-curve/ecdsa/marshal.go rename to ecc/stark-curve/signature/ecdsa/marshal.go diff --git a/ecc/stark-curve/ecdsa/marshal_test.go b/ecc/stark-curve/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/stark-curve/ecdsa/marshal_test.go rename to ecc/stark-curve/signature/ecdsa/marshal_test.go diff --git a/internal/generator/main.go b/internal/generator/main.go index 23f7b8ba6..ba2dd97c1 100644 --- a/internal/generator/main.go +++ b/internal/generator/main.go @@ -13,7 +13,6 @@ import ( "github.com/consensys/gnark-crypto/internal/generator/config" "github.com/consensys/gnark-crypto/internal/generator/crypto/hash/mimc" "github.com/consensys/gnark-crypto/internal/generator/ecc" - "github.com/consensys/gnark-crypto/internal/generator/ecdsa" "github.com/consensys/gnark-crypto/internal/generator/edwards" "github.com/consensys/gnark-crypto/internal/generator/edwards/eddsa" "github.com/consensys/gnark-crypto/internal/generator/fft" @@ -25,6 +24,7 @@ import ( "github.com/consensys/gnark-crypto/internal/generator/permutation" "github.com/consensys/gnark-crypto/internal/generator/plookup" "github.com/consensys/gnark-crypto/internal/generator/polynomial" + "github.com/consensys/gnark-crypto/internal/generator/signature/ecdsa" "github.com/consensys/gnark-crypto/internal/generator/sumcheck" "github.com/consensys/gnark-crypto/internal/generator/test_vector_utils" "github.com/consensys/gnark-crypto/internal/generator/tower" @@ -69,7 +69,7 @@ func main() { } // generate ecdsa - assertNoError(ecdsa.Generate(conf, curveDir, bgen)) + assertNoError(ecdsa.Generate(conf, filepath.Join(curveDir, "signature"), bgen)) if conf.Equal(config.STARK_CURVE) { return // TODO @yelhousni diff --git a/internal/generator/ecdsa/generate.go b/internal/generator/signature/ecdsa/generate.go similarity index 90% rename from internal/generator/ecdsa/generate.go rename to internal/generator/signature/ecdsa/generate.go index 00076625e..98031d558 100644 --- a/internal/generator/ecdsa/generate.go +++ b/internal/generator/signature/ecdsa/generate.go @@ -19,6 +19,6 @@ func Generate(conf config.Curve, baseDir string, bgen *bavard.BatchGenerator) er {File: filepath.Join(baseDir, "marshal.go"), Templates: []string{"marshal.go.tmpl"}}, {File: filepath.Join(baseDir, "marshal_test.go"), Templates: []string{"marshal.test.go.tmpl"}}, } - return bgen.Generate(conf, conf.Package, "./ecdsa/template", entries...) + return bgen.Generate(conf, conf.Package, "./signature/ecdsa/template", entries...) } diff --git a/internal/generator/ecdsa/template/doc.go.tmpl b/internal/generator/signature/ecdsa/template/doc.go.tmpl similarity index 100% rename from internal/generator/ecdsa/template/doc.go.tmpl rename to internal/generator/signature/ecdsa/template/doc.go.tmpl diff --git a/internal/generator/ecdsa/template/ecdsa.go.tmpl b/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl similarity index 100% rename from internal/generator/ecdsa/template/ecdsa.go.tmpl rename to internal/generator/signature/ecdsa/template/ecdsa.go.tmpl diff --git a/internal/generator/ecdsa/template/ecdsa.test.go.tmpl b/internal/generator/signature/ecdsa/template/ecdsa.test.go.tmpl similarity index 100% rename from internal/generator/ecdsa/template/ecdsa.test.go.tmpl rename to internal/generator/signature/ecdsa/template/ecdsa.test.go.tmpl diff --git a/internal/generator/ecdsa/template/marshal.go.tmpl b/internal/generator/signature/ecdsa/template/marshal.go.tmpl similarity index 100% rename from internal/generator/ecdsa/template/marshal.go.tmpl rename to internal/generator/signature/ecdsa/template/marshal.go.tmpl diff --git a/internal/generator/ecdsa/template/marshal.test.go.tmpl b/internal/generator/signature/ecdsa/template/marshal.test.go.tmpl similarity index 100% rename from internal/generator/ecdsa/template/marshal.test.go.tmpl rename to internal/generator/signature/ecdsa/template/marshal.test.go.tmpl From dcecc4c3f21b9418cc291775b9a8e61e67a4e292 Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Wed, 25 Jan 2023 17:11:59 +0100 Subject: [PATCH 02/13] feat: add schnorr signature on all curves --- ecc/bls12-377/signature/schnorr/doc.go | 23 ++ ecc/bls12-377/signature/schnorr/marshal.go | 108 +++++++ .../signature/schnorr/marshal_test.go | 64 ++++ ecc/bls12-377/signature/schnorr/schnorr.go | 278 ++++++++++++++++++ .../signature/schnorr/schnorr_test.go | 78 +++++ ecc/bls12-378/signature/schnorr/doc.go | 23 ++ ecc/bls12-378/signature/schnorr/marshal.go | 108 +++++++ .../signature/schnorr/marshal_test.go | 64 ++++ ecc/bls12-378/signature/schnorr/schnorr.go | 278 ++++++++++++++++++ .../signature/schnorr/schnorr_test.go | 78 +++++ ecc/bls12-381/signature/schnorr/doc.go | 23 ++ ecc/bls12-381/signature/schnorr/marshal.go | 108 +++++++ .../signature/schnorr/marshal_test.go | 64 ++++ ecc/bls12-381/signature/schnorr/schnorr.go | 278 ++++++++++++++++++ .../signature/schnorr/schnorr_test.go | 78 +++++ ecc/bls24-315/signature/schnorr/doc.go | 23 ++ ecc/bls24-315/signature/schnorr/marshal.go | 108 +++++++ .../signature/schnorr/marshal_test.go | 64 ++++ ecc/bls24-315/signature/schnorr/schnorr.go | 278 ++++++++++++++++++ .../signature/schnorr/schnorr_test.go | 78 +++++ ecc/bls24-317/signature/schnorr/doc.go | 23 ++ ecc/bls24-317/signature/schnorr/marshal.go | 108 +++++++ .../signature/schnorr/marshal_test.go | 64 ++++ ecc/bls24-317/signature/schnorr/schnorr.go | 278 ++++++++++++++++++ .../signature/schnorr/schnorr_test.go | 78 +++++ ecc/bn254/signature/schnorr/doc.go | 23 ++ ecc/bn254/signature/schnorr/marshal.go | 108 +++++++ ecc/bn254/signature/schnorr/marshal_test.go | 64 ++++ ecc/bn254/signature/schnorr/schnorr.go | 278 ++++++++++++++++++ ecc/bn254/signature/schnorr/schnorr_test.go | 78 +++++ ecc/bw6-633/signature/schnorr/doc.go | 23 ++ ecc/bw6-633/signature/schnorr/marshal.go | 108 +++++++ ecc/bw6-633/signature/schnorr/marshal_test.go | 64 ++++ ecc/bw6-633/signature/schnorr/schnorr.go | 278 ++++++++++++++++++ ecc/bw6-633/signature/schnorr/schnorr_test.go | 78 +++++ ecc/bw6-756/signature/schnorr/doc.go | 23 ++ ecc/bw6-756/signature/schnorr/marshal.go | 108 +++++++ ecc/bw6-756/signature/schnorr/marshal_test.go | 64 ++++ ecc/bw6-756/signature/schnorr/schnorr.go | 278 ++++++++++++++++++ ecc/bw6-756/signature/schnorr/schnorr_test.go | 78 +++++ ecc/bw6-761/signature/schnorr/doc.go | 23 ++ ecc/bw6-761/signature/schnorr/marshal.go | 108 +++++++ ecc/bw6-761/signature/schnorr/marshal_test.go | 64 ++++ ecc/bw6-761/signature/schnorr/schnorr.go | 278 ++++++++++++++++++ ecc/bw6-761/signature/schnorr/schnorr_test.go | 78 +++++ ecc/secp256k1/signature/schnorr/doc.go | 23 ++ ecc/secp256k1/signature/schnorr/marshal.go | 108 +++++++ .../signature/schnorr/marshal_test.go | 64 ++++ ecc/secp256k1/signature/schnorr/schnorr.go | 278 ++++++++++++++++++ .../signature/schnorr/schnorr_test.go | 78 +++++ ecc/stark-curve/signature/schnorr/doc.go | 23 ++ ecc/stark-curve/signature/schnorr/marshal.go | 108 +++++++ .../signature/schnorr/marshal_test.go | 64 ++++ ecc/stark-curve/signature/schnorr/schnorr.go | 278 ++++++++++++++++++ .../signature/schnorr/schnorr_test.go | 78 +++++ internal/generator/main.go | 6 +- .../generator/signature/schnorr/generate.go | 24 ++ .../signature/schnorr/template/doc.go.tmpl | 8 + .../schnorr/template/marshal.go.tmpl | 98 ++++++ .../schnorr/template/marshal.test.go.tmpl | 46 +++ .../schnorr/template/schnorr.go.tmpl | 269 +++++++++++++++++ .../schnorr/template/schnorr.test.go.tmpl | 60 ++++ signature/ecdsa/ecdsa.go | 22 +- signature/schnorr/schnorr.go | 65 ++++ 64 files changed, 6647 insertions(+), 12 deletions(-) create mode 100644 ecc/bls12-377/signature/schnorr/doc.go create mode 100644 ecc/bls12-377/signature/schnorr/marshal.go create mode 100644 ecc/bls12-377/signature/schnorr/marshal_test.go create mode 100644 ecc/bls12-377/signature/schnorr/schnorr.go create mode 100644 ecc/bls12-377/signature/schnorr/schnorr_test.go create mode 100644 ecc/bls12-378/signature/schnorr/doc.go create mode 100644 ecc/bls12-378/signature/schnorr/marshal.go create mode 100644 ecc/bls12-378/signature/schnorr/marshal_test.go create mode 100644 ecc/bls12-378/signature/schnorr/schnorr.go create mode 100644 ecc/bls12-378/signature/schnorr/schnorr_test.go create mode 100644 ecc/bls12-381/signature/schnorr/doc.go create mode 100644 ecc/bls12-381/signature/schnorr/marshal.go create mode 100644 ecc/bls12-381/signature/schnorr/marshal_test.go create mode 100644 ecc/bls12-381/signature/schnorr/schnorr.go create mode 100644 ecc/bls12-381/signature/schnorr/schnorr_test.go create mode 100644 ecc/bls24-315/signature/schnorr/doc.go create mode 100644 ecc/bls24-315/signature/schnorr/marshal.go create mode 100644 ecc/bls24-315/signature/schnorr/marshal_test.go create mode 100644 ecc/bls24-315/signature/schnorr/schnorr.go create mode 100644 ecc/bls24-315/signature/schnorr/schnorr_test.go create mode 100644 ecc/bls24-317/signature/schnorr/doc.go create mode 100644 ecc/bls24-317/signature/schnorr/marshal.go create mode 100644 ecc/bls24-317/signature/schnorr/marshal_test.go create mode 100644 ecc/bls24-317/signature/schnorr/schnorr.go create mode 100644 ecc/bls24-317/signature/schnorr/schnorr_test.go create mode 100644 ecc/bn254/signature/schnorr/doc.go create mode 100644 ecc/bn254/signature/schnorr/marshal.go create mode 100644 ecc/bn254/signature/schnorr/marshal_test.go create mode 100644 ecc/bn254/signature/schnorr/schnorr.go create mode 100644 ecc/bn254/signature/schnorr/schnorr_test.go create mode 100644 ecc/bw6-633/signature/schnorr/doc.go create mode 100644 ecc/bw6-633/signature/schnorr/marshal.go create mode 100644 ecc/bw6-633/signature/schnorr/marshal_test.go create mode 100644 ecc/bw6-633/signature/schnorr/schnorr.go create mode 100644 ecc/bw6-633/signature/schnorr/schnorr_test.go create mode 100644 ecc/bw6-756/signature/schnorr/doc.go create mode 100644 ecc/bw6-756/signature/schnorr/marshal.go create mode 100644 ecc/bw6-756/signature/schnorr/marshal_test.go create mode 100644 ecc/bw6-756/signature/schnorr/schnorr.go create mode 100644 ecc/bw6-756/signature/schnorr/schnorr_test.go create mode 100644 ecc/bw6-761/signature/schnorr/doc.go create mode 100644 ecc/bw6-761/signature/schnorr/marshal.go create mode 100644 ecc/bw6-761/signature/schnorr/marshal_test.go create mode 100644 ecc/bw6-761/signature/schnorr/schnorr.go create mode 100644 ecc/bw6-761/signature/schnorr/schnorr_test.go create mode 100644 ecc/secp256k1/signature/schnorr/doc.go create mode 100644 ecc/secp256k1/signature/schnorr/marshal.go create mode 100644 ecc/secp256k1/signature/schnorr/marshal_test.go create mode 100644 ecc/secp256k1/signature/schnorr/schnorr.go create mode 100644 ecc/secp256k1/signature/schnorr/schnorr_test.go create mode 100644 ecc/stark-curve/signature/schnorr/doc.go create mode 100644 ecc/stark-curve/signature/schnorr/marshal.go create mode 100644 ecc/stark-curve/signature/schnorr/marshal_test.go create mode 100644 ecc/stark-curve/signature/schnorr/schnorr.go create mode 100644 ecc/stark-curve/signature/schnorr/schnorr_test.go create mode 100644 internal/generator/signature/schnorr/generate.go create mode 100644 internal/generator/signature/schnorr/template/doc.go.tmpl create mode 100644 internal/generator/signature/schnorr/template/marshal.go.tmpl create mode 100644 internal/generator/signature/schnorr/template/marshal.test.go.tmpl create mode 100644 internal/generator/signature/schnorr/template/schnorr.go.tmpl create mode 100644 internal/generator/signature/schnorr/template/schnorr.test.go.tmpl create mode 100644 signature/schnorr/schnorr.go diff --git a/ecc/bls12-377/signature/schnorr/doc.go b/ecc/bls12-377/signature/schnorr/doc.go new file mode 100644 index 000000000..5d1c86957 --- /dev/null +++ b/ecc/bls12-377/signature/schnorr/doc.go @@ -0,0 +1,23 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package schnorr provides Schnorr signature scheme on the bls12-377 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +package schnorr diff --git a/ecc/bls12-377/signature/schnorr/marshal.go b/ecc/bls12-377/signature/schnorr/marshal.go new file mode 100644 index 000000000..2b92ad686 --- /dev/null +++ b/ecc/bls12-377/signature/schnorr/marshal.go @@ -0,0 +1,108 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/ecc/bls12-377/signature/schnorr/marshal_test.go b/ecc/bls12-377/signature/schnorr/marshal_test.go new file mode 100644 index 000000000..5bd24a7e5 --- /dev/null +++ b/ecc/bls12-377/signature/schnorr/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-377] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bls12-377/signature/schnorr/schnorr.go b/ecc/bls12-377/signature/schnorr/schnorr.go new file mode 100644 index 000000000..70a485c22 --- /dev/null +++ b/ecc/bls12-377/signature/schnorr/schnorr.go @@ -0,0 +1,278 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-377" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A bls12377.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bls12377.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P bls12377.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P bls12377.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P bls12377.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/ecc/bls12-377/signature/schnorr/schnorr_test.go b/ecc/bls12-377/signature/schnorr/schnorr_test.go new file mode 100644 index 000000000..68b7c8c57 --- /dev/null +++ b/ecc/bls12-377/signature/schnorr/schnorr_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-377] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/ecc/bls12-378/signature/schnorr/doc.go b/ecc/bls12-378/signature/schnorr/doc.go new file mode 100644 index 000000000..6d056ac70 --- /dev/null +++ b/ecc/bls12-378/signature/schnorr/doc.go @@ -0,0 +1,23 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package schnorr provides Schnorr signature scheme on the bls12-378 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +package schnorr diff --git a/ecc/bls12-378/signature/schnorr/marshal.go b/ecc/bls12-378/signature/schnorr/marshal.go new file mode 100644 index 000000000..2b92ad686 --- /dev/null +++ b/ecc/bls12-378/signature/schnorr/marshal.go @@ -0,0 +1,108 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/ecc/bls12-378/signature/schnorr/marshal_test.go b/ecc/bls12-378/signature/schnorr/marshal_test.go new file mode 100644 index 000000000..3c81b214c --- /dev/null +++ b/ecc/bls12-378/signature/schnorr/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-378] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bls12-378/signature/schnorr/schnorr.go b/ecc/bls12-378/signature/schnorr/schnorr.go new file mode 100644 index 000000000..e7277a5ef --- /dev/null +++ b/ecc/bls12-378/signature/schnorr/schnorr.go @@ -0,0 +1,278 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-378" + "github.com/consensys/gnark-crypto/ecc/bls12-378/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-378/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A bls12378.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bls12378.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P bls12378.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P bls12378.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P bls12378.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/ecc/bls12-378/signature/schnorr/schnorr_test.go b/ecc/bls12-378/signature/schnorr/schnorr_test.go new file mode 100644 index 000000000..69d54ce8f --- /dev/null +++ b/ecc/bls12-378/signature/schnorr/schnorr_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-378] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/ecc/bls12-381/signature/schnorr/doc.go b/ecc/bls12-381/signature/schnorr/doc.go new file mode 100644 index 000000000..dcf3bb586 --- /dev/null +++ b/ecc/bls12-381/signature/schnorr/doc.go @@ -0,0 +1,23 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package schnorr provides Schnorr signature scheme on the bls12-381 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +package schnorr diff --git a/ecc/bls12-381/signature/schnorr/marshal.go b/ecc/bls12-381/signature/schnorr/marshal.go new file mode 100644 index 000000000..2b92ad686 --- /dev/null +++ b/ecc/bls12-381/signature/schnorr/marshal.go @@ -0,0 +1,108 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/ecc/bls12-381/signature/schnorr/marshal_test.go b/ecc/bls12-381/signature/schnorr/marshal_test.go new file mode 100644 index 000000000..df30517a8 --- /dev/null +++ b/ecc/bls12-381/signature/schnorr/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-381] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bls12-381/signature/schnorr/schnorr.go b/ecc/bls12-381/signature/schnorr/schnorr.go new file mode 100644 index 000000000..60ebbdfd1 --- /dev/null +++ b/ecc/bls12-381/signature/schnorr/schnorr.go @@ -0,0 +1,278 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A bls12381.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bls12381.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P bls12381.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P bls12381.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P bls12381.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/ecc/bls12-381/signature/schnorr/schnorr_test.go b/ecc/bls12-381/signature/schnorr/schnorr_test.go new file mode 100644 index 000000000..ca692100c --- /dev/null +++ b/ecc/bls12-381/signature/schnorr/schnorr_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-381] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/ecc/bls24-315/signature/schnorr/doc.go b/ecc/bls24-315/signature/schnorr/doc.go new file mode 100644 index 000000000..ff4bf0324 --- /dev/null +++ b/ecc/bls24-315/signature/schnorr/doc.go @@ -0,0 +1,23 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package schnorr provides Schnorr signature scheme on the bls24-315 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +package schnorr diff --git a/ecc/bls24-315/signature/schnorr/marshal.go b/ecc/bls24-315/signature/schnorr/marshal.go new file mode 100644 index 000000000..2b92ad686 --- /dev/null +++ b/ecc/bls24-315/signature/schnorr/marshal.go @@ -0,0 +1,108 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/ecc/bls24-315/signature/schnorr/marshal_test.go b/ecc/bls24-315/signature/schnorr/marshal_test.go new file mode 100644 index 000000000..43bcbeb6b --- /dev/null +++ b/ecc/bls24-315/signature/schnorr/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS24-315] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bls24-315/signature/schnorr/schnorr.go b/ecc/bls24-315/signature/schnorr/schnorr.go new file mode 100644 index 000000000..7ebbc88e4 --- /dev/null +++ b/ecc/bls24-315/signature/schnorr/schnorr.go @@ -0,0 +1,278 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls24-315" + "github.com/consensys/gnark-crypto/ecc/bls24-315/fp" + "github.com/consensys/gnark-crypto/ecc/bls24-315/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A bls24315.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bls24315.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P bls24315.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P bls24315.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P bls24315.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/ecc/bls24-315/signature/schnorr/schnorr_test.go b/ecc/bls24-315/signature/schnorr/schnorr_test.go new file mode 100644 index 000000000..a36590b40 --- /dev/null +++ b/ecc/bls24-315/signature/schnorr/schnorr_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS24-315] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/ecc/bls24-317/signature/schnorr/doc.go b/ecc/bls24-317/signature/schnorr/doc.go new file mode 100644 index 000000000..12245de88 --- /dev/null +++ b/ecc/bls24-317/signature/schnorr/doc.go @@ -0,0 +1,23 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package schnorr provides Schnorr signature scheme on the bls24-317 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +package schnorr diff --git a/ecc/bls24-317/signature/schnorr/marshal.go b/ecc/bls24-317/signature/schnorr/marshal.go new file mode 100644 index 000000000..2b92ad686 --- /dev/null +++ b/ecc/bls24-317/signature/schnorr/marshal.go @@ -0,0 +1,108 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/ecc/bls24-317/signature/schnorr/marshal_test.go b/ecc/bls24-317/signature/schnorr/marshal_test.go new file mode 100644 index 000000000..cf16dbb36 --- /dev/null +++ b/ecc/bls24-317/signature/schnorr/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS24-317] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bls24-317/signature/schnorr/schnorr.go b/ecc/bls24-317/signature/schnorr/schnorr.go new file mode 100644 index 000000000..76f5bd465 --- /dev/null +++ b/ecc/bls24-317/signature/schnorr/schnorr.go @@ -0,0 +1,278 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls24-317" + "github.com/consensys/gnark-crypto/ecc/bls24-317/fp" + "github.com/consensys/gnark-crypto/ecc/bls24-317/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A bls24317.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bls24317.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P bls24317.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P bls24317.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P bls24317.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/ecc/bls24-317/signature/schnorr/schnorr_test.go b/ecc/bls24-317/signature/schnorr/schnorr_test.go new file mode 100644 index 000000000..49ec67942 --- /dev/null +++ b/ecc/bls24-317/signature/schnorr/schnorr_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS24-317] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/ecc/bn254/signature/schnorr/doc.go b/ecc/bn254/signature/schnorr/doc.go new file mode 100644 index 000000000..630879533 --- /dev/null +++ b/ecc/bn254/signature/schnorr/doc.go @@ -0,0 +1,23 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package schnorr provides Schnorr signature scheme on the bn254 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +package schnorr diff --git a/ecc/bn254/signature/schnorr/marshal.go b/ecc/bn254/signature/schnorr/marshal.go new file mode 100644 index 000000000..2b92ad686 --- /dev/null +++ b/ecc/bn254/signature/schnorr/marshal.go @@ -0,0 +1,108 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/ecc/bn254/signature/schnorr/marshal_test.go b/ecc/bn254/signature/schnorr/marshal_test.go new file mode 100644 index 000000000..169c1697c --- /dev/null +++ b/ecc/bn254/signature/schnorr/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BN254] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bn254/signature/schnorr/schnorr.go b/ecc/bn254/signature/schnorr/schnorr.go new file mode 100644 index 000000000..e16e62e7e --- /dev/null +++ b/ecc/bn254/signature/schnorr/schnorr.go @@ -0,0 +1,278 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A bn254.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bn254.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P bn254.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P bn254.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P bn254.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/ecc/bn254/signature/schnorr/schnorr_test.go b/ecc/bn254/signature/schnorr/schnorr_test.go new file mode 100644 index 000000000..9e8496fc0 --- /dev/null +++ b/ecc/bn254/signature/schnorr/schnorr_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BN254] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/ecc/bw6-633/signature/schnorr/doc.go b/ecc/bw6-633/signature/schnorr/doc.go new file mode 100644 index 000000000..8688835c3 --- /dev/null +++ b/ecc/bw6-633/signature/schnorr/doc.go @@ -0,0 +1,23 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package schnorr provides Schnorr signature scheme on the bw6-633 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +package schnorr diff --git a/ecc/bw6-633/signature/schnorr/marshal.go b/ecc/bw6-633/signature/schnorr/marshal.go new file mode 100644 index 000000000..2b92ad686 --- /dev/null +++ b/ecc/bw6-633/signature/schnorr/marshal.go @@ -0,0 +1,108 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/ecc/bw6-633/signature/schnorr/marshal_test.go b/ecc/bw6-633/signature/schnorr/marshal_test.go new file mode 100644 index 000000000..3314c79ec --- /dev/null +++ b/ecc/bw6-633/signature/schnorr/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-633] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bw6-633/signature/schnorr/schnorr.go b/ecc/bw6-633/signature/schnorr/schnorr.go new file mode 100644 index 000000000..3ca930229 --- /dev/null +++ b/ecc/bw6-633/signature/schnorr/schnorr.go @@ -0,0 +1,278 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bw6-633" + "github.com/consensys/gnark-crypto/ecc/bw6-633/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-633/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A bw6633.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bw6633.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P bw6633.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P bw6633.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P bw6633.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/ecc/bw6-633/signature/schnorr/schnorr_test.go b/ecc/bw6-633/signature/schnorr/schnorr_test.go new file mode 100644 index 000000000..ae4fd01ee --- /dev/null +++ b/ecc/bw6-633/signature/schnorr/schnorr_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-633] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/ecc/bw6-756/signature/schnorr/doc.go b/ecc/bw6-756/signature/schnorr/doc.go new file mode 100644 index 000000000..ef808bee8 --- /dev/null +++ b/ecc/bw6-756/signature/schnorr/doc.go @@ -0,0 +1,23 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package schnorr provides Schnorr signature scheme on the bw6-756 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +package schnorr diff --git a/ecc/bw6-756/signature/schnorr/marshal.go b/ecc/bw6-756/signature/schnorr/marshal.go new file mode 100644 index 000000000..2b92ad686 --- /dev/null +++ b/ecc/bw6-756/signature/schnorr/marshal.go @@ -0,0 +1,108 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/ecc/bw6-756/signature/schnorr/marshal_test.go b/ecc/bw6-756/signature/schnorr/marshal_test.go new file mode 100644 index 000000000..8b65b5c99 --- /dev/null +++ b/ecc/bw6-756/signature/schnorr/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-756] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bw6-756/signature/schnorr/schnorr.go b/ecc/bw6-756/signature/schnorr/schnorr.go new file mode 100644 index 000000000..de465a5f6 --- /dev/null +++ b/ecc/bw6-756/signature/schnorr/schnorr.go @@ -0,0 +1,278 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bw6-756" + "github.com/consensys/gnark-crypto/ecc/bw6-756/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-756/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A bw6756.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bw6756.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P bw6756.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P bw6756.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P bw6756.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/ecc/bw6-756/signature/schnorr/schnorr_test.go b/ecc/bw6-756/signature/schnorr/schnorr_test.go new file mode 100644 index 000000000..becbf1070 --- /dev/null +++ b/ecc/bw6-756/signature/schnorr/schnorr_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-756] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/ecc/bw6-761/signature/schnorr/doc.go b/ecc/bw6-761/signature/schnorr/doc.go new file mode 100644 index 000000000..205afb4a8 --- /dev/null +++ b/ecc/bw6-761/signature/schnorr/doc.go @@ -0,0 +1,23 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package schnorr provides Schnorr signature scheme on the bw6-761 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +package schnorr diff --git a/ecc/bw6-761/signature/schnorr/marshal.go b/ecc/bw6-761/signature/schnorr/marshal.go new file mode 100644 index 000000000..2b92ad686 --- /dev/null +++ b/ecc/bw6-761/signature/schnorr/marshal.go @@ -0,0 +1,108 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/ecc/bw6-761/signature/schnorr/marshal_test.go b/ecc/bw6-761/signature/schnorr/marshal_test.go new file mode 100644 index 000000000..d53171fce --- /dev/null +++ b/ecc/bw6-761/signature/schnorr/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-761] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bw6-761/signature/schnorr/schnorr.go b/ecc/bw6-761/signature/schnorr/schnorr.go new file mode 100644 index 000000000..13ded779e --- /dev/null +++ b/ecc/bw6-761/signature/schnorr/schnorr.go @@ -0,0 +1,278 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bw6-761" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A bw6761.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bw6761.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P bw6761.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P bw6761.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P bw6761.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/ecc/bw6-761/signature/schnorr/schnorr_test.go b/ecc/bw6-761/signature/schnorr/schnorr_test.go new file mode 100644 index 000000000..f4ab6ce56 --- /dev/null +++ b/ecc/bw6-761/signature/schnorr/schnorr_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-761] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/ecc/secp256k1/signature/schnorr/doc.go b/ecc/secp256k1/signature/schnorr/doc.go new file mode 100644 index 000000000..dde769425 --- /dev/null +++ b/ecc/secp256k1/signature/schnorr/doc.go @@ -0,0 +1,23 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package schnorr provides Schnorr signature scheme on the secp256k1 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +package schnorr diff --git a/ecc/secp256k1/signature/schnorr/marshal.go b/ecc/secp256k1/signature/schnorr/marshal.go new file mode 100644 index 000000000..a010a563b --- /dev/null +++ b/ecc/secp256k1/signature/schnorr/marshal.go @@ -0,0 +1,108 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.RawBytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.RawBytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/ecc/secp256k1/signature/schnorr/marshal_test.go b/ecc/secp256k1/signature/schnorr/marshal_test.go new file mode 100644 index 000000000..c06385c57 --- /dev/null +++ b/ecc/secp256k1/signature/schnorr/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[SECP256K1] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/secp256k1/signature/schnorr/schnorr.go b/ecc/secp256k1/signature/schnorr/schnorr.go new file mode 100644 index 000000000..c0372a5c7 --- /dev/null +++ b/ecc/secp256k1/signature/schnorr/schnorr.go @@ -0,0 +1,278 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/secp256k1" + "github.com/consensys/gnark-crypto/ecc/secp256k1/fp" + "github.com/consensys/gnark-crypto/ecc/secp256k1/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = 2 * sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A secp256k1.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, g := secp256k1.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P secp256k1.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P secp256k1.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P secp256k1.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/ecc/secp256k1/signature/schnorr/schnorr_test.go b/ecc/secp256k1/signature/schnorr/schnorr_test.go new file mode 100644 index 000000000..8af13bee5 --- /dev/null +++ b/ecc/secp256k1/signature/schnorr/schnorr_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[SECP256K1] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/ecc/stark-curve/signature/schnorr/doc.go b/ecc/stark-curve/signature/schnorr/doc.go new file mode 100644 index 000000000..a815596e4 --- /dev/null +++ b/ecc/stark-curve/signature/schnorr/doc.go @@ -0,0 +1,23 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package schnorr provides Schnorr signature scheme on the stark-curve curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +package schnorr diff --git a/ecc/stark-curve/signature/schnorr/marshal.go b/ecc/stark-curve/signature/schnorr/marshal.go new file mode 100644 index 000000000..2b92ad686 --- /dev/null +++ b/ecc/stark-curve/signature/schnorr/marshal.go @@ -0,0 +1,108 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/ecc/stark-curve/signature/schnorr/marshal_test.go b/ecc/stark-curve/signature/schnorr/marshal_test.go new file mode 100644 index 000000000..10e961c05 --- /dev/null +++ b/ecc/stark-curve/signature/schnorr/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[STARK-CURVE] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/stark-curve/signature/schnorr/schnorr.go b/ecc/stark-curve/signature/schnorr/schnorr.go new file mode 100644 index 000000000..55e4f6141 --- /dev/null +++ b/ecc/stark-curve/signature/schnorr/schnorr.go @@ -0,0 +1,278 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/stark-curve" + "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" + "github.com/consensys/gnark-crypto/ecc/stark-curve/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A starkcurve.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, g := starkcurve.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P starkcurve.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P starkcurve.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P starkcurve.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/ecc/stark-curve/signature/schnorr/schnorr_test.go b/ecc/stark-curve/signature/schnorr/schnorr_test.go new file mode 100644 index 000000000..2b8ccdb3a --- /dev/null +++ b/ecc/stark-curve/signature/schnorr/schnorr_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package schnorr + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[STARK-CURVE] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/internal/generator/main.go b/internal/generator/main.go index ba2dd97c1..c45fd536b 100644 --- a/internal/generator/main.go +++ b/internal/generator/main.go @@ -25,6 +25,7 @@ import ( "github.com/consensys/gnark-crypto/internal/generator/plookup" "github.com/consensys/gnark-crypto/internal/generator/polynomial" "github.com/consensys/gnark-crypto/internal/generator/signature/ecdsa" + "github.com/consensys/gnark-crypto/internal/generator/signature/schnorr" "github.com/consensys/gnark-crypto/internal/generator/sumcheck" "github.com/consensys/gnark-crypto/internal/generator/test_vector_utils" "github.com/consensys/gnark-crypto/internal/generator/tower" @@ -68,9 +69,12 @@ func main() { ElementType: "fr.Element", } - // generate ecdsa + // generate ecdsa signature assertNoError(ecdsa.Generate(conf, filepath.Join(curveDir, "signature"), bgen)) + // generate schnorr signature + assertNoError(schnorr.Generate(conf, filepath.Join(curveDir, "signature"), bgen)) + if conf.Equal(config.STARK_CURVE) { return // TODO @yelhousni } diff --git a/internal/generator/signature/schnorr/generate.go b/internal/generator/signature/schnorr/generate.go new file mode 100644 index 000000000..918b379eb --- /dev/null +++ b/internal/generator/signature/schnorr/generate.go @@ -0,0 +1,24 @@ +package schnorr + +import ( + "path/filepath" + + "github.com/consensys/bavard" + "github.com/consensys/gnark-crypto/internal/generator/config" +) + +func Generate(conf config.Curve, baseDir string, bgen *bavard.BatchGenerator) error { + // schnorr + conf.Package = "schnorr" + baseDir = filepath.Join(baseDir, conf.Package) + + entries := []bavard.Entry{ + {File: filepath.Join(baseDir, "doc.go"), Templates: []string{"doc.go.tmpl"}}, + {File: filepath.Join(baseDir, "schnorr.go"), Templates: []string{"schnorr.go.tmpl"}}, + {File: filepath.Join(baseDir, "schnorr_test.go"), Templates: []string{"schnorr.test.go.tmpl"}}, + {File: filepath.Join(baseDir, "marshal.go"), Templates: []string{"marshal.go.tmpl"}}, + {File: filepath.Join(baseDir, "marshal_test.go"), Templates: []string{"marshal.test.go.tmpl"}}, + } + return bgen.Generate(conf, conf.Package, "./signature/schnorr/template", entries...) + +} diff --git a/internal/generator/signature/schnorr/template/doc.go.tmpl b/internal/generator/signature/schnorr/template/doc.go.tmpl new file mode 100644 index 000000000..536926c48 --- /dev/null +++ b/internal/generator/signature/schnorr/template/doc.go.tmpl @@ -0,0 +1,8 @@ +// Package {{.Package}} provides Schnorr signature scheme on the {{.Name}} curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/Schnorr_signature +// - RFC8235: https://www.rfc-editor.org/rfc/rfc8235 +// - BIP-340: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +// +package {{.Package}} diff --git a/internal/generator/signature/schnorr/template/marshal.go.tmpl b/internal/generator/signature/schnorr/template/marshal.go.tmpl new file mode 100644 index 000000000..2e76fe21e --- /dev/null +++ b/internal/generator/signature/schnorr/template/marshal.go.tmpl @@ -0,0 +1,98 @@ +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte +{{- if eq .Name "secp256k1"}} + pkBin := pk.A.RawBytes() +{{- else}} + pkBin := pk.A.Bytes() +{{- end}} + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte +{{- if eq .Name "secp256k1"}} + pubkBin := privKey.PublicKey.A.RawBytes() +{{- else}} + pubkBin := privKey.PublicKey.A.Bytes() +{{- end}} + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFr r||s +func (sig *Signature) Bytes() []byte { + var res [sizeSignature]byte + subtle.ConstantTimeCopy(1, res[:sizeFr], sig.R[:]) + subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:]) + return res[:] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + subtle.ConstantTimeCopy(1, sig.R[:], buf[:sizeFr]) + n += sizeFr + subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr]) + n += sizeFr + return n, nil +} diff --git a/internal/generator/signature/schnorr/template/marshal.test.go.tmpl b/internal/generator/signature/schnorr/template/marshal.test.go.tmpl new file mode 100644 index 000000000..5fc66a474 --- /dev/null +++ b/internal/generator/signature/schnorr/template/marshal.test.go.tmpl @@ -0,0 +1,46 @@ +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[{{ toUpper .Name }}] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/internal/generator/signature/schnorr/template/schnorr.go.tmpl b/internal/generator/signature/schnorr/template/schnorr.go.tmpl new file mode 100644 index 000000000..7f1056da6 --- /dev/null +++ b/internal/generator/signature/schnorr/template/schnorr.go.tmpl @@ -0,0 +1,269 @@ +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/{{ .Name }}" + "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr" + "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fp" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes +{{- if eq .Name "secp256k1"}} + sizePublicKey = 2 * sizeFp +{{- else}} + sizePublicKey = sizeFp +{{- end}} + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFr +) + +var order = fr.Modulus() + +// PublicKey represents an Schnorr public key +type PublicKey struct { + A {{ .CurvePackage }}.G1Affine +} + +// PrivateKey represents an Schnorr private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an Schnorr signature +type Signature struct { + R, S [sizeFr]byte +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + + {{- if or (eq .Name "secp256k1") (eq .Name "stark-curve")}} + _, g := {{ .CurvePackage }}.Generators() + {{- else}} + _, _, g, _ := {{ .CurvePackage }}.Generators() + {{- end}} + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the Schnorr signature +// +// k ← 𝔽r (random) +// P = k ⋅ g1Gen +// r = H ( P || m ) +// s = k - x ⋅ r +// signature = {r, s} +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + csprng, err := nonce(privKey, message) + if err != nil { + return nil, err + } + k, err := randFieldElement(csprng) + if err != nil { + return nil, err + } + + var P {{ .CurvePackage }}.G1Affine + P.ScalarMultiplicationBase(k) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + + s.Mul(scalar, r) + s.Sub(k, s). + Mod(s, order) + + var sig Signature + r.FillBytes(sig.R[:sizeFr]) + s.FillBytes(sig.S[:sizeFr]) + + return sig.Bytes(), nil +} + +// Verify validates the Schnorr signature +// +// R = s ⋅ Base + r ⋅ publiKey +// H ( R || m ) ?= r +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + + r, s, e := new(big.Int), new(big.Int), new(big.Int) + r.SetBytes(sig.R[:sizeFr]) + s.SetBytes(sig.S[:sizeFr]) + + var P {{ .CurvePackage }}.G1Jac + P.JointScalarMultiplicationBase(&publicKey.A, s, r) + var _P {{ .CurvePackage }}.G1Affine + _P.FromJacobian(&P) + + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + + return e.Cmp(r) == 0, nil + +} diff --git a/internal/generator/signature/schnorr/template/schnorr.test.go.tmpl b/internal/generator/signature/schnorr/template/schnorr.test.go.tmpl new file mode 100644 index 000000000..de6ac9a4a --- /dev/null +++ b/internal/generator/signature/schnorr/template/schnorr.test.go.tmpl @@ -0,0 +1,60 @@ +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestSchnorr(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[{{ toUpper .Name }}] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + flag, _ := publicKey.Verify(sig, msg, hFunc) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignSchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, hFunc) + } +} + +func BenchmarkVerifySchnorr(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, hFunc) + } +} diff --git a/signature/ecdsa/ecdsa.go b/signature/ecdsa/ecdsa.go index 68daac09d..ffe16b590 100644 --- a/signature/ecdsa/ecdsa.go +++ b/signature/ecdsa/ecdsa.go @@ -20,17 +20,17 @@ import ( "io" "github.com/consensys/gnark-crypto/ecc" - ecdsa_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/ecdsa" - ecdsa_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/ecdsa" - ecdsa_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/ecdsa" - ecdsa_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/ecdsa" - ecdsa_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/ecdsa" - ecdsa_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/ecdsa" - ecdsa_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/ecdsa" - ecdsa_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/ecdsa" - ecdsa_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/ecdsa" - ecdsa_secp256k1 "github.com/consensys/gnark-crypto/ecc/secp256k1/ecdsa" - ecdsa_starkcurve "github.com/consensys/gnark-crypto/ecc/stark-curve/ecdsa" + ecdsa_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signature/ecdsa" + ecdsa_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signature/ecdsa" + ecdsa_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signature/ecdsa" + ecdsa_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signature/ecdsa" + ecdsa_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signature/ecdsa" + ecdsa_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signature/ecdsa" + ecdsa_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signature/ecdsa" + ecdsa_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signature/ecdsa" + ecdsa_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signature/ecdsa" + ecdsa_secp256k1 "github.com/consensys/gnark-crypto/ecc/secp256k1/signature/ecdsa" + ecdsa_starkcurve "github.com/consensys/gnark-crypto/ecc/stark-curve/signature/ecdsa" "github.com/consensys/gnark-crypto/signature" ) diff --git a/signature/schnorr/schnorr.go b/signature/schnorr/schnorr.go new file mode 100644 index 000000000..9c432cd4b --- /dev/null +++ b/signature/schnorr/schnorr.go @@ -0,0 +1,65 @@ +/* +Copyright © 2020 ConsenSys + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schnorr + +import ( + "io" + + "github.com/consensys/gnark-crypto/ecc" + schnorr_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signature/schnorr" + schnorr_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signature/schnorr" + schnorr_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signature/schnorr" + schnorr_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signature/schnorr" + schnorr_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signature/schnorr" + schnorr_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signature/schnorr" + schnorr_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signature/schnorr" + schnorr_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signature/schnorr" + schnorr_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signature/schnorr" + schnorr_secp256k1 "github.com/consensys/gnark-crypto/ecc/secp256k1/signature/schnorr" + schnorr_starkcurve "github.com/consensys/gnark-crypto/ecc/stark-curve/signature/schnorr" + "github.com/consensys/gnark-crypto/signature" +) + +// New takes a source of randomness and returns a new key pair +func New(ss ecc.ID, r io.Reader) (signature.Signer, error) { + switch ss { + case ecc.BN254: + return schnorr_bn254.GenerateKey(r) + case ecc.BLS12_381: + return schnorr_bls12381.GenerateKey(r) + case ecc.BLS12_377: + return schnorr_bls12377.GenerateKey(r) + case ecc.BLS12_378: + return schnorr_bls12378.GenerateKey(r) + case ecc.BW6_761: + return schnorr_bw6761.GenerateKey(r) + case ecc.BW6_756: + return schnorr_bw6756.GenerateKey(r) + case ecc.BLS24_315: + return schnorr_bls24315.GenerateKey(r) + case ecc.BLS24_317: + return schnorr_bls24317.GenerateKey(r) + case ecc.BW6_633: + return schnorr_bw6633.GenerateKey(r) + case ecc.SECP256K1: + return schnorr_secp256k1.GenerateKey(r) + case ecc.STARK_CURVE: + return schnorr_starkcurve.GenerateKey(r) + default: + panic("not implemented") + } +} From 5bd17bce2b841717d2a31bc45e322c157074501e Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Wed, 25 Jan 2023 17:20:39 +0100 Subject: [PATCH 03/13] test: schnorr with pre-hashed message --- ecc/bls12-377/signature/schnorr/schnorr.go | 68 ++++++++++-------- ecc/bls12-378/signature/schnorr/schnorr.go | 68 ++++++++++-------- ecc/bls12-381/signature/schnorr/schnorr.go | 68 ++++++++++-------- ecc/bls24-315/signature/schnorr/schnorr.go | 68 ++++++++++-------- ecc/bls24-317/signature/schnorr/schnorr.go | 68 ++++++++++-------- ecc/bn254/signature/schnorr/schnorr.go | 68 ++++++++++-------- ecc/bw6-633/signature/schnorr/schnorr.go | 68 ++++++++++-------- ecc/bw6-756/signature/schnorr/schnorr.go | 68 ++++++++++-------- ecc/bw6-761/signature/schnorr/schnorr.go | 68 ++++++++++-------- ecc/secp256k1/signature/schnorr/schnorr.go | 68 ++++++++++-------- ecc/stark-curve/signature/schnorr/schnorr.go | 68 ++++++++++-------- .../schnorr/template/schnorr.go.tmpl | 72 ++++++++++--------- 12 files changed, 458 insertions(+), 362 deletions(-) diff --git a/ecc/bls12-377/signature/schnorr/schnorr.go b/ecc/bls12-377/signature/schnorr/schnorr.go index 70a485c22..328b33516 100644 --- a/ecc/bls12-377/signature/schnorr/schnorr.go +++ b/ecc/bls12-377/signature/schnorr/schnorr.go @@ -207,23 +207,27 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bls12377.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) } - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -256,23 +260,27 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bls12377.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) } - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - return e.Cmp(r) == 0, nil } diff --git a/ecc/bls12-378/signature/schnorr/schnorr.go b/ecc/bls12-378/signature/schnorr/schnorr.go index e7277a5ef..344c3f6f3 100644 --- a/ecc/bls12-378/signature/schnorr/schnorr.go +++ b/ecc/bls12-378/signature/schnorr/schnorr.go @@ -207,23 +207,27 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bls12378.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) } - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -256,23 +260,27 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bls12378.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) } - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - return e.Cmp(r) == 0, nil } diff --git a/ecc/bls12-381/signature/schnorr/schnorr.go b/ecc/bls12-381/signature/schnorr/schnorr.go index 60ebbdfd1..f1d16026f 100644 --- a/ecc/bls12-381/signature/schnorr/schnorr.go +++ b/ecc/bls12-381/signature/schnorr/schnorr.go @@ -207,23 +207,27 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bls12381.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) } - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -256,23 +260,27 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bls12381.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) } - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - return e.Cmp(r) == 0, nil } diff --git a/ecc/bls24-315/signature/schnorr/schnorr.go b/ecc/bls24-315/signature/schnorr/schnorr.go index 7ebbc88e4..83cb61540 100644 --- a/ecc/bls24-315/signature/schnorr/schnorr.go +++ b/ecc/bls24-315/signature/schnorr/schnorr.go @@ -207,23 +207,27 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bls24315.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) } - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -256,23 +260,27 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bls24315.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) } - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - return e.Cmp(r) == 0, nil } diff --git a/ecc/bls24-317/signature/schnorr/schnorr.go b/ecc/bls24-317/signature/schnorr/schnorr.go index 76f5bd465..b45b7d147 100644 --- a/ecc/bls24-317/signature/schnorr/schnorr.go +++ b/ecc/bls24-317/signature/schnorr/schnorr.go @@ -207,23 +207,27 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bls24317.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) } - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -256,23 +260,27 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bls24317.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) } - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - return e.Cmp(r) == 0, nil } diff --git a/ecc/bn254/signature/schnorr/schnorr.go b/ecc/bn254/signature/schnorr/schnorr.go index e16e62e7e..d28e3d63f 100644 --- a/ecc/bn254/signature/schnorr/schnorr.go +++ b/ecc/bn254/signature/schnorr/schnorr.go @@ -207,23 +207,27 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bn254.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) } - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -256,23 +260,27 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bn254.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) } - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - return e.Cmp(r) == 0, nil } diff --git a/ecc/bw6-633/signature/schnorr/schnorr.go b/ecc/bw6-633/signature/schnorr/schnorr.go index 3ca930229..9e8631b49 100644 --- a/ecc/bw6-633/signature/schnorr/schnorr.go +++ b/ecc/bw6-633/signature/schnorr/schnorr.go @@ -207,23 +207,27 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bw6633.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) } - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -256,23 +260,27 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bw6633.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) } - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - return e.Cmp(r) == 0, nil } diff --git a/ecc/bw6-756/signature/schnorr/schnorr.go b/ecc/bw6-756/signature/schnorr/schnorr.go index de465a5f6..f44046979 100644 --- a/ecc/bw6-756/signature/schnorr/schnorr.go +++ b/ecc/bw6-756/signature/schnorr/schnorr.go @@ -207,23 +207,27 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bw6756.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) } - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -256,23 +260,27 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bw6756.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) } - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - return e.Cmp(r) == 0, nil } diff --git a/ecc/bw6-761/signature/schnorr/schnorr.go b/ecc/bw6-761/signature/schnorr/schnorr.go index 13ded779e..90e97627b 100644 --- a/ecc/bw6-761/signature/schnorr/schnorr.go +++ b/ecc/bw6-761/signature/schnorr/schnorr.go @@ -207,23 +207,27 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bw6761.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) } - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -256,23 +260,27 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bw6761.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) } - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - return e.Cmp(r) == 0, nil } diff --git a/ecc/secp256k1/signature/schnorr/schnorr.go b/ecc/secp256k1/signature/schnorr/schnorr.go index c0372a5c7..b168333d9 100644 --- a/ecc/secp256k1/signature/schnorr/schnorr.go +++ b/ecc/secp256k1/signature/schnorr/schnorr.go @@ -207,23 +207,27 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P secp256k1.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) } - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -256,23 +260,27 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P secp256k1.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) } - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - return e.Cmp(r) == 0, nil } diff --git a/ecc/stark-curve/signature/schnorr/schnorr.go b/ecc/stark-curve/signature/schnorr/schnorr.go index 55e4f6141..852b48ac9 100644 --- a/ecc/stark-curve/signature/schnorr/schnorr.go +++ b/ecc/stark-curve/signature/schnorr/schnorr.go @@ -207,23 +207,27 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P starkcurve.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) } - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -256,23 +260,27 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P starkcurve.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) } - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - return e.Cmp(r) == 0, nil } diff --git a/internal/generator/signature/schnorr/template/schnorr.go.tmpl b/internal/generator/signature/schnorr/template/schnorr.go.tmpl index 7f1056da6..99b0846c3 100644 --- a/internal/generator/signature/schnorr/template/schnorr.go.tmpl +++ b/internal/generator/signature/schnorr/template/schnorr.go.tmpl @@ -198,22 +198,26 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P {{ .CurvePackage }}.G1Affine P.ScalarMultiplicationBase(k) - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err + } + + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + } else { + r = HashToInt(message) + } s.Mul(scalar, r) s.Sub(k, s). @@ -247,22 +251,26 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P {{ .CurvePackage }}.G1Affine _P.FromJacobian(&P) - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + if hFunc != nil { + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err + } + + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + } else { + e = HashToInt(message) + } return e.Cmp(r) == 0, nil From 0b42484364b68a708fdf06cd33487c369e76c26f Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 26 Jan 2023 10:54:51 +0100 Subject: [PATCH 04/13] style(schnorr): rename ECDSA to Schnorr in test --- .../generator/signature/schnorr/template/marshal.test.go.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/generator/signature/schnorr/template/marshal.test.go.tmpl b/internal/generator/signature/schnorr/template/marshal.test.go.tmpl index 5fc66a474..2e75d159b 100644 --- a/internal/generator/signature/schnorr/template/marshal.test.go.tmpl +++ b/internal/generator/signature/schnorr/template/marshal.test.go.tmpl @@ -23,7 +23,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[{{ toUpper .Name }}] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[{{ toUpper .Name }}] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) From 6ecef50b55ddc1e919e2f0b4b29466fa7c1fcadc Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 26 Jan 2023 11:16:56 +0100 Subject: [PATCH 05/13] test: schnorr with pre-hashed message --- .../signature/schnorr/marshal_test.go | 2 +- .../signature/schnorr/schnorr_test.go | 22 ++++++++++++++----- .../signature/schnorr/marshal_test.go | 2 +- .../signature/schnorr/schnorr_test.go | 22 ++++++++++++++----- .../signature/schnorr/marshal_test.go | 2 +- .../signature/schnorr/schnorr_test.go | 22 ++++++++++++++----- .../signature/schnorr/marshal_test.go | 2 +- .../signature/schnorr/schnorr_test.go | 22 ++++++++++++++----- .../signature/schnorr/marshal_test.go | 2 +- .../signature/schnorr/schnorr_test.go | 22 ++++++++++++++----- ecc/bn254/signature/schnorr/marshal_test.go | 2 +- ecc/bn254/signature/schnorr/schnorr_test.go | 22 ++++++++++++++----- ecc/bw6-633/signature/schnorr/marshal_test.go | 2 +- ecc/bw6-633/signature/schnorr/schnorr_test.go | 22 ++++++++++++++----- ecc/bw6-756/signature/schnorr/marshal_test.go | 2 +- ecc/bw6-756/signature/schnorr/schnorr_test.go | 22 ++++++++++++++----- ecc/bw6-761/signature/schnorr/marshal_test.go | 2 +- ecc/bw6-761/signature/schnorr/schnorr_test.go | 22 ++++++++++++++----- .../signature/schnorr/marshal_test.go | 2 +- .../signature/schnorr/schnorr_test.go | 22 ++++++++++++++----- .../signature/schnorr/marshal_test.go | 2 +- .../signature/schnorr/schnorr_test.go | 22 ++++++++++++++----- .../schnorr/template/schnorr.test.go.tmpl | 22 ++++++++++++++----- 23 files changed, 215 insertions(+), 71 deletions(-) diff --git a/ecc/bls12-377/signature/schnorr/marshal_test.go b/ecc/bls12-377/signature/schnorr/marshal_test.go index 5bd24a7e5..fedca5a07 100644 --- a/ecc/bls12-377/signature/schnorr/marshal_test.go +++ b/ecc/bls12-377/signature/schnorr/marshal_test.go @@ -41,7 +41,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[BLS12-377] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[BLS12-377] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) diff --git a/ecc/bls12-377/signature/schnorr/schnorr_test.go b/ecc/bls12-377/signature/schnorr/schnorr_test.go index 68b7c8c57..157c71856 100644 --- a/ecc/bls12-377/signature/schnorr/schnorr_test.go +++ b/ecc/bls12-377/signature/schnorr/schnorr_test.go @@ -46,6 +46,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[BLS12-377] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -57,10 +71,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -68,11 +81,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } diff --git a/ecc/bls12-378/signature/schnorr/marshal_test.go b/ecc/bls12-378/signature/schnorr/marshal_test.go index 3c81b214c..a5bed6622 100644 --- a/ecc/bls12-378/signature/schnorr/marshal_test.go +++ b/ecc/bls12-378/signature/schnorr/marshal_test.go @@ -41,7 +41,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[BLS12-378] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[BLS12-378] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) diff --git a/ecc/bls12-378/signature/schnorr/schnorr_test.go b/ecc/bls12-378/signature/schnorr/schnorr_test.go index 69d54ce8f..12e42d9ca 100644 --- a/ecc/bls12-378/signature/schnorr/schnorr_test.go +++ b/ecc/bls12-378/signature/schnorr/schnorr_test.go @@ -46,6 +46,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[BLS12-378] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -57,10 +71,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -68,11 +81,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } diff --git a/ecc/bls12-381/signature/schnorr/marshal_test.go b/ecc/bls12-381/signature/schnorr/marshal_test.go index df30517a8..254233609 100644 --- a/ecc/bls12-381/signature/schnorr/marshal_test.go +++ b/ecc/bls12-381/signature/schnorr/marshal_test.go @@ -41,7 +41,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[BLS12-381] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[BLS12-381] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) diff --git a/ecc/bls12-381/signature/schnorr/schnorr_test.go b/ecc/bls12-381/signature/schnorr/schnorr_test.go index ca692100c..50d39e61b 100644 --- a/ecc/bls12-381/signature/schnorr/schnorr_test.go +++ b/ecc/bls12-381/signature/schnorr/schnorr_test.go @@ -46,6 +46,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[BLS12-381] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -57,10 +71,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -68,11 +81,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } diff --git a/ecc/bls24-315/signature/schnorr/marshal_test.go b/ecc/bls24-315/signature/schnorr/marshal_test.go index 43bcbeb6b..f75a8bccf 100644 --- a/ecc/bls24-315/signature/schnorr/marshal_test.go +++ b/ecc/bls24-315/signature/schnorr/marshal_test.go @@ -41,7 +41,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[BLS24-315] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[BLS24-315] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) diff --git a/ecc/bls24-315/signature/schnorr/schnorr_test.go b/ecc/bls24-315/signature/schnorr/schnorr_test.go index a36590b40..aee5be60f 100644 --- a/ecc/bls24-315/signature/schnorr/schnorr_test.go +++ b/ecc/bls24-315/signature/schnorr/schnorr_test.go @@ -46,6 +46,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[BLS24-315] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -57,10 +71,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -68,11 +81,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } diff --git a/ecc/bls24-317/signature/schnorr/marshal_test.go b/ecc/bls24-317/signature/schnorr/marshal_test.go index cf16dbb36..cc55bde47 100644 --- a/ecc/bls24-317/signature/schnorr/marshal_test.go +++ b/ecc/bls24-317/signature/schnorr/marshal_test.go @@ -41,7 +41,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[BLS24-317] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[BLS24-317] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) diff --git a/ecc/bls24-317/signature/schnorr/schnorr_test.go b/ecc/bls24-317/signature/schnorr/schnorr_test.go index 49ec67942..fdadf0eca 100644 --- a/ecc/bls24-317/signature/schnorr/schnorr_test.go +++ b/ecc/bls24-317/signature/schnorr/schnorr_test.go @@ -46,6 +46,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[BLS24-317] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -57,10 +71,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -68,11 +81,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } diff --git a/ecc/bn254/signature/schnorr/marshal_test.go b/ecc/bn254/signature/schnorr/marshal_test.go index 169c1697c..f0bdd21eb 100644 --- a/ecc/bn254/signature/schnorr/marshal_test.go +++ b/ecc/bn254/signature/schnorr/marshal_test.go @@ -41,7 +41,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[BN254] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[BN254] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) diff --git a/ecc/bn254/signature/schnorr/schnorr_test.go b/ecc/bn254/signature/schnorr/schnorr_test.go index 9e8496fc0..dcabca4f4 100644 --- a/ecc/bn254/signature/schnorr/schnorr_test.go +++ b/ecc/bn254/signature/schnorr/schnorr_test.go @@ -46,6 +46,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[BN254] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -57,10 +71,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -68,11 +81,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } diff --git a/ecc/bw6-633/signature/schnorr/marshal_test.go b/ecc/bw6-633/signature/schnorr/marshal_test.go index 3314c79ec..dae0361ae 100644 --- a/ecc/bw6-633/signature/schnorr/marshal_test.go +++ b/ecc/bw6-633/signature/schnorr/marshal_test.go @@ -41,7 +41,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[BW6-633] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[BW6-633] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) diff --git a/ecc/bw6-633/signature/schnorr/schnorr_test.go b/ecc/bw6-633/signature/schnorr/schnorr_test.go index ae4fd01ee..a9bb91e56 100644 --- a/ecc/bw6-633/signature/schnorr/schnorr_test.go +++ b/ecc/bw6-633/signature/schnorr/schnorr_test.go @@ -46,6 +46,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[BW6-633] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -57,10 +71,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -68,11 +81,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } diff --git a/ecc/bw6-756/signature/schnorr/marshal_test.go b/ecc/bw6-756/signature/schnorr/marshal_test.go index 8b65b5c99..8d8ba9b2c 100644 --- a/ecc/bw6-756/signature/schnorr/marshal_test.go +++ b/ecc/bw6-756/signature/schnorr/marshal_test.go @@ -41,7 +41,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[BW6-756] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[BW6-756] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) diff --git a/ecc/bw6-756/signature/schnorr/schnorr_test.go b/ecc/bw6-756/signature/schnorr/schnorr_test.go index becbf1070..b8f3ff26a 100644 --- a/ecc/bw6-756/signature/schnorr/schnorr_test.go +++ b/ecc/bw6-756/signature/schnorr/schnorr_test.go @@ -46,6 +46,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[BW6-756] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -57,10 +71,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -68,11 +81,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } diff --git a/ecc/bw6-761/signature/schnorr/marshal_test.go b/ecc/bw6-761/signature/schnorr/marshal_test.go index d53171fce..cded0c9ad 100644 --- a/ecc/bw6-761/signature/schnorr/marshal_test.go +++ b/ecc/bw6-761/signature/schnorr/marshal_test.go @@ -41,7 +41,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[BW6-761] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[BW6-761] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) diff --git a/ecc/bw6-761/signature/schnorr/schnorr_test.go b/ecc/bw6-761/signature/schnorr/schnorr_test.go index f4ab6ce56..ea0054339 100644 --- a/ecc/bw6-761/signature/schnorr/schnorr_test.go +++ b/ecc/bw6-761/signature/schnorr/schnorr_test.go @@ -46,6 +46,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[BW6-761] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -57,10 +71,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -68,11 +81,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } diff --git a/ecc/secp256k1/signature/schnorr/marshal_test.go b/ecc/secp256k1/signature/schnorr/marshal_test.go index c06385c57..ee0dd08e5 100644 --- a/ecc/secp256k1/signature/schnorr/marshal_test.go +++ b/ecc/secp256k1/signature/schnorr/marshal_test.go @@ -41,7 +41,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[SECP256K1] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[SECP256K1] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) diff --git a/ecc/secp256k1/signature/schnorr/schnorr_test.go b/ecc/secp256k1/signature/schnorr/schnorr_test.go index 8af13bee5..99fa41bec 100644 --- a/ecc/secp256k1/signature/schnorr/schnorr_test.go +++ b/ecc/secp256k1/signature/schnorr/schnorr_test.go @@ -46,6 +46,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[SECP256K1] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -57,10 +71,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -68,11 +81,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } diff --git a/ecc/stark-curve/signature/schnorr/marshal_test.go b/ecc/stark-curve/signature/schnorr/marshal_test.go index 10e961c05..64bd65c14 100644 --- a/ecc/stark-curve/signature/schnorr/marshal_test.go +++ b/ecc/stark-curve/signature/schnorr/marshal_test.go @@ -41,7 +41,7 @@ func TestSerialization(t *testing.T) { properties := gopter.NewProperties(parameters) - properties.Property("[STARK-CURVE] ECDSA serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + properties.Property("[STARK-CURVE] Schnorr serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( func() bool { privKey, _ := GenerateKey(rand.Reader) diff --git a/ecc/stark-curve/signature/schnorr/schnorr_test.go b/ecc/stark-curve/signature/schnorr/schnorr_test.go index 2b8ccdb3a..b9b111eac 100644 --- a/ecc/stark-curve/signature/schnorr/schnorr_test.go +++ b/ecc/stark-curve/signature/schnorr/schnorr_test.go @@ -46,6 +46,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[STARK-CURVE] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -57,10 +71,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -68,11 +81,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } diff --git a/internal/generator/signature/schnorr/template/schnorr.test.go.tmpl b/internal/generator/signature/schnorr/template/schnorr.test.go.tmpl index de6ac9a4a..9f7293193 100644 --- a/internal/generator/signature/schnorr/template/schnorr.test.go.tmpl +++ b/internal/generator/signature/schnorr/template/schnorr.test.go.tmpl @@ -28,6 +28,20 @@ func TestSchnorr(t *testing.T) { }, )) + properties.Property("[{{ toUpper .Name }}] test the signing and verification (pre-hashed)", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing Schnorr") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -39,10 +53,9 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, hFunc) + privKey.Sign(msg, nil) } } @@ -50,11 +63,10 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - hFunc := sha256.New() - sig, _ := privKey.Sign(msg, hFunc) + sig, _ := privKey.Sign(msg, nil) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, hFunc) + privKey.PublicKey.Verify(sig, msg, nil) } } From a55f219a9869484773330b7f346586facdbdc934 Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 26 Jan 2023 13:02:56 +0100 Subject: [PATCH 06/13] feat: add BLS signature scheme --- ecc/bls12-377/signatures/bls/bls.go | 240 ++++++++++++++++++ ecc/bls12-377/signatures/bls/bls_test.go | 74 ++++++ ecc/bls12-377/signatures/bls/doc.go | 22 ++ ecc/bls12-377/signatures/bls/marshal.go | 104 ++++++++ ecc/bls12-377/signatures/bls/marshal_test.go | 64 +++++ .../{signature => signatures}/ecdsa/doc.go | 0 .../{signature => signatures}/ecdsa/ecdsa.go | 0 .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signature => signatures}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 0 .../schnorr/schnorr_test.go | 0 ecc/bls12-378/signatures/bls/bls.go | 240 ++++++++++++++++++ ecc/bls12-378/signatures/bls/bls_test.go | 74 ++++++ ecc/bls12-378/signatures/bls/doc.go | 22 ++ ecc/bls12-378/signatures/bls/marshal.go | 104 ++++++++ ecc/bls12-378/signatures/bls/marshal_test.go | 64 +++++ .../{signature => signatures}/ecdsa/doc.go | 0 .../{signature => signatures}/ecdsa/ecdsa.go | 0 .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signature => signatures}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 0 .../schnorr/schnorr_test.go | 0 ecc/bls12-381/signatures/bls/bls.go | 240 ++++++++++++++++++ ecc/bls12-381/signatures/bls/bls_test.go | 74 ++++++ ecc/bls12-381/signatures/bls/doc.go | 22 ++ ecc/bls12-381/signatures/bls/marshal.go | 104 ++++++++ ecc/bls12-381/signatures/bls/marshal_test.go | 64 +++++ .../{signature => signatures}/ecdsa/doc.go | 0 .../{signature => signatures}/ecdsa/ecdsa.go | 0 .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signature => signatures}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 0 .../schnorr/schnorr_test.go | 0 ecc/bls24-315/signatures/bls/bls.go | 240 ++++++++++++++++++ ecc/bls24-315/signatures/bls/bls_test.go | 74 ++++++ ecc/bls24-315/signatures/bls/doc.go | 22 ++ ecc/bls24-315/signatures/bls/marshal.go | 104 ++++++++ ecc/bls24-315/signatures/bls/marshal_test.go | 64 +++++ .../{signature => signatures}/ecdsa/doc.go | 0 .../{signature => signatures}/ecdsa/ecdsa.go | 0 .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signature => signatures}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 0 .../schnorr/schnorr_test.go | 0 ecc/bls24-317/signatures/bls/bls.go | 240 ++++++++++++++++++ ecc/bls24-317/signatures/bls/bls_test.go | 74 ++++++ ecc/bls24-317/signatures/bls/doc.go | 22 ++ ecc/bls24-317/signatures/bls/marshal.go | 104 ++++++++ ecc/bls24-317/signatures/bls/marshal_test.go | 64 +++++ .../{signature => signatures}/ecdsa/doc.go | 0 .../{signature => signatures}/ecdsa/ecdsa.go | 0 .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signature => signatures}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 0 .../schnorr/schnorr_test.go | 0 ecc/bn254/signatures/bls/bls.go | 240 ++++++++++++++++++ ecc/bn254/signatures/bls/bls_test.go | 74 ++++++ ecc/bn254/signatures/bls/doc.go | 22 ++ ecc/bn254/signatures/bls/marshal.go | 104 ++++++++ ecc/bn254/signatures/bls/marshal_test.go | 64 +++++ .../{signature => signatures}/ecdsa/doc.go | 0 .../{signature => signatures}/ecdsa/ecdsa.go | 0 .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signature => signatures}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 0 .../schnorr/schnorr_test.go | 0 ecc/bw6-633/signatures/bls/bls.go | 240 ++++++++++++++++++ ecc/bw6-633/signatures/bls/bls_test.go | 74 ++++++ ecc/bw6-633/signatures/bls/doc.go | 22 ++ ecc/bw6-633/signatures/bls/marshal.go | 104 ++++++++ ecc/bw6-633/signatures/bls/marshal_test.go | 64 +++++ .../{signature => signatures}/ecdsa/doc.go | 0 .../{signature => signatures}/ecdsa/ecdsa.go | 0 .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signature => signatures}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 0 .../schnorr/schnorr_test.go | 0 ecc/bw6-756/signatures/bls/bls.go | 240 ++++++++++++++++++ ecc/bw6-756/signatures/bls/bls_test.go | 74 ++++++ ecc/bw6-756/signatures/bls/doc.go | 22 ++ ecc/bw6-756/signatures/bls/marshal.go | 104 ++++++++ ecc/bw6-756/signatures/bls/marshal_test.go | 64 +++++ .../{signature => signatures}/ecdsa/doc.go | 0 .../{signature => signatures}/ecdsa/ecdsa.go | 0 .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signature => signatures}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 0 .../schnorr/schnorr_test.go | 0 ecc/bw6-761/signatures/bls/bls.go | 240 ++++++++++++++++++ ecc/bw6-761/signatures/bls/bls_test.go | 74 ++++++ ecc/bw6-761/signatures/bls/doc.go | 22 ++ ecc/bw6-761/signatures/bls/marshal.go | 104 ++++++++ ecc/bw6-761/signatures/bls/marshal_test.go | 64 +++++ .../{signature => signatures}/ecdsa/doc.go | 0 .../{signature => signatures}/ecdsa/ecdsa.go | 0 .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signature => signatures}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 0 .../schnorr/schnorr_test.go | 0 .../{signature => signatures}/ecdsa/doc.go | 0 .../{signature => signatures}/ecdsa/ecdsa.go | 0 .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signature => signatures}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 0 .../schnorr/schnorr_test.go | 0 .../{signature => signatures}/ecdsa/doc.go | 0 .../{signature => signatures}/ecdsa/ecdsa.go | 0 .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signature => signatures}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 0 .../schnorr/schnorr_test.go | 0 internal/generator/main.go | 8 +- internal/generator/signature/bls/generate.go | 24 ++ .../signature/bls/template/bls.go.tmpl | 227 +++++++++++++++++ .../signature/bls/template/bls.test.go.tmpl | 56 ++++ .../signature/bls/template/doc.go.tmpl | 7 + .../signature/bls/template/marshal.go.tmpl | 94 +++++++ .../bls/template/marshal.test.go.tmpl | 46 ++++ signature/bls/bls.go | 59 +++++ 163 files changed, 5055 insertions(+), 2 deletions(-) create mode 100644 ecc/bls12-377/signatures/bls/bls.go create mode 100644 ecc/bls12-377/signatures/bls/bls_test.go create mode 100644 ecc/bls12-377/signatures/bls/doc.go create mode 100644 ecc/bls12-377/signatures/bls/marshal.go create mode 100644 ecc/bls12-377/signatures/bls/marshal_test.go rename ecc/bls12-377/{signature => signatures}/ecdsa/doc.go (100%) rename ecc/bls12-377/{signature => signatures}/ecdsa/ecdsa.go (100%) rename ecc/bls12-377/{signature => signatures}/ecdsa/ecdsa_test.go (100%) rename ecc/bls12-377/{signature => signatures}/ecdsa/marshal.go (100%) rename ecc/bls12-377/{signature => signatures}/ecdsa/marshal_test.go (100%) rename ecc/bls12-377/{signature => signatures}/schnorr/doc.go (100%) rename ecc/bls12-377/{signature => signatures}/schnorr/marshal.go (100%) rename ecc/bls12-377/{signature => signatures}/schnorr/marshal_test.go (100%) rename ecc/bls12-377/{signature => signatures}/schnorr/schnorr.go (100%) rename ecc/bls12-377/{signature => signatures}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bls12-378/signatures/bls/bls.go create mode 100644 ecc/bls12-378/signatures/bls/bls_test.go create mode 100644 ecc/bls12-378/signatures/bls/doc.go create mode 100644 ecc/bls12-378/signatures/bls/marshal.go create mode 100644 ecc/bls12-378/signatures/bls/marshal_test.go rename ecc/bls12-378/{signature => signatures}/ecdsa/doc.go (100%) rename ecc/bls12-378/{signature => signatures}/ecdsa/ecdsa.go (100%) rename ecc/bls12-378/{signature => signatures}/ecdsa/ecdsa_test.go (100%) rename ecc/bls12-378/{signature => signatures}/ecdsa/marshal.go (100%) rename ecc/bls12-378/{signature => signatures}/ecdsa/marshal_test.go (100%) rename ecc/bls12-378/{signature => signatures}/schnorr/doc.go (100%) rename ecc/bls12-378/{signature => signatures}/schnorr/marshal.go (100%) rename ecc/bls12-378/{signature => signatures}/schnorr/marshal_test.go (100%) rename ecc/bls12-378/{signature => signatures}/schnorr/schnorr.go (100%) rename ecc/bls12-378/{signature => signatures}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bls12-381/signatures/bls/bls.go create mode 100644 ecc/bls12-381/signatures/bls/bls_test.go create mode 100644 ecc/bls12-381/signatures/bls/doc.go create mode 100644 ecc/bls12-381/signatures/bls/marshal.go create mode 100644 ecc/bls12-381/signatures/bls/marshal_test.go rename ecc/bls12-381/{signature => signatures}/ecdsa/doc.go (100%) rename ecc/bls12-381/{signature => signatures}/ecdsa/ecdsa.go (100%) rename ecc/bls12-381/{signature => signatures}/ecdsa/ecdsa_test.go (100%) rename ecc/bls12-381/{signature => signatures}/ecdsa/marshal.go (100%) rename ecc/bls12-381/{signature => signatures}/ecdsa/marshal_test.go (100%) rename ecc/bls12-381/{signature => signatures}/schnorr/doc.go (100%) rename ecc/bls12-381/{signature => signatures}/schnorr/marshal.go (100%) rename ecc/bls12-381/{signature => signatures}/schnorr/marshal_test.go (100%) rename ecc/bls12-381/{signature => signatures}/schnorr/schnorr.go (100%) rename ecc/bls12-381/{signature => signatures}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bls24-315/signatures/bls/bls.go create mode 100644 ecc/bls24-315/signatures/bls/bls_test.go create mode 100644 ecc/bls24-315/signatures/bls/doc.go create mode 100644 ecc/bls24-315/signatures/bls/marshal.go create mode 100644 ecc/bls24-315/signatures/bls/marshal_test.go rename ecc/bls24-315/{signature => signatures}/ecdsa/doc.go (100%) rename ecc/bls24-315/{signature => signatures}/ecdsa/ecdsa.go (100%) rename ecc/bls24-315/{signature => signatures}/ecdsa/ecdsa_test.go (100%) rename ecc/bls24-315/{signature => signatures}/ecdsa/marshal.go (100%) rename ecc/bls24-315/{signature => signatures}/ecdsa/marshal_test.go (100%) rename ecc/bls24-315/{signature => signatures}/schnorr/doc.go (100%) rename ecc/bls24-315/{signature => signatures}/schnorr/marshal.go (100%) rename ecc/bls24-315/{signature => signatures}/schnorr/marshal_test.go (100%) rename ecc/bls24-315/{signature => signatures}/schnorr/schnorr.go (100%) rename ecc/bls24-315/{signature => signatures}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bls24-317/signatures/bls/bls.go create mode 100644 ecc/bls24-317/signatures/bls/bls_test.go create mode 100644 ecc/bls24-317/signatures/bls/doc.go create mode 100644 ecc/bls24-317/signatures/bls/marshal.go create mode 100644 ecc/bls24-317/signatures/bls/marshal_test.go rename ecc/bls24-317/{signature => signatures}/ecdsa/doc.go (100%) rename ecc/bls24-317/{signature => signatures}/ecdsa/ecdsa.go (100%) rename ecc/bls24-317/{signature => signatures}/ecdsa/ecdsa_test.go (100%) rename ecc/bls24-317/{signature => signatures}/ecdsa/marshal.go (100%) rename ecc/bls24-317/{signature => signatures}/ecdsa/marshal_test.go (100%) rename ecc/bls24-317/{signature => signatures}/schnorr/doc.go (100%) rename ecc/bls24-317/{signature => signatures}/schnorr/marshal.go (100%) rename ecc/bls24-317/{signature => signatures}/schnorr/marshal_test.go (100%) rename ecc/bls24-317/{signature => signatures}/schnorr/schnorr.go (100%) rename ecc/bls24-317/{signature => signatures}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bn254/signatures/bls/bls.go create mode 100644 ecc/bn254/signatures/bls/bls_test.go create mode 100644 ecc/bn254/signatures/bls/doc.go create mode 100644 ecc/bn254/signatures/bls/marshal.go create mode 100644 ecc/bn254/signatures/bls/marshal_test.go rename ecc/bn254/{signature => signatures}/ecdsa/doc.go (100%) rename ecc/bn254/{signature => signatures}/ecdsa/ecdsa.go (100%) rename ecc/bn254/{signature => signatures}/ecdsa/ecdsa_test.go (100%) rename ecc/bn254/{signature => signatures}/ecdsa/marshal.go (100%) rename ecc/bn254/{signature => signatures}/ecdsa/marshal_test.go (100%) rename ecc/bn254/{signature => signatures}/schnorr/doc.go (100%) rename ecc/bn254/{signature => signatures}/schnorr/marshal.go (100%) rename ecc/bn254/{signature => signatures}/schnorr/marshal_test.go (100%) rename ecc/bn254/{signature => signatures}/schnorr/schnorr.go (100%) rename ecc/bn254/{signature => signatures}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bw6-633/signatures/bls/bls.go create mode 100644 ecc/bw6-633/signatures/bls/bls_test.go create mode 100644 ecc/bw6-633/signatures/bls/doc.go create mode 100644 ecc/bw6-633/signatures/bls/marshal.go create mode 100644 ecc/bw6-633/signatures/bls/marshal_test.go rename ecc/bw6-633/{signature => signatures}/ecdsa/doc.go (100%) rename ecc/bw6-633/{signature => signatures}/ecdsa/ecdsa.go (100%) rename ecc/bw6-633/{signature => signatures}/ecdsa/ecdsa_test.go (100%) rename ecc/bw6-633/{signature => signatures}/ecdsa/marshal.go (100%) rename ecc/bw6-633/{signature => signatures}/ecdsa/marshal_test.go (100%) rename ecc/bw6-633/{signature => signatures}/schnorr/doc.go (100%) rename ecc/bw6-633/{signature => signatures}/schnorr/marshal.go (100%) rename ecc/bw6-633/{signature => signatures}/schnorr/marshal_test.go (100%) rename ecc/bw6-633/{signature => signatures}/schnorr/schnorr.go (100%) rename ecc/bw6-633/{signature => signatures}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bw6-756/signatures/bls/bls.go create mode 100644 ecc/bw6-756/signatures/bls/bls_test.go create mode 100644 ecc/bw6-756/signatures/bls/doc.go create mode 100644 ecc/bw6-756/signatures/bls/marshal.go create mode 100644 ecc/bw6-756/signatures/bls/marshal_test.go rename ecc/bw6-756/{signature => signatures}/ecdsa/doc.go (100%) rename ecc/bw6-756/{signature => signatures}/ecdsa/ecdsa.go (100%) rename ecc/bw6-756/{signature => signatures}/ecdsa/ecdsa_test.go (100%) rename ecc/bw6-756/{signature => signatures}/ecdsa/marshal.go (100%) rename ecc/bw6-756/{signature => signatures}/ecdsa/marshal_test.go (100%) rename ecc/bw6-756/{signature => signatures}/schnorr/doc.go (100%) rename ecc/bw6-756/{signature => signatures}/schnorr/marshal.go (100%) rename ecc/bw6-756/{signature => signatures}/schnorr/marshal_test.go (100%) rename ecc/bw6-756/{signature => signatures}/schnorr/schnorr.go (100%) rename ecc/bw6-756/{signature => signatures}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bw6-761/signatures/bls/bls.go create mode 100644 ecc/bw6-761/signatures/bls/bls_test.go create mode 100644 ecc/bw6-761/signatures/bls/doc.go create mode 100644 ecc/bw6-761/signatures/bls/marshal.go create mode 100644 ecc/bw6-761/signatures/bls/marshal_test.go rename ecc/bw6-761/{signature => signatures}/ecdsa/doc.go (100%) rename ecc/bw6-761/{signature => signatures}/ecdsa/ecdsa.go (100%) rename ecc/bw6-761/{signature => signatures}/ecdsa/ecdsa_test.go (100%) rename ecc/bw6-761/{signature => signatures}/ecdsa/marshal.go (100%) rename ecc/bw6-761/{signature => signatures}/ecdsa/marshal_test.go (100%) rename ecc/bw6-761/{signature => signatures}/schnorr/doc.go (100%) rename ecc/bw6-761/{signature => signatures}/schnorr/marshal.go (100%) rename ecc/bw6-761/{signature => signatures}/schnorr/marshal_test.go (100%) rename ecc/bw6-761/{signature => signatures}/schnorr/schnorr.go (100%) rename ecc/bw6-761/{signature => signatures}/schnorr/schnorr_test.go (100%) rename ecc/secp256k1/{signature => signatures}/ecdsa/doc.go (100%) rename ecc/secp256k1/{signature => signatures}/ecdsa/ecdsa.go (100%) rename ecc/secp256k1/{signature => signatures}/ecdsa/ecdsa_test.go (100%) rename ecc/secp256k1/{signature => signatures}/ecdsa/marshal.go (100%) rename ecc/secp256k1/{signature => signatures}/ecdsa/marshal_test.go (100%) rename ecc/secp256k1/{signature => signatures}/schnorr/doc.go (100%) rename ecc/secp256k1/{signature => signatures}/schnorr/marshal.go (100%) rename ecc/secp256k1/{signature => signatures}/schnorr/marshal_test.go (100%) rename ecc/secp256k1/{signature => signatures}/schnorr/schnorr.go (100%) rename ecc/secp256k1/{signature => signatures}/schnorr/schnorr_test.go (100%) rename ecc/stark-curve/{signature => signatures}/ecdsa/doc.go (100%) rename ecc/stark-curve/{signature => signatures}/ecdsa/ecdsa.go (100%) rename ecc/stark-curve/{signature => signatures}/ecdsa/ecdsa_test.go (100%) rename ecc/stark-curve/{signature => signatures}/ecdsa/marshal.go (100%) rename ecc/stark-curve/{signature => signatures}/ecdsa/marshal_test.go (100%) rename ecc/stark-curve/{signature => signatures}/schnorr/doc.go (100%) rename ecc/stark-curve/{signature => signatures}/schnorr/marshal.go (100%) rename ecc/stark-curve/{signature => signatures}/schnorr/marshal_test.go (100%) rename ecc/stark-curve/{signature => signatures}/schnorr/schnorr.go (100%) rename ecc/stark-curve/{signature => signatures}/schnorr/schnorr_test.go (100%) create mode 100644 internal/generator/signature/bls/generate.go create mode 100644 internal/generator/signature/bls/template/bls.go.tmpl create mode 100644 internal/generator/signature/bls/template/bls.test.go.tmpl create mode 100644 internal/generator/signature/bls/template/doc.go.tmpl create mode 100644 internal/generator/signature/bls/template/marshal.go.tmpl create mode 100644 internal/generator/signature/bls/template/marshal.test.go.tmpl create mode 100644 signature/bls/bls.go diff --git a/ecc/bls12-377/signatures/bls/bls.go b/ecc/bls12-377/signatures/bls/bls.go new file mode 100644 index 000000000..4898a1c25 --- /dev/null +++ b/ecc/bls12-377/signatures/bls/bls.go @@ -0,0 +1,240 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-377" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFp +) + +var order = fr.Modulus() + +// PublicKey represents an BLS public key +type PublicKey struct { + A bls12377.G1Affine +} + +// PrivateKey represents an BLS private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an BLS signature +type Signature struct { + S bls12377.G2Affine +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bls12377.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the BLS signature +// +// H(m) ← m (hash to G₂) +// S = sk ⋅ H(m) ∈ G₂ +// signature = S +// +// hFunc should always be nil. +// Hashing the message first with hFunc is not needed, as it is included in HashToG2. +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + // Hash the message into G2 + dst := []byte("0x01") + H, err := bls12377.HashToG2(message, dst) + if err != nil { + return nil, err + } + + // Sign + var sig Signature + scalar := new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + sig.S.ScalarMultiplication(&H, scalar) + + return sig.Bytes(), nil +} + +// Verify validates the BLS signature +// +// e(G1, sig.S) ?= e(pk, G2) +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + // Hash the message into G2 + dst := []byte("0x01") + H, err := bls12377.HashToG2(message, dst) + if err != nil { + return false, err + } + + // Verify the signature + _, _, g1, _ := bls12377.Generators() + g1.Neg(&g1) + f, err := bls12377.PairingCheck([]bls12377.G1Affine{g1, publicKey.A}, []bls12377.G2Affine{sig.S, H}) + if err != nil { + return false, err + } + + return f, nil + +} diff --git a/ecc/bls12-377/signatures/bls/bls_test.go b/ecc/bls12-377/signatures/bls/bls_test.go new file mode 100644 index 000000000..922e78981 --- /dev/null +++ b/ecc/bls12-377/signatures/bls/bls_test.go @@ -0,0 +1,74 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestBLS(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-377] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing BLS") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking BLS sign()") + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, nil) + } +} + +func BenchmarkVerifyBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking BLS sign()") + sig, _ := privKey.Sign(msg, nil) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, nil) + } +} diff --git a/ecc/bls12-377/signatures/bls/doc.go b/ecc/bls12-377/signatures/bls/doc.go new file mode 100644 index 000000000..134da1144 --- /dev/null +++ b/ecc/bls12-377/signatures/bls/doc.go @@ -0,0 +1,22 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package bls provides BLS signature scheme on the bls12-377 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/BLS_digital_signature +// - IETF: https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/05/ +package bls diff --git a/ecc/bls12-377/signatures/bls/marshal.go b/ecc/bls12-377/signatures/bls/marshal.go new file mode 100644 index 000000000..6f4eccc43 --- /dev/null +++ b/ecc/bls12-377/signatures/bls/marshal.go @@ -0,0 +1,104 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFp (G2 compressef encoding) +func (sig *Signature) Bytes() []byte { + res := sig.S.Bytes() + return res[:sizeSignature] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + sig.S.SetBytes(buf) + n += sizeFr + return n, nil +} diff --git a/ecc/bls12-377/signatures/bls/marshal_test.go b/ecc/bls12-377/signatures/bls/marshal_test.go new file mode 100644 index 000000000..37f9a5355 --- /dev/null +++ b/ecc/bls12-377/signatures/bls/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-377] BLS serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bls12-377/signature/ecdsa/doc.go b/ecc/bls12-377/signatures/ecdsa/doc.go similarity index 100% rename from ecc/bls12-377/signature/ecdsa/doc.go rename to ecc/bls12-377/signatures/ecdsa/doc.go diff --git a/ecc/bls12-377/signature/ecdsa/ecdsa.go b/ecc/bls12-377/signatures/ecdsa/ecdsa.go similarity index 100% rename from ecc/bls12-377/signature/ecdsa/ecdsa.go rename to ecc/bls12-377/signatures/ecdsa/ecdsa.go diff --git a/ecc/bls12-377/signature/ecdsa/ecdsa_test.go b/ecc/bls12-377/signatures/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls12-377/signature/ecdsa/ecdsa_test.go rename to ecc/bls12-377/signatures/ecdsa/ecdsa_test.go diff --git a/ecc/bls12-377/signature/ecdsa/marshal.go b/ecc/bls12-377/signatures/ecdsa/marshal.go similarity index 100% rename from ecc/bls12-377/signature/ecdsa/marshal.go rename to ecc/bls12-377/signatures/ecdsa/marshal.go diff --git a/ecc/bls12-377/signature/ecdsa/marshal_test.go b/ecc/bls12-377/signatures/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls12-377/signature/ecdsa/marshal_test.go rename to ecc/bls12-377/signatures/ecdsa/marshal_test.go diff --git a/ecc/bls12-377/signature/schnorr/doc.go b/ecc/bls12-377/signatures/schnorr/doc.go similarity index 100% rename from ecc/bls12-377/signature/schnorr/doc.go rename to ecc/bls12-377/signatures/schnorr/doc.go diff --git a/ecc/bls12-377/signature/schnorr/marshal.go b/ecc/bls12-377/signatures/schnorr/marshal.go similarity index 100% rename from ecc/bls12-377/signature/schnorr/marshal.go rename to ecc/bls12-377/signatures/schnorr/marshal.go diff --git a/ecc/bls12-377/signature/schnorr/marshal_test.go b/ecc/bls12-377/signatures/schnorr/marshal_test.go similarity index 100% rename from ecc/bls12-377/signature/schnorr/marshal_test.go rename to ecc/bls12-377/signatures/schnorr/marshal_test.go diff --git a/ecc/bls12-377/signature/schnorr/schnorr.go b/ecc/bls12-377/signatures/schnorr/schnorr.go similarity index 100% rename from ecc/bls12-377/signature/schnorr/schnorr.go rename to ecc/bls12-377/signatures/schnorr/schnorr.go diff --git a/ecc/bls12-377/signature/schnorr/schnorr_test.go b/ecc/bls12-377/signatures/schnorr/schnorr_test.go similarity index 100% rename from ecc/bls12-377/signature/schnorr/schnorr_test.go rename to ecc/bls12-377/signatures/schnorr/schnorr_test.go diff --git a/ecc/bls12-378/signatures/bls/bls.go b/ecc/bls12-378/signatures/bls/bls.go new file mode 100644 index 000000000..951e1c227 --- /dev/null +++ b/ecc/bls12-378/signatures/bls/bls.go @@ -0,0 +1,240 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-378" + "github.com/consensys/gnark-crypto/ecc/bls12-378/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-378/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFp +) + +var order = fr.Modulus() + +// PublicKey represents an BLS public key +type PublicKey struct { + A bls12378.G1Affine +} + +// PrivateKey represents an BLS private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an BLS signature +type Signature struct { + S bls12378.G2Affine +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bls12378.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the BLS signature +// +// H(m) ← m (hash to G₂) +// S = sk ⋅ H(m) ∈ G₂ +// signature = S +// +// hFunc should always be nil. +// Hashing the message first with hFunc is not needed, as it is included in HashToG2. +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + // Hash the message into G2 + dst := []byte("0x01") + H, err := bls12378.HashToG2(message, dst) + if err != nil { + return nil, err + } + + // Sign + var sig Signature + scalar := new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + sig.S.ScalarMultiplication(&H, scalar) + + return sig.Bytes(), nil +} + +// Verify validates the BLS signature +// +// e(G1, sig.S) ?= e(pk, G2) +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + // Hash the message into G2 + dst := []byte("0x01") + H, err := bls12378.HashToG2(message, dst) + if err != nil { + return false, err + } + + // Verify the signature + _, _, g1, _ := bls12378.Generators() + g1.Neg(&g1) + f, err := bls12378.PairingCheck([]bls12378.G1Affine{g1, publicKey.A}, []bls12378.G2Affine{sig.S, H}) + if err != nil { + return false, err + } + + return f, nil + +} diff --git a/ecc/bls12-378/signatures/bls/bls_test.go b/ecc/bls12-378/signatures/bls/bls_test.go new file mode 100644 index 000000000..020c82120 --- /dev/null +++ b/ecc/bls12-378/signatures/bls/bls_test.go @@ -0,0 +1,74 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestBLS(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-378] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing BLS") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking BLS sign()") + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, nil) + } +} + +func BenchmarkVerifyBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking BLS sign()") + sig, _ := privKey.Sign(msg, nil) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, nil) + } +} diff --git a/ecc/bls12-378/signatures/bls/doc.go b/ecc/bls12-378/signatures/bls/doc.go new file mode 100644 index 000000000..e783ed744 --- /dev/null +++ b/ecc/bls12-378/signatures/bls/doc.go @@ -0,0 +1,22 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package bls provides BLS signature scheme on the bls12-378 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/BLS_digital_signature +// - IETF: https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/05/ +package bls diff --git a/ecc/bls12-378/signatures/bls/marshal.go b/ecc/bls12-378/signatures/bls/marshal.go new file mode 100644 index 000000000..6f4eccc43 --- /dev/null +++ b/ecc/bls12-378/signatures/bls/marshal.go @@ -0,0 +1,104 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFp (G2 compressef encoding) +func (sig *Signature) Bytes() []byte { + res := sig.S.Bytes() + return res[:sizeSignature] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + sig.S.SetBytes(buf) + n += sizeFr + return n, nil +} diff --git a/ecc/bls12-378/signatures/bls/marshal_test.go b/ecc/bls12-378/signatures/bls/marshal_test.go new file mode 100644 index 000000000..5d561539d --- /dev/null +++ b/ecc/bls12-378/signatures/bls/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-378] BLS serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bls12-378/signature/ecdsa/doc.go b/ecc/bls12-378/signatures/ecdsa/doc.go similarity index 100% rename from ecc/bls12-378/signature/ecdsa/doc.go rename to ecc/bls12-378/signatures/ecdsa/doc.go diff --git a/ecc/bls12-378/signature/ecdsa/ecdsa.go b/ecc/bls12-378/signatures/ecdsa/ecdsa.go similarity index 100% rename from ecc/bls12-378/signature/ecdsa/ecdsa.go rename to ecc/bls12-378/signatures/ecdsa/ecdsa.go diff --git a/ecc/bls12-378/signature/ecdsa/ecdsa_test.go b/ecc/bls12-378/signatures/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls12-378/signature/ecdsa/ecdsa_test.go rename to ecc/bls12-378/signatures/ecdsa/ecdsa_test.go diff --git a/ecc/bls12-378/signature/ecdsa/marshal.go b/ecc/bls12-378/signatures/ecdsa/marshal.go similarity index 100% rename from ecc/bls12-378/signature/ecdsa/marshal.go rename to ecc/bls12-378/signatures/ecdsa/marshal.go diff --git a/ecc/bls12-378/signature/ecdsa/marshal_test.go b/ecc/bls12-378/signatures/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls12-378/signature/ecdsa/marshal_test.go rename to ecc/bls12-378/signatures/ecdsa/marshal_test.go diff --git a/ecc/bls12-378/signature/schnorr/doc.go b/ecc/bls12-378/signatures/schnorr/doc.go similarity index 100% rename from ecc/bls12-378/signature/schnorr/doc.go rename to ecc/bls12-378/signatures/schnorr/doc.go diff --git a/ecc/bls12-378/signature/schnorr/marshal.go b/ecc/bls12-378/signatures/schnorr/marshal.go similarity index 100% rename from ecc/bls12-378/signature/schnorr/marshal.go rename to ecc/bls12-378/signatures/schnorr/marshal.go diff --git a/ecc/bls12-378/signature/schnorr/marshal_test.go b/ecc/bls12-378/signatures/schnorr/marshal_test.go similarity index 100% rename from ecc/bls12-378/signature/schnorr/marshal_test.go rename to ecc/bls12-378/signatures/schnorr/marshal_test.go diff --git a/ecc/bls12-378/signature/schnorr/schnorr.go b/ecc/bls12-378/signatures/schnorr/schnorr.go similarity index 100% rename from ecc/bls12-378/signature/schnorr/schnorr.go rename to ecc/bls12-378/signatures/schnorr/schnorr.go diff --git a/ecc/bls12-378/signature/schnorr/schnorr_test.go b/ecc/bls12-378/signatures/schnorr/schnorr_test.go similarity index 100% rename from ecc/bls12-378/signature/schnorr/schnorr_test.go rename to ecc/bls12-378/signatures/schnorr/schnorr_test.go diff --git a/ecc/bls12-381/signatures/bls/bls.go b/ecc/bls12-381/signatures/bls/bls.go new file mode 100644 index 000000000..5af9e435e --- /dev/null +++ b/ecc/bls12-381/signatures/bls/bls.go @@ -0,0 +1,240 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFp +) + +var order = fr.Modulus() + +// PublicKey represents an BLS public key +type PublicKey struct { + A bls12381.G1Affine +} + +// PrivateKey represents an BLS private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an BLS signature +type Signature struct { + S bls12381.G2Affine +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bls12381.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the BLS signature +// +// H(m) ← m (hash to G₂) +// S = sk ⋅ H(m) ∈ G₂ +// signature = S +// +// hFunc should always be nil. +// Hashing the message first with hFunc is not needed, as it is included in HashToG2. +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + // Hash the message into G2 + dst := []byte("0x01") + H, err := bls12381.HashToG2(message, dst) + if err != nil { + return nil, err + } + + // Sign + var sig Signature + scalar := new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + sig.S.ScalarMultiplication(&H, scalar) + + return sig.Bytes(), nil +} + +// Verify validates the BLS signature +// +// e(G1, sig.S) ?= e(pk, G2) +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + // Hash the message into G2 + dst := []byte("0x01") + H, err := bls12381.HashToG2(message, dst) + if err != nil { + return false, err + } + + // Verify the signature + _, _, g1, _ := bls12381.Generators() + g1.Neg(&g1) + f, err := bls12381.PairingCheck([]bls12381.G1Affine{g1, publicKey.A}, []bls12381.G2Affine{sig.S, H}) + if err != nil { + return false, err + } + + return f, nil + +} diff --git a/ecc/bls12-381/signatures/bls/bls_test.go b/ecc/bls12-381/signatures/bls/bls_test.go new file mode 100644 index 000000000..767077ce8 --- /dev/null +++ b/ecc/bls12-381/signatures/bls/bls_test.go @@ -0,0 +1,74 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestBLS(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-381] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing BLS") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking BLS sign()") + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, nil) + } +} + +func BenchmarkVerifyBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking BLS sign()") + sig, _ := privKey.Sign(msg, nil) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, nil) + } +} diff --git a/ecc/bls12-381/signatures/bls/doc.go b/ecc/bls12-381/signatures/bls/doc.go new file mode 100644 index 000000000..401106ece --- /dev/null +++ b/ecc/bls12-381/signatures/bls/doc.go @@ -0,0 +1,22 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package bls provides BLS signature scheme on the bls12-381 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/BLS_digital_signature +// - IETF: https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/05/ +package bls diff --git a/ecc/bls12-381/signatures/bls/marshal.go b/ecc/bls12-381/signatures/bls/marshal.go new file mode 100644 index 000000000..6f4eccc43 --- /dev/null +++ b/ecc/bls12-381/signatures/bls/marshal.go @@ -0,0 +1,104 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFp (G2 compressef encoding) +func (sig *Signature) Bytes() []byte { + res := sig.S.Bytes() + return res[:sizeSignature] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + sig.S.SetBytes(buf) + n += sizeFr + return n, nil +} diff --git a/ecc/bls12-381/signatures/bls/marshal_test.go b/ecc/bls12-381/signatures/bls/marshal_test.go new file mode 100644 index 000000000..3e2056648 --- /dev/null +++ b/ecc/bls12-381/signatures/bls/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS12-381] BLS serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bls12-381/signature/ecdsa/doc.go b/ecc/bls12-381/signatures/ecdsa/doc.go similarity index 100% rename from ecc/bls12-381/signature/ecdsa/doc.go rename to ecc/bls12-381/signatures/ecdsa/doc.go diff --git a/ecc/bls12-381/signature/ecdsa/ecdsa.go b/ecc/bls12-381/signatures/ecdsa/ecdsa.go similarity index 100% rename from ecc/bls12-381/signature/ecdsa/ecdsa.go rename to ecc/bls12-381/signatures/ecdsa/ecdsa.go diff --git a/ecc/bls12-381/signature/ecdsa/ecdsa_test.go b/ecc/bls12-381/signatures/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls12-381/signature/ecdsa/ecdsa_test.go rename to ecc/bls12-381/signatures/ecdsa/ecdsa_test.go diff --git a/ecc/bls12-381/signature/ecdsa/marshal.go b/ecc/bls12-381/signatures/ecdsa/marshal.go similarity index 100% rename from ecc/bls12-381/signature/ecdsa/marshal.go rename to ecc/bls12-381/signatures/ecdsa/marshal.go diff --git a/ecc/bls12-381/signature/ecdsa/marshal_test.go b/ecc/bls12-381/signatures/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls12-381/signature/ecdsa/marshal_test.go rename to ecc/bls12-381/signatures/ecdsa/marshal_test.go diff --git a/ecc/bls12-381/signature/schnorr/doc.go b/ecc/bls12-381/signatures/schnorr/doc.go similarity index 100% rename from ecc/bls12-381/signature/schnorr/doc.go rename to ecc/bls12-381/signatures/schnorr/doc.go diff --git a/ecc/bls12-381/signature/schnorr/marshal.go b/ecc/bls12-381/signatures/schnorr/marshal.go similarity index 100% rename from ecc/bls12-381/signature/schnorr/marshal.go rename to ecc/bls12-381/signatures/schnorr/marshal.go diff --git a/ecc/bls12-381/signature/schnorr/marshal_test.go b/ecc/bls12-381/signatures/schnorr/marshal_test.go similarity index 100% rename from ecc/bls12-381/signature/schnorr/marshal_test.go rename to ecc/bls12-381/signatures/schnorr/marshal_test.go diff --git a/ecc/bls12-381/signature/schnorr/schnorr.go b/ecc/bls12-381/signatures/schnorr/schnorr.go similarity index 100% rename from ecc/bls12-381/signature/schnorr/schnorr.go rename to ecc/bls12-381/signatures/schnorr/schnorr.go diff --git a/ecc/bls12-381/signature/schnorr/schnorr_test.go b/ecc/bls12-381/signatures/schnorr/schnorr_test.go similarity index 100% rename from ecc/bls12-381/signature/schnorr/schnorr_test.go rename to ecc/bls12-381/signatures/schnorr/schnorr_test.go diff --git a/ecc/bls24-315/signatures/bls/bls.go b/ecc/bls24-315/signatures/bls/bls.go new file mode 100644 index 000000000..ed6bc4791 --- /dev/null +++ b/ecc/bls24-315/signatures/bls/bls.go @@ -0,0 +1,240 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls24-315" + "github.com/consensys/gnark-crypto/ecc/bls24-315/fp" + "github.com/consensys/gnark-crypto/ecc/bls24-315/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 4 * sizeFp +) + +var order = fr.Modulus() + +// PublicKey represents an BLS public key +type PublicKey struct { + A bls24315.G1Affine +} + +// PrivateKey represents an BLS private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an BLS signature +type Signature struct { + S bls24315.G2Affine +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bls24315.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the BLS signature +// +// H(m) ← m (hash to G₂) +// S = sk ⋅ H(m) ∈ G₂ +// signature = S +// +// hFunc should always be nil. +// Hashing the message first with hFunc is not needed, as it is included in HashToG2. +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + // Hash the message into G2 + dst := []byte("0x01") + H, err := bls24315.HashToG2(message, dst) + if err != nil { + return nil, err + } + + // Sign + var sig Signature + scalar := new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + sig.S.ScalarMultiplication(&H, scalar) + + return sig.Bytes(), nil +} + +// Verify validates the BLS signature +// +// e(G1, sig.S) ?= e(pk, G2) +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + // Hash the message into G2 + dst := []byte("0x01") + H, err := bls24315.HashToG2(message, dst) + if err != nil { + return false, err + } + + // Verify the signature + _, _, g1, _ := bls24315.Generators() + g1.Neg(&g1) + f, err := bls24315.PairingCheck([]bls24315.G1Affine{g1, publicKey.A}, []bls24315.G2Affine{sig.S, H}) + if err != nil { + return false, err + } + + return f, nil + +} diff --git a/ecc/bls24-315/signatures/bls/bls_test.go b/ecc/bls24-315/signatures/bls/bls_test.go new file mode 100644 index 000000000..f0edb4545 --- /dev/null +++ b/ecc/bls24-315/signatures/bls/bls_test.go @@ -0,0 +1,74 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestBLS(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS24-315] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing BLS") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking BLS sign()") + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, nil) + } +} + +func BenchmarkVerifyBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking BLS sign()") + sig, _ := privKey.Sign(msg, nil) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, nil) + } +} diff --git a/ecc/bls24-315/signatures/bls/doc.go b/ecc/bls24-315/signatures/bls/doc.go new file mode 100644 index 000000000..3d7b572ad --- /dev/null +++ b/ecc/bls24-315/signatures/bls/doc.go @@ -0,0 +1,22 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package bls provides BLS signature scheme on the bls24-315 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/BLS_digital_signature +// - IETF: https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/05/ +package bls diff --git a/ecc/bls24-315/signatures/bls/marshal.go b/ecc/bls24-315/signatures/bls/marshal.go new file mode 100644 index 000000000..6f4eccc43 --- /dev/null +++ b/ecc/bls24-315/signatures/bls/marshal.go @@ -0,0 +1,104 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFp (G2 compressef encoding) +func (sig *Signature) Bytes() []byte { + res := sig.S.Bytes() + return res[:sizeSignature] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + sig.S.SetBytes(buf) + n += sizeFr + return n, nil +} diff --git a/ecc/bls24-315/signatures/bls/marshal_test.go b/ecc/bls24-315/signatures/bls/marshal_test.go new file mode 100644 index 000000000..2c6196f3a --- /dev/null +++ b/ecc/bls24-315/signatures/bls/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS24-315] BLS serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bls24-315/signature/ecdsa/doc.go b/ecc/bls24-315/signatures/ecdsa/doc.go similarity index 100% rename from ecc/bls24-315/signature/ecdsa/doc.go rename to ecc/bls24-315/signatures/ecdsa/doc.go diff --git a/ecc/bls24-315/signature/ecdsa/ecdsa.go b/ecc/bls24-315/signatures/ecdsa/ecdsa.go similarity index 100% rename from ecc/bls24-315/signature/ecdsa/ecdsa.go rename to ecc/bls24-315/signatures/ecdsa/ecdsa.go diff --git a/ecc/bls24-315/signature/ecdsa/ecdsa_test.go b/ecc/bls24-315/signatures/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls24-315/signature/ecdsa/ecdsa_test.go rename to ecc/bls24-315/signatures/ecdsa/ecdsa_test.go diff --git a/ecc/bls24-315/signature/ecdsa/marshal.go b/ecc/bls24-315/signatures/ecdsa/marshal.go similarity index 100% rename from ecc/bls24-315/signature/ecdsa/marshal.go rename to ecc/bls24-315/signatures/ecdsa/marshal.go diff --git a/ecc/bls24-315/signature/ecdsa/marshal_test.go b/ecc/bls24-315/signatures/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls24-315/signature/ecdsa/marshal_test.go rename to ecc/bls24-315/signatures/ecdsa/marshal_test.go diff --git a/ecc/bls24-315/signature/schnorr/doc.go b/ecc/bls24-315/signatures/schnorr/doc.go similarity index 100% rename from ecc/bls24-315/signature/schnorr/doc.go rename to ecc/bls24-315/signatures/schnorr/doc.go diff --git a/ecc/bls24-315/signature/schnorr/marshal.go b/ecc/bls24-315/signatures/schnorr/marshal.go similarity index 100% rename from ecc/bls24-315/signature/schnorr/marshal.go rename to ecc/bls24-315/signatures/schnorr/marshal.go diff --git a/ecc/bls24-315/signature/schnorr/marshal_test.go b/ecc/bls24-315/signatures/schnorr/marshal_test.go similarity index 100% rename from ecc/bls24-315/signature/schnorr/marshal_test.go rename to ecc/bls24-315/signatures/schnorr/marshal_test.go diff --git a/ecc/bls24-315/signature/schnorr/schnorr.go b/ecc/bls24-315/signatures/schnorr/schnorr.go similarity index 100% rename from ecc/bls24-315/signature/schnorr/schnorr.go rename to ecc/bls24-315/signatures/schnorr/schnorr.go diff --git a/ecc/bls24-315/signature/schnorr/schnorr_test.go b/ecc/bls24-315/signatures/schnorr/schnorr_test.go similarity index 100% rename from ecc/bls24-315/signature/schnorr/schnorr_test.go rename to ecc/bls24-315/signatures/schnorr/schnorr_test.go diff --git a/ecc/bls24-317/signatures/bls/bls.go b/ecc/bls24-317/signatures/bls/bls.go new file mode 100644 index 000000000..97c6d1ea7 --- /dev/null +++ b/ecc/bls24-317/signatures/bls/bls.go @@ -0,0 +1,240 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls24-317" + "github.com/consensys/gnark-crypto/ecc/bls24-317/fp" + "github.com/consensys/gnark-crypto/ecc/bls24-317/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 4 * sizeFp +) + +var order = fr.Modulus() + +// PublicKey represents an BLS public key +type PublicKey struct { + A bls24317.G1Affine +} + +// PrivateKey represents an BLS private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an BLS signature +type Signature struct { + S bls24317.G2Affine +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bls24317.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the BLS signature +// +// H(m) ← m (hash to G₂) +// S = sk ⋅ H(m) ∈ G₂ +// signature = S +// +// hFunc should always be nil. +// Hashing the message first with hFunc is not needed, as it is included in HashToG2. +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + // Hash the message into G2 + dst := []byte("0x01") + H, err := bls24317.HashToG2(message, dst) + if err != nil { + return nil, err + } + + // Sign + var sig Signature + scalar := new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + sig.S.ScalarMultiplication(&H, scalar) + + return sig.Bytes(), nil +} + +// Verify validates the BLS signature +// +// e(G1, sig.S) ?= e(pk, G2) +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + // Hash the message into G2 + dst := []byte("0x01") + H, err := bls24317.HashToG2(message, dst) + if err != nil { + return false, err + } + + // Verify the signature + _, _, g1, _ := bls24317.Generators() + g1.Neg(&g1) + f, err := bls24317.PairingCheck([]bls24317.G1Affine{g1, publicKey.A}, []bls24317.G2Affine{sig.S, H}) + if err != nil { + return false, err + } + + return f, nil + +} diff --git a/ecc/bls24-317/signatures/bls/bls_test.go b/ecc/bls24-317/signatures/bls/bls_test.go new file mode 100644 index 000000000..8c2b8329b --- /dev/null +++ b/ecc/bls24-317/signatures/bls/bls_test.go @@ -0,0 +1,74 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestBLS(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS24-317] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing BLS") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking BLS sign()") + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, nil) + } +} + +func BenchmarkVerifyBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking BLS sign()") + sig, _ := privKey.Sign(msg, nil) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, nil) + } +} diff --git a/ecc/bls24-317/signatures/bls/doc.go b/ecc/bls24-317/signatures/bls/doc.go new file mode 100644 index 000000000..0c380bc38 --- /dev/null +++ b/ecc/bls24-317/signatures/bls/doc.go @@ -0,0 +1,22 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package bls provides BLS signature scheme on the bls24-317 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/BLS_digital_signature +// - IETF: https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/05/ +package bls diff --git a/ecc/bls24-317/signatures/bls/marshal.go b/ecc/bls24-317/signatures/bls/marshal.go new file mode 100644 index 000000000..6f4eccc43 --- /dev/null +++ b/ecc/bls24-317/signatures/bls/marshal.go @@ -0,0 +1,104 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFp (G2 compressef encoding) +func (sig *Signature) Bytes() []byte { + res := sig.S.Bytes() + return res[:sizeSignature] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + sig.S.SetBytes(buf) + n += sizeFr + return n, nil +} diff --git a/ecc/bls24-317/signatures/bls/marshal_test.go b/ecc/bls24-317/signatures/bls/marshal_test.go new file mode 100644 index 000000000..ab98b2038 --- /dev/null +++ b/ecc/bls24-317/signatures/bls/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BLS24-317] BLS serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bls24-317/signature/ecdsa/doc.go b/ecc/bls24-317/signatures/ecdsa/doc.go similarity index 100% rename from ecc/bls24-317/signature/ecdsa/doc.go rename to ecc/bls24-317/signatures/ecdsa/doc.go diff --git a/ecc/bls24-317/signature/ecdsa/ecdsa.go b/ecc/bls24-317/signatures/ecdsa/ecdsa.go similarity index 100% rename from ecc/bls24-317/signature/ecdsa/ecdsa.go rename to ecc/bls24-317/signatures/ecdsa/ecdsa.go diff --git a/ecc/bls24-317/signature/ecdsa/ecdsa_test.go b/ecc/bls24-317/signatures/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls24-317/signature/ecdsa/ecdsa_test.go rename to ecc/bls24-317/signatures/ecdsa/ecdsa_test.go diff --git a/ecc/bls24-317/signature/ecdsa/marshal.go b/ecc/bls24-317/signatures/ecdsa/marshal.go similarity index 100% rename from ecc/bls24-317/signature/ecdsa/marshal.go rename to ecc/bls24-317/signatures/ecdsa/marshal.go diff --git a/ecc/bls24-317/signature/ecdsa/marshal_test.go b/ecc/bls24-317/signatures/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls24-317/signature/ecdsa/marshal_test.go rename to ecc/bls24-317/signatures/ecdsa/marshal_test.go diff --git a/ecc/bls24-317/signature/schnorr/doc.go b/ecc/bls24-317/signatures/schnorr/doc.go similarity index 100% rename from ecc/bls24-317/signature/schnorr/doc.go rename to ecc/bls24-317/signatures/schnorr/doc.go diff --git a/ecc/bls24-317/signature/schnorr/marshal.go b/ecc/bls24-317/signatures/schnorr/marshal.go similarity index 100% rename from ecc/bls24-317/signature/schnorr/marshal.go rename to ecc/bls24-317/signatures/schnorr/marshal.go diff --git a/ecc/bls24-317/signature/schnorr/marshal_test.go b/ecc/bls24-317/signatures/schnorr/marshal_test.go similarity index 100% rename from ecc/bls24-317/signature/schnorr/marshal_test.go rename to ecc/bls24-317/signatures/schnorr/marshal_test.go diff --git a/ecc/bls24-317/signature/schnorr/schnorr.go b/ecc/bls24-317/signatures/schnorr/schnorr.go similarity index 100% rename from ecc/bls24-317/signature/schnorr/schnorr.go rename to ecc/bls24-317/signatures/schnorr/schnorr.go diff --git a/ecc/bls24-317/signature/schnorr/schnorr_test.go b/ecc/bls24-317/signatures/schnorr/schnorr_test.go similarity index 100% rename from ecc/bls24-317/signature/schnorr/schnorr_test.go rename to ecc/bls24-317/signatures/schnorr/schnorr_test.go diff --git a/ecc/bn254/signatures/bls/bls.go b/ecc/bn254/signatures/bls/bls.go new file mode 100644 index 000000000..59b90373a --- /dev/null +++ b/ecc/bn254/signatures/bls/bls.go @@ -0,0 +1,240 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 2 * sizeFp +) + +var order = fr.Modulus() + +// PublicKey represents an BLS public key +type PublicKey struct { + A bn254.G1Affine +} + +// PrivateKey represents an BLS private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an BLS signature +type Signature struct { + S bn254.G2Affine +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bn254.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the BLS signature +// +// H(m) ← m (hash to G₂) +// S = sk ⋅ H(m) ∈ G₂ +// signature = S +// +// hFunc should always be nil. +// Hashing the message first with hFunc is not needed, as it is included in HashToG2. +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + // Hash the message into G2 + dst := []byte("0x01") + H, err := bn254.HashToG2(message, dst) + if err != nil { + return nil, err + } + + // Sign + var sig Signature + scalar := new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + sig.S.ScalarMultiplication(&H, scalar) + + return sig.Bytes(), nil +} + +// Verify validates the BLS signature +// +// e(G1, sig.S) ?= e(pk, G2) +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + // Hash the message into G2 + dst := []byte("0x01") + H, err := bn254.HashToG2(message, dst) + if err != nil { + return false, err + } + + // Verify the signature + _, _, g1, _ := bn254.Generators() + g1.Neg(&g1) + f, err := bn254.PairingCheck([]bn254.G1Affine{g1, publicKey.A}, []bn254.G2Affine{sig.S, H}) + if err != nil { + return false, err + } + + return f, nil + +} diff --git a/ecc/bn254/signatures/bls/bls_test.go b/ecc/bn254/signatures/bls/bls_test.go new file mode 100644 index 000000000..ff646c3d2 --- /dev/null +++ b/ecc/bn254/signatures/bls/bls_test.go @@ -0,0 +1,74 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestBLS(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BN254] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing BLS") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking BLS sign()") + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, nil) + } +} + +func BenchmarkVerifyBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking BLS sign()") + sig, _ := privKey.Sign(msg, nil) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, nil) + } +} diff --git a/ecc/bn254/signatures/bls/doc.go b/ecc/bn254/signatures/bls/doc.go new file mode 100644 index 000000000..df8a855e4 --- /dev/null +++ b/ecc/bn254/signatures/bls/doc.go @@ -0,0 +1,22 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package bls provides BLS signature scheme on the bn254 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/BLS_digital_signature +// - IETF: https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/05/ +package bls diff --git a/ecc/bn254/signatures/bls/marshal.go b/ecc/bn254/signatures/bls/marshal.go new file mode 100644 index 000000000..6f4eccc43 --- /dev/null +++ b/ecc/bn254/signatures/bls/marshal.go @@ -0,0 +1,104 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFp (G2 compressef encoding) +func (sig *Signature) Bytes() []byte { + res := sig.S.Bytes() + return res[:sizeSignature] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + sig.S.SetBytes(buf) + n += sizeFr + return n, nil +} diff --git a/ecc/bn254/signatures/bls/marshal_test.go b/ecc/bn254/signatures/bls/marshal_test.go new file mode 100644 index 000000000..40ebb3d43 --- /dev/null +++ b/ecc/bn254/signatures/bls/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BN254] BLS serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bn254/signature/ecdsa/doc.go b/ecc/bn254/signatures/ecdsa/doc.go similarity index 100% rename from ecc/bn254/signature/ecdsa/doc.go rename to ecc/bn254/signatures/ecdsa/doc.go diff --git a/ecc/bn254/signature/ecdsa/ecdsa.go b/ecc/bn254/signatures/ecdsa/ecdsa.go similarity index 100% rename from ecc/bn254/signature/ecdsa/ecdsa.go rename to ecc/bn254/signatures/ecdsa/ecdsa.go diff --git a/ecc/bn254/signature/ecdsa/ecdsa_test.go b/ecc/bn254/signatures/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bn254/signature/ecdsa/ecdsa_test.go rename to ecc/bn254/signatures/ecdsa/ecdsa_test.go diff --git a/ecc/bn254/signature/ecdsa/marshal.go b/ecc/bn254/signatures/ecdsa/marshal.go similarity index 100% rename from ecc/bn254/signature/ecdsa/marshal.go rename to ecc/bn254/signatures/ecdsa/marshal.go diff --git a/ecc/bn254/signature/ecdsa/marshal_test.go b/ecc/bn254/signatures/ecdsa/marshal_test.go similarity index 100% rename from ecc/bn254/signature/ecdsa/marshal_test.go rename to ecc/bn254/signatures/ecdsa/marshal_test.go diff --git a/ecc/bn254/signature/schnorr/doc.go b/ecc/bn254/signatures/schnorr/doc.go similarity index 100% rename from ecc/bn254/signature/schnorr/doc.go rename to ecc/bn254/signatures/schnorr/doc.go diff --git a/ecc/bn254/signature/schnorr/marshal.go b/ecc/bn254/signatures/schnorr/marshal.go similarity index 100% rename from ecc/bn254/signature/schnorr/marshal.go rename to ecc/bn254/signatures/schnorr/marshal.go diff --git a/ecc/bn254/signature/schnorr/marshal_test.go b/ecc/bn254/signatures/schnorr/marshal_test.go similarity index 100% rename from ecc/bn254/signature/schnorr/marshal_test.go rename to ecc/bn254/signatures/schnorr/marshal_test.go diff --git a/ecc/bn254/signature/schnorr/schnorr.go b/ecc/bn254/signatures/schnorr/schnorr.go similarity index 100% rename from ecc/bn254/signature/schnorr/schnorr.go rename to ecc/bn254/signatures/schnorr/schnorr.go diff --git a/ecc/bn254/signature/schnorr/schnorr_test.go b/ecc/bn254/signatures/schnorr/schnorr_test.go similarity index 100% rename from ecc/bn254/signature/schnorr/schnorr_test.go rename to ecc/bn254/signatures/schnorr/schnorr_test.go diff --git a/ecc/bw6-633/signatures/bls/bls.go b/ecc/bw6-633/signatures/bls/bls.go new file mode 100644 index 000000000..28d2ed07c --- /dev/null +++ b/ecc/bw6-633/signatures/bls/bls.go @@ -0,0 +1,240 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bw6-633" + "github.com/consensys/gnark-crypto/ecc/bw6-633/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-633/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 1 * sizeFp +) + +var order = fr.Modulus() + +// PublicKey represents an BLS public key +type PublicKey struct { + A bw6633.G1Affine +} + +// PrivateKey represents an BLS private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an BLS signature +type Signature struct { + S bw6633.G2Affine +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bw6633.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the BLS signature +// +// H(m) ← m (hash to G₂) +// S = sk ⋅ H(m) ∈ G₂ +// signature = S +// +// hFunc should always be nil. +// Hashing the message first with hFunc is not needed, as it is included in HashToG2. +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + // Hash the message into G2 + dst := []byte("0x01") + H, err := bw6633.HashToG2(message, dst) + if err != nil { + return nil, err + } + + // Sign + var sig Signature + scalar := new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + sig.S.ScalarMultiplication(&H, scalar) + + return sig.Bytes(), nil +} + +// Verify validates the BLS signature +// +// e(G1, sig.S) ?= e(pk, G2) +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + // Hash the message into G2 + dst := []byte("0x01") + H, err := bw6633.HashToG2(message, dst) + if err != nil { + return false, err + } + + // Verify the signature + _, _, g1, _ := bw6633.Generators() + g1.Neg(&g1) + f, err := bw6633.PairingCheck([]bw6633.G1Affine{g1, publicKey.A}, []bw6633.G2Affine{sig.S, H}) + if err != nil { + return false, err + } + + return f, nil + +} diff --git a/ecc/bw6-633/signatures/bls/bls_test.go b/ecc/bw6-633/signatures/bls/bls_test.go new file mode 100644 index 000000000..833f9e657 --- /dev/null +++ b/ecc/bw6-633/signatures/bls/bls_test.go @@ -0,0 +1,74 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestBLS(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-633] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing BLS") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking BLS sign()") + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, nil) + } +} + +func BenchmarkVerifyBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking BLS sign()") + sig, _ := privKey.Sign(msg, nil) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, nil) + } +} diff --git a/ecc/bw6-633/signatures/bls/doc.go b/ecc/bw6-633/signatures/bls/doc.go new file mode 100644 index 000000000..ecdcd09ed --- /dev/null +++ b/ecc/bw6-633/signatures/bls/doc.go @@ -0,0 +1,22 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package bls provides BLS signature scheme on the bw6-633 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/BLS_digital_signature +// - IETF: https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/05/ +package bls diff --git a/ecc/bw6-633/signatures/bls/marshal.go b/ecc/bw6-633/signatures/bls/marshal.go new file mode 100644 index 000000000..6f4eccc43 --- /dev/null +++ b/ecc/bw6-633/signatures/bls/marshal.go @@ -0,0 +1,104 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFp (G2 compressef encoding) +func (sig *Signature) Bytes() []byte { + res := sig.S.Bytes() + return res[:sizeSignature] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + sig.S.SetBytes(buf) + n += sizeFr + return n, nil +} diff --git a/ecc/bw6-633/signatures/bls/marshal_test.go b/ecc/bw6-633/signatures/bls/marshal_test.go new file mode 100644 index 000000000..1031617f7 --- /dev/null +++ b/ecc/bw6-633/signatures/bls/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-633] BLS serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bw6-633/signature/ecdsa/doc.go b/ecc/bw6-633/signatures/ecdsa/doc.go similarity index 100% rename from ecc/bw6-633/signature/ecdsa/doc.go rename to ecc/bw6-633/signatures/ecdsa/doc.go diff --git a/ecc/bw6-633/signature/ecdsa/ecdsa.go b/ecc/bw6-633/signatures/ecdsa/ecdsa.go similarity index 100% rename from ecc/bw6-633/signature/ecdsa/ecdsa.go rename to ecc/bw6-633/signatures/ecdsa/ecdsa.go diff --git a/ecc/bw6-633/signature/ecdsa/ecdsa_test.go b/ecc/bw6-633/signatures/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bw6-633/signature/ecdsa/ecdsa_test.go rename to ecc/bw6-633/signatures/ecdsa/ecdsa_test.go diff --git a/ecc/bw6-633/signature/ecdsa/marshal.go b/ecc/bw6-633/signatures/ecdsa/marshal.go similarity index 100% rename from ecc/bw6-633/signature/ecdsa/marshal.go rename to ecc/bw6-633/signatures/ecdsa/marshal.go diff --git a/ecc/bw6-633/signature/ecdsa/marshal_test.go b/ecc/bw6-633/signatures/ecdsa/marshal_test.go similarity index 100% rename from ecc/bw6-633/signature/ecdsa/marshal_test.go rename to ecc/bw6-633/signatures/ecdsa/marshal_test.go diff --git a/ecc/bw6-633/signature/schnorr/doc.go b/ecc/bw6-633/signatures/schnorr/doc.go similarity index 100% rename from ecc/bw6-633/signature/schnorr/doc.go rename to ecc/bw6-633/signatures/schnorr/doc.go diff --git a/ecc/bw6-633/signature/schnorr/marshal.go b/ecc/bw6-633/signatures/schnorr/marshal.go similarity index 100% rename from ecc/bw6-633/signature/schnorr/marshal.go rename to ecc/bw6-633/signatures/schnorr/marshal.go diff --git a/ecc/bw6-633/signature/schnorr/marshal_test.go b/ecc/bw6-633/signatures/schnorr/marshal_test.go similarity index 100% rename from ecc/bw6-633/signature/schnorr/marshal_test.go rename to ecc/bw6-633/signatures/schnorr/marshal_test.go diff --git a/ecc/bw6-633/signature/schnorr/schnorr.go b/ecc/bw6-633/signatures/schnorr/schnorr.go similarity index 100% rename from ecc/bw6-633/signature/schnorr/schnorr.go rename to ecc/bw6-633/signatures/schnorr/schnorr.go diff --git a/ecc/bw6-633/signature/schnorr/schnorr_test.go b/ecc/bw6-633/signatures/schnorr/schnorr_test.go similarity index 100% rename from ecc/bw6-633/signature/schnorr/schnorr_test.go rename to ecc/bw6-633/signatures/schnorr/schnorr_test.go diff --git a/ecc/bw6-756/signatures/bls/bls.go b/ecc/bw6-756/signatures/bls/bls.go new file mode 100644 index 000000000..76c6356b6 --- /dev/null +++ b/ecc/bw6-756/signatures/bls/bls.go @@ -0,0 +1,240 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bw6-756" + "github.com/consensys/gnark-crypto/ecc/bw6-756/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-756/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 1 * sizeFp +) + +var order = fr.Modulus() + +// PublicKey represents an BLS public key +type PublicKey struct { + A bw6756.G1Affine +} + +// PrivateKey represents an BLS private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an BLS signature +type Signature struct { + S bw6756.G2Affine +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bw6756.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the BLS signature +// +// H(m) ← m (hash to G₂) +// S = sk ⋅ H(m) ∈ G₂ +// signature = S +// +// hFunc should always be nil. +// Hashing the message first with hFunc is not needed, as it is included in HashToG2. +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + // Hash the message into G2 + dst := []byte("0x01") + H, err := bw6756.HashToG2(message, dst) + if err != nil { + return nil, err + } + + // Sign + var sig Signature + scalar := new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + sig.S.ScalarMultiplication(&H, scalar) + + return sig.Bytes(), nil +} + +// Verify validates the BLS signature +// +// e(G1, sig.S) ?= e(pk, G2) +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + // Hash the message into G2 + dst := []byte("0x01") + H, err := bw6756.HashToG2(message, dst) + if err != nil { + return false, err + } + + // Verify the signature + _, _, g1, _ := bw6756.Generators() + g1.Neg(&g1) + f, err := bw6756.PairingCheck([]bw6756.G1Affine{g1, publicKey.A}, []bw6756.G2Affine{sig.S, H}) + if err != nil { + return false, err + } + + return f, nil + +} diff --git a/ecc/bw6-756/signatures/bls/bls_test.go b/ecc/bw6-756/signatures/bls/bls_test.go new file mode 100644 index 000000000..b75fee539 --- /dev/null +++ b/ecc/bw6-756/signatures/bls/bls_test.go @@ -0,0 +1,74 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestBLS(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-756] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing BLS") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking BLS sign()") + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, nil) + } +} + +func BenchmarkVerifyBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking BLS sign()") + sig, _ := privKey.Sign(msg, nil) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, nil) + } +} diff --git a/ecc/bw6-756/signatures/bls/doc.go b/ecc/bw6-756/signatures/bls/doc.go new file mode 100644 index 000000000..728ef793e --- /dev/null +++ b/ecc/bw6-756/signatures/bls/doc.go @@ -0,0 +1,22 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package bls provides BLS signature scheme on the bw6-756 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/BLS_digital_signature +// - IETF: https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/05/ +package bls diff --git a/ecc/bw6-756/signatures/bls/marshal.go b/ecc/bw6-756/signatures/bls/marshal.go new file mode 100644 index 000000000..6f4eccc43 --- /dev/null +++ b/ecc/bw6-756/signatures/bls/marshal.go @@ -0,0 +1,104 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFp (G2 compressef encoding) +func (sig *Signature) Bytes() []byte { + res := sig.S.Bytes() + return res[:sizeSignature] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + sig.S.SetBytes(buf) + n += sizeFr + return n, nil +} diff --git a/ecc/bw6-756/signatures/bls/marshal_test.go b/ecc/bw6-756/signatures/bls/marshal_test.go new file mode 100644 index 000000000..4e1b81eaf --- /dev/null +++ b/ecc/bw6-756/signatures/bls/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-756] BLS serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bw6-756/signature/ecdsa/doc.go b/ecc/bw6-756/signatures/ecdsa/doc.go similarity index 100% rename from ecc/bw6-756/signature/ecdsa/doc.go rename to ecc/bw6-756/signatures/ecdsa/doc.go diff --git a/ecc/bw6-756/signature/ecdsa/ecdsa.go b/ecc/bw6-756/signatures/ecdsa/ecdsa.go similarity index 100% rename from ecc/bw6-756/signature/ecdsa/ecdsa.go rename to ecc/bw6-756/signatures/ecdsa/ecdsa.go diff --git a/ecc/bw6-756/signature/ecdsa/ecdsa_test.go b/ecc/bw6-756/signatures/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bw6-756/signature/ecdsa/ecdsa_test.go rename to ecc/bw6-756/signatures/ecdsa/ecdsa_test.go diff --git a/ecc/bw6-756/signature/ecdsa/marshal.go b/ecc/bw6-756/signatures/ecdsa/marshal.go similarity index 100% rename from ecc/bw6-756/signature/ecdsa/marshal.go rename to ecc/bw6-756/signatures/ecdsa/marshal.go diff --git a/ecc/bw6-756/signature/ecdsa/marshal_test.go b/ecc/bw6-756/signatures/ecdsa/marshal_test.go similarity index 100% rename from ecc/bw6-756/signature/ecdsa/marshal_test.go rename to ecc/bw6-756/signatures/ecdsa/marshal_test.go diff --git a/ecc/bw6-756/signature/schnorr/doc.go b/ecc/bw6-756/signatures/schnorr/doc.go similarity index 100% rename from ecc/bw6-756/signature/schnorr/doc.go rename to ecc/bw6-756/signatures/schnorr/doc.go diff --git a/ecc/bw6-756/signature/schnorr/marshal.go b/ecc/bw6-756/signatures/schnorr/marshal.go similarity index 100% rename from ecc/bw6-756/signature/schnorr/marshal.go rename to ecc/bw6-756/signatures/schnorr/marshal.go diff --git a/ecc/bw6-756/signature/schnorr/marshal_test.go b/ecc/bw6-756/signatures/schnorr/marshal_test.go similarity index 100% rename from ecc/bw6-756/signature/schnorr/marshal_test.go rename to ecc/bw6-756/signatures/schnorr/marshal_test.go diff --git a/ecc/bw6-756/signature/schnorr/schnorr.go b/ecc/bw6-756/signatures/schnorr/schnorr.go similarity index 100% rename from ecc/bw6-756/signature/schnorr/schnorr.go rename to ecc/bw6-756/signatures/schnorr/schnorr.go diff --git a/ecc/bw6-756/signature/schnorr/schnorr_test.go b/ecc/bw6-756/signatures/schnorr/schnorr_test.go similarity index 100% rename from ecc/bw6-756/signature/schnorr/schnorr_test.go rename to ecc/bw6-756/signatures/schnorr/schnorr_test.go diff --git a/ecc/bw6-761/signatures/bls/bls.go b/ecc/bw6-761/signatures/bls/bls.go new file mode 100644 index 000000000..5f1f13676 --- /dev/null +++ b/ecc/bw6-761/signatures/bls/bls.go @@ -0,0 +1,240 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bw6-761" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = 1 * sizeFp +) + +var order = fr.Modulus() + +// PublicKey represents an BLS public key +type PublicKey struct { + A bw6761.G1Affine +} + +// PrivateKey represents an BLS private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an BLS signature +type Signature struct { + S bw6761.G2Affine +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + _, _, g, _ := bw6761.Generators() + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the BLS signature +// +// H(m) ← m (hash to G₂) +// S = sk ⋅ H(m) ∈ G₂ +// signature = S +// +// hFunc should always be nil. +// Hashing the message first with hFunc is not needed, as it is included in HashToG2. +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + // Hash the message into G2 + dst := []byte("0x01") + H, err := bw6761.HashToG2(message, dst) + if err != nil { + return nil, err + } + + // Sign + var sig Signature + scalar := new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + sig.S.ScalarMultiplication(&H, scalar) + + return sig.Bytes(), nil +} + +// Verify validates the BLS signature +// +// e(G1, sig.S) ?= e(pk, G2) +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + // Hash the message into G2 + dst := []byte("0x01") + H, err := bw6761.HashToG2(message, dst) + if err != nil { + return false, err + } + + // Verify the signature + _, _, g1, _ := bw6761.Generators() + g1.Neg(&g1) + f, err := bw6761.PairingCheck([]bw6761.G1Affine{g1, publicKey.A}, []bw6761.G2Affine{sig.S, H}) + if err != nil { + return false, err + } + + return f, nil + +} diff --git a/ecc/bw6-761/signatures/bls/bls_test.go b/ecc/bw6-761/signatures/bls/bls_test.go new file mode 100644 index 000000000..81234637e --- /dev/null +++ b/ecc/bw6-761/signatures/bls/bls_test.go @@ -0,0 +1,74 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestBLS(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-761] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing BLS") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking BLS sign()") + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, nil) + } +} + +func BenchmarkVerifyBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking BLS sign()") + sig, _ := privKey.Sign(msg, nil) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, nil) + } +} diff --git a/ecc/bw6-761/signatures/bls/doc.go b/ecc/bw6-761/signatures/bls/doc.go new file mode 100644 index 000000000..6d6e72182 --- /dev/null +++ b/ecc/bw6-761/signatures/bls/doc.go @@ -0,0 +1,22 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// Package bls provides BLS signature scheme on the bw6-761 curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/BLS_digital_signature +// - IETF: https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/05/ +package bls diff --git a/ecc/bw6-761/signatures/bls/marshal.go b/ecc/bw6-761/signatures/bls/marshal.go new file mode 100644 index 000000000..6f4eccc43 --- /dev/null +++ b/ecc/bw6-761/signatures/bls/marshal.go @@ -0,0 +1,104 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte + pkBin := pk.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte + pubkBin := privKey.PublicKey.A.Bytes() + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFp (G2 compressef encoding) +func (sig *Signature) Bytes() []byte { + res := sig.S.Bytes() + return res[:sizeSignature] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + sig.S.SetBytes(buf) + n += sizeFr + return n, nil +} diff --git a/ecc/bw6-761/signatures/bls/marshal_test.go b/ecc/bw6-761/signatures/bls/marshal_test.go new file mode 100644 index 000000000..cd2c2c574 --- /dev/null +++ b/ecc/bw6-761/signatures/bls/marshal_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls + +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[BW6-761] BLS serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/ecc/bw6-761/signature/ecdsa/doc.go b/ecc/bw6-761/signatures/ecdsa/doc.go similarity index 100% rename from ecc/bw6-761/signature/ecdsa/doc.go rename to ecc/bw6-761/signatures/ecdsa/doc.go diff --git a/ecc/bw6-761/signature/ecdsa/ecdsa.go b/ecc/bw6-761/signatures/ecdsa/ecdsa.go similarity index 100% rename from ecc/bw6-761/signature/ecdsa/ecdsa.go rename to ecc/bw6-761/signatures/ecdsa/ecdsa.go diff --git a/ecc/bw6-761/signature/ecdsa/ecdsa_test.go b/ecc/bw6-761/signatures/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bw6-761/signature/ecdsa/ecdsa_test.go rename to ecc/bw6-761/signatures/ecdsa/ecdsa_test.go diff --git a/ecc/bw6-761/signature/ecdsa/marshal.go b/ecc/bw6-761/signatures/ecdsa/marshal.go similarity index 100% rename from ecc/bw6-761/signature/ecdsa/marshal.go rename to ecc/bw6-761/signatures/ecdsa/marshal.go diff --git a/ecc/bw6-761/signature/ecdsa/marshal_test.go b/ecc/bw6-761/signatures/ecdsa/marshal_test.go similarity index 100% rename from ecc/bw6-761/signature/ecdsa/marshal_test.go rename to ecc/bw6-761/signatures/ecdsa/marshal_test.go diff --git a/ecc/bw6-761/signature/schnorr/doc.go b/ecc/bw6-761/signatures/schnorr/doc.go similarity index 100% rename from ecc/bw6-761/signature/schnorr/doc.go rename to ecc/bw6-761/signatures/schnorr/doc.go diff --git a/ecc/bw6-761/signature/schnorr/marshal.go b/ecc/bw6-761/signatures/schnorr/marshal.go similarity index 100% rename from ecc/bw6-761/signature/schnorr/marshal.go rename to ecc/bw6-761/signatures/schnorr/marshal.go diff --git a/ecc/bw6-761/signature/schnorr/marshal_test.go b/ecc/bw6-761/signatures/schnorr/marshal_test.go similarity index 100% rename from ecc/bw6-761/signature/schnorr/marshal_test.go rename to ecc/bw6-761/signatures/schnorr/marshal_test.go diff --git a/ecc/bw6-761/signature/schnorr/schnorr.go b/ecc/bw6-761/signatures/schnorr/schnorr.go similarity index 100% rename from ecc/bw6-761/signature/schnorr/schnorr.go rename to ecc/bw6-761/signatures/schnorr/schnorr.go diff --git a/ecc/bw6-761/signature/schnorr/schnorr_test.go b/ecc/bw6-761/signatures/schnorr/schnorr_test.go similarity index 100% rename from ecc/bw6-761/signature/schnorr/schnorr_test.go rename to ecc/bw6-761/signatures/schnorr/schnorr_test.go diff --git a/ecc/secp256k1/signature/ecdsa/doc.go b/ecc/secp256k1/signatures/ecdsa/doc.go similarity index 100% rename from ecc/secp256k1/signature/ecdsa/doc.go rename to ecc/secp256k1/signatures/ecdsa/doc.go diff --git a/ecc/secp256k1/signature/ecdsa/ecdsa.go b/ecc/secp256k1/signatures/ecdsa/ecdsa.go similarity index 100% rename from ecc/secp256k1/signature/ecdsa/ecdsa.go rename to ecc/secp256k1/signatures/ecdsa/ecdsa.go diff --git a/ecc/secp256k1/signature/ecdsa/ecdsa_test.go b/ecc/secp256k1/signatures/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/secp256k1/signature/ecdsa/ecdsa_test.go rename to ecc/secp256k1/signatures/ecdsa/ecdsa_test.go diff --git a/ecc/secp256k1/signature/ecdsa/marshal.go b/ecc/secp256k1/signatures/ecdsa/marshal.go similarity index 100% rename from ecc/secp256k1/signature/ecdsa/marshal.go rename to ecc/secp256k1/signatures/ecdsa/marshal.go diff --git a/ecc/secp256k1/signature/ecdsa/marshal_test.go b/ecc/secp256k1/signatures/ecdsa/marshal_test.go similarity index 100% rename from ecc/secp256k1/signature/ecdsa/marshal_test.go rename to ecc/secp256k1/signatures/ecdsa/marshal_test.go diff --git a/ecc/secp256k1/signature/schnorr/doc.go b/ecc/secp256k1/signatures/schnorr/doc.go similarity index 100% rename from ecc/secp256k1/signature/schnorr/doc.go rename to ecc/secp256k1/signatures/schnorr/doc.go diff --git a/ecc/secp256k1/signature/schnorr/marshal.go b/ecc/secp256k1/signatures/schnorr/marshal.go similarity index 100% rename from ecc/secp256k1/signature/schnorr/marshal.go rename to ecc/secp256k1/signatures/schnorr/marshal.go diff --git a/ecc/secp256k1/signature/schnorr/marshal_test.go b/ecc/secp256k1/signatures/schnorr/marshal_test.go similarity index 100% rename from ecc/secp256k1/signature/schnorr/marshal_test.go rename to ecc/secp256k1/signatures/schnorr/marshal_test.go diff --git a/ecc/secp256k1/signature/schnorr/schnorr.go b/ecc/secp256k1/signatures/schnorr/schnorr.go similarity index 100% rename from ecc/secp256k1/signature/schnorr/schnorr.go rename to ecc/secp256k1/signatures/schnorr/schnorr.go diff --git a/ecc/secp256k1/signature/schnorr/schnorr_test.go b/ecc/secp256k1/signatures/schnorr/schnorr_test.go similarity index 100% rename from ecc/secp256k1/signature/schnorr/schnorr_test.go rename to ecc/secp256k1/signatures/schnorr/schnorr_test.go diff --git a/ecc/stark-curve/signature/ecdsa/doc.go b/ecc/stark-curve/signatures/ecdsa/doc.go similarity index 100% rename from ecc/stark-curve/signature/ecdsa/doc.go rename to ecc/stark-curve/signatures/ecdsa/doc.go diff --git a/ecc/stark-curve/signature/ecdsa/ecdsa.go b/ecc/stark-curve/signatures/ecdsa/ecdsa.go similarity index 100% rename from ecc/stark-curve/signature/ecdsa/ecdsa.go rename to ecc/stark-curve/signatures/ecdsa/ecdsa.go diff --git a/ecc/stark-curve/signature/ecdsa/ecdsa_test.go b/ecc/stark-curve/signatures/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/stark-curve/signature/ecdsa/ecdsa_test.go rename to ecc/stark-curve/signatures/ecdsa/ecdsa_test.go diff --git a/ecc/stark-curve/signature/ecdsa/marshal.go b/ecc/stark-curve/signatures/ecdsa/marshal.go similarity index 100% rename from ecc/stark-curve/signature/ecdsa/marshal.go rename to ecc/stark-curve/signatures/ecdsa/marshal.go diff --git a/ecc/stark-curve/signature/ecdsa/marshal_test.go b/ecc/stark-curve/signatures/ecdsa/marshal_test.go similarity index 100% rename from ecc/stark-curve/signature/ecdsa/marshal_test.go rename to ecc/stark-curve/signatures/ecdsa/marshal_test.go diff --git a/ecc/stark-curve/signature/schnorr/doc.go b/ecc/stark-curve/signatures/schnorr/doc.go similarity index 100% rename from ecc/stark-curve/signature/schnorr/doc.go rename to ecc/stark-curve/signatures/schnorr/doc.go diff --git a/ecc/stark-curve/signature/schnorr/marshal.go b/ecc/stark-curve/signatures/schnorr/marshal.go similarity index 100% rename from ecc/stark-curve/signature/schnorr/marshal.go rename to ecc/stark-curve/signatures/schnorr/marshal.go diff --git a/ecc/stark-curve/signature/schnorr/marshal_test.go b/ecc/stark-curve/signatures/schnorr/marshal_test.go similarity index 100% rename from ecc/stark-curve/signature/schnorr/marshal_test.go rename to ecc/stark-curve/signatures/schnorr/marshal_test.go diff --git a/ecc/stark-curve/signature/schnorr/schnorr.go b/ecc/stark-curve/signatures/schnorr/schnorr.go similarity index 100% rename from ecc/stark-curve/signature/schnorr/schnorr.go rename to ecc/stark-curve/signatures/schnorr/schnorr.go diff --git a/ecc/stark-curve/signature/schnorr/schnorr_test.go b/ecc/stark-curve/signatures/schnorr/schnorr_test.go similarity index 100% rename from ecc/stark-curve/signature/schnorr/schnorr_test.go rename to ecc/stark-curve/signatures/schnorr/schnorr_test.go diff --git a/internal/generator/main.go b/internal/generator/main.go index c45fd536b..e2e0d98dd 100644 --- a/internal/generator/main.go +++ b/internal/generator/main.go @@ -24,6 +24,7 @@ import ( "github.com/consensys/gnark-crypto/internal/generator/permutation" "github.com/consensys/gnark-crypto/internal/generator/plookup" "github.com/consensys/gnark-crypto/internal/generator/polynomial" + "github.com/consensys/gnark-crypto/internal/generator/signature/bls" "github.com/consensys/gnark-crypto/internal/generator/signature/ecdsa" "github.com/consensys/gnark-crypto/internal/generator/signature/schnorr" "github.com/consensys/gnark-crypto/internal/generator/sumcheck" @@ -70,10 +71,10 @@ func main() { } // generate ecdsa signature - assertNoError(ecdsa.Generate(conf, filepath.Join(curveDir, "signature"), bgen)) + assertNoError(ecdsa.Generate(conf, filepath.Join(curveDir, "signatures"), bgen)) // generate schnorr signature - assertNoError(schnorr.Generate(conf, filepath.Join(curveDir, "signature"), bgen)) + assertNoError(schnorr.Generate(conf, filepath.Join(curveDir, "signatures"), bgen)) if conf.Equal(config.STARK_CURVE) { return // TODO @yelhousni @@ -86,6 +87,9 @@ func main() { return } + // generate bls signature + assertNoError(bls.Generate(conf, filepath.Join(curveDir, "signatures"), bgen)) + // generate tower of extension assertNoError(tower.Generate(conf, filepath.Join(curveDir, "internal", "fptower"), bgen)) diff --git a/internal/generator/signature/bls/generate.go b/internal/generator/signature/bls/generate.go new file mode 100644 index 000000000..dd98ac567 --- /dev/null +++ b/internal/generator/signature/bls/generate.go @@ -0,0 +1,24 @@ +package bls + +import ( + "path/filepath" + + "github.com/consensys/bavard" + "github.com/consensys/gnark-crypto/internal/generator/config" +) + +func Generate(conf config.Curve, baseDir string, bgen *bavard.BatchGenerator) error { + // bls + conf.Package = "bls" + baseDir = filepath.Join(baseDir, conf.Package) + + entries := []bavard.Entry{ + {File: filepath.Join(baseDir, "doc.go"), Templates: []string{"doc.go.tmpl"}}, + {File: filepath.Join(baseDir, "bls.go"), Templates: []string{"bls.go.tmpl"}}, + {File: filepath.Join(baseDir, "bls_test.go"), Templates: []string{"bls.test.go.tmpl"}}, + {File: filepath.Join(baseDir, "marshal.go"), Templates: []string{"marshal.go.tmpl"}}, + {File: filepath.Join(baseDir, "marshal_test.go"), Templates: []string{"marshal.test.go.tmpl"}}, + } + return bgen.Generate(conf, conf.Package, "./signature/bls/template", entries...) + +} diff --git a/internal/generator/signature/bls/template/bls.go.tmpl b/internal/generator/signature/bls/template/bls.go.tmpl new file mode 100644 index 000000000..a8dcdf8d5 --- /dev/null +++ b/internal/generator/signature/bls/template/bls.go.tmpl @@ -0,0 +1,227 @@ +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "hash" + "io" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/{{ .Name }}" + "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr" + "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fp" + "github.com/consensys/gnark-crypto/signature" +) + +var errInvalidSig = errors.New("invalid signature") + +const ( + sizeFr = fr.Bytes + sizeFp = fp.Bytes + sizePublicKey = sizeFp + sizePrivateKey = sizeFr + sizePublicKey + sizeSignature = {{ .G2.CoordExtDegree}} * sizeFp +) + +var order = fr.Modulus() + +// PublicKey represents an BLS public key +type PublicKey struct { + A {{ .CurvePackage }}.G1Affine +} + +// PrivateKey represents an BLS private key +type PrivateKey struct { + PublicKey PublicKey + scalar [sizeFr]byte // secret scalar, in big Endian +} + +// Signature represents an BLS signature +type Signature struct { + S {{ .CurvePackage }}.G2Affine +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the order of the given +// curve using the procedure given in FIPS 186-4, Appendix B.5.1. +func randFieldElement(rand io.Reader) (k *big.Int, err error) { + b := make([]byte, fr.Bits/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(order, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(rand io.Reader) (*PrivateKey, error) { + + k, err := randFieldElement(rand) + if err != nil { + return nil, err + + } + + {{- if or (eq .Name "secp256k1") (eq .Name "stark-curve")}} + _, g := {{ .CurvePackage }}.Generators() + {{- else}} + _, _, g, _ := {{ .CurvePackage }}.Generators() + {{- end}} + + privateKey := new(PrivateKey) + k.FillBytes(privateKey.scalar[:sizeFr]) + privateKey.PublicKey.A.ScalarMultiplication(&g, k) + return privateKey, nil +} + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > sizeFr { + hash = hash[:sizeFr] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - sizeFr + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +type zr struct{} + +// Read replaces the contents of dst with zeros. It is safe for concurrent use. +func (zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = zr{} + +const ( + aesIV = "gnark-crypto IV." // must be 16 chars (equal block size) +) + +func nonce(privateKey *PrivateKey, hash []byte) (csprng *cipher.StreamReader, err error) { + // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: + // + // SHA2-512(privateKey.scalar ∥ entropy ∥ hash)[:32] + // + // The CSPRNG key is indifferentiable from a random oracle as shown in + // [Coron], the AES-CTR stream is indifferentiable from a random oracle + // under standard cryptographic assumptions (see [Larsson] for examples). + // + // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf + // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf + + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, entropy) + if err != nil { + return + + } + + // Initialize an SHA-512 hash context; digest... + md := sha512.New() + md.Write(privateKey.scalar[:sizeFr]) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, _ := aes.NewCipher(key) + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng = &cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + return csprng, err +} + +// Equal compares 2 public keys +func (pub *PublicKey) Equal(x signature.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + bpk := pub.Bytes() + bxx := xx.Bytes() + return subtle.ConstantTimeCompare(bpk, bxx) == 1 +} + +// Public returns the public key associated to the private key. +func (privKey *PrivateKey) Public() signature.PublicKey { + var pub PublicKey + pub.A.Set(&privKey.PublicKey.A) + return &pub +} + +// Sign performs the BLS signature +// +// H(m) ← m (hash to G₂) +// S = sk ⋅ H(m) ∈ G₂ +// signature = S +// +// hFunc should always be nil. +// Hashing the message first with hFunc is not needed, as it is included in HashToG2. +func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + // Hash the message into G2 + dst := []byte("0x01") + H, err := {{ .CurvePackage }}.HashToG2(message, dst) + if err != nil { + return nil, err + } + + // Sign + var sig Signature + scalar := new(big.Int) + scalar.SetBytes(privKey.scalar[:sizeFr]) + sig.S.ScalarMultiplication(&H, scalar) + + return sig.Bytes(), nil +} + +// Verify validates the BLS signature +// +// e(G1, sig.S) ?= e(pk, G2) +func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + + // Deserialize the signature + var sig Signature + if _, err := sig.SetBytes(sigBin); err != nil { + return false, err + } + // Hash the message into G2 + dst := []byte("0x01") + H, err := {{ .CurvePackage }}.HashToG2(message, dst) + if err != nil { + return false, err + } + + // Verify the signature + _, _, g1, _ := {{ .CurvePackage }}.Generators() + g1.Neg(&g1) + f, err := {{ .CurvePackage }}.PairingCheck([]{{ .CurvePackage }}.G1Affine{g1, publicKey.A}, []{{ .CurvePackage }}.G2Affine{sig.S, H}) + if err != nil { + return false, err + } + + return f, nil + +} diff --git a/internal/generator/signature/bls/template/bls.test.go.tmpl b/internal/generator/signature/bls/template/bls.test.go.tmpl new file mode 100644 index 000000000..953822abb --- /dev/null +++ b/internal/generator/signature/bls/template/bls.test.go.tmpl @@ -0,0 +1,56 @@ +import ( + "crypto/rand" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +func TestBLS(t *testing.T) { + + t.Parallel() + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + + properties.Property("[{{ toUpper .Name }}] test the signing and verification", prop.ForAll( + func() bool { + + privKey, _ := GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + msg := []byte("testing BLS") + sig, _ := privKey.Sign(msg, nil) + flag, _ := publicKey.Verify(sig, msg, nil) + + return flag + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} + +// ------------------------------------------------------------ +// benches + +func BenchmarkSignBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + + msg := []byte("benchmarking BLS sign()") + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.Sign(msg, nil) + } +} + +func BenchmarkVerifyBLS(b *testing.B) { + + privKey, _ := GenerateKey(rand.Reader) + msg := []byte("benchmarking BLS sign()") + sig, _ := privKey.Sign(msg, nil) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + privKey.PublicKey.Verify(sig, msg, nil) + } +} diff --git a/internal/generator/signature/bls/template/doc.go.tmpl b/internal/generator/signature/bls/template/doc.go.tmpl new file mode 100644 index 000000000..2ccfc58e1 --- /dev/null +++ b/internal/generator/signature/bls/template/doc.go.tmpl @@ -0,0 +1,7 @@ +// Package {{.Package}} provides BLS signature scheme on the {{.Name}} curve. +// +// Documentation: +// - Wikipedia: https://en.wikipedia.org/wiki/BLS_digital_signature +// - IETF: https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/05/ +// +package {{.Package}} diff --git a/internal/generator/signature/bls/template/marshal.go.tmpl b/internal/generator/signature/bls/template/marshal.go.tmpl new file mode 100644 index 000000000..95648122d --- /dev/null +++ b/internal/generator/signature/bls/template/marshal.go.tmpl @@ -0,0 +1,94 @@ +import ( + "crypto/subtle" + "io" +) + +// Bytes returns the binary representation of the public key +// follows https://tools.ietf.org/html/rfc8032#section-3.1 +// and returns a compressed representation of the point (x,y) +// +// x, y are the coordinates of the point +// on the curve as big endian integers. +// compressed representation store x with a parity bit to recompute y +func (pk *PublicKey) Bytes() []byte { + var res [sizePublicKey]byte +{{- if eq .Name "secp256k1"}} + pkBin := pk.A.RawBytes() +{{- else}} + pkBin := pk.A.Bytes() +{{- end}} + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pkBin[:]) + return res[:] +} + +// SetBytes sets p from binary representation in buf. +// buf represents a public key as x||y where x, y are +// interpreted as big endian binary numbers corresponding +// to the coordinates of a point on the curve. +// It returns the number of bytes read from the buffer. +func (pk *PublicKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePublicKey { + return n, io.ErrShortBuffer + } + if _, err := pk.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizeFp + return n, nil +} + +// Bytes returns the binary representation of pk, +// as byte array publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +func (privKey *PrivateKey) Bytes() []byte { + var res [sizePrivateKey]byte +{{- if eq .Name "secp256k1"}} + pubkBin := privKey.PublicKey.A.RawBytes() +{{- else}} + pubkBin := privKey.PublicKey.A.Bytes() +{{- end}} + subtle.ConstantTimeCopy(1, res[:sizePublicKey], pubkBin[:]) + subtle.ConstantTimeCopy(1, res[sizePublicKey:sizePrivateKey], privKey.scalar[:]) + return res[:] +} + +// SetBytes sets pk from buf, where buf is interpreted +// as publicKey||scalar +// where publicKey is as publicKey.Bytes(), and +// scalar is in big endian, of size sizeFr. +// It returns the number byte read. +func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizePrivateKey { + return n, io.ErrShortBuffer + } + if _, err := privKey.PublicKey.A.SetBytes(buf[:sizePublicKey]); err != nil { + return 0, err + } + n += sizePublicKey + subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizePublicKey:sizePrivateKey]) + n += sizeFr + return n, nil +} + +// Bytes returns the binary representation of sig +// as a byte array of size 2*sizeFp (G2 compressef encoding) +func (sig *Signature) Bytes() []byte { + res := sig.S.Bytes() + return res[:sizeSignature] +} + +// SetBytes sets sig from a buffer in binary. +// buf is read interpreted as r||s +// It returns the number of bytes read from buf. +func (sig *Signature) SetBytes(buf []byte) (int, error) { + n := 0 + if len(buf) < sizeSignature { + return n, io.ErrShortBuffer + } + sig.S.SetBytes(buf) + n += sizeFr + return n, nil +} diff --git a/internal/generator/signature/bls/template/marshal.test.go.tmpl b/internal/generator/signature/bls/template/marshal.test.go.tmpl new file mode 100644 index 000000000..3d8a1922d --- /dev/null +++ b/internal/generator/signature/bls/template/marshal.test.go.tmpl @@ -0,0 +1,46 @@ +import ( + "crypto/rand" + "crypto/subtle" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/prop" +) + +const ( + nbFuzzShort = 10 + nbFuzz = 100 +) + +func TestSerialization(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + if testing.Short() { + parameters.MinSuccessfulTests = nbFuzzShort + } else { + parameters.MinSuccessfulTests = nbFuzz + } + + properties := gopter.NewProperties(parameters) + + properties.Property("[{{ toUpper .Name }}] BLS serialization: SetBytes(Bytes()) should stay the same", prop.ForAll( + func() bool { + privKey, _ := GenerateKey(rand.Reader) + + var end PrivateKey + buf := privKey.Bytes() + n, err := end.SetBytes(buf[:]) + if err != nil { + return false + } + if n != sizePrivateKey { + return false + } + + return end.PublicKey.Equal(&privKey.PublicKey) && subtle.ConstantTimeCompare(end.scalar[:], privKey.scalar[:]) == 1 + + }, + )) + + properties.TestingRun(t, gopter.ConsoleReporter(false)) +} diff --git a/signature/bls/bls.go b/signature/bls/bls.go new file mode 100644 index 000000000..a2c8c96ad --- /dev/null +++ b/signature/bls/bls.go @@ -0,0 +1,59 @@ +/* +Copyright © 2020 ConsenSys + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package bls + +import ( + "io" + + "github.com/consensys/gnark-crypto/ecc" + bls_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signature/bls" + bls_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signature/bls" + bls_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signature/bls" + bls_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signature/bls" + bls_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signature/bls" + bls_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signature/bls" + bls_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signature/bls" + bls_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signature/bls" + bls_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signature/bls" + "github.com/consensys/gnark-crypto/signature" +) + +// New takes a source of randomness and returns a new key pair +func New(ss ecc.ID, r io.Reader) (signature.Signer, error) { + switch ss { + case ecc.BN254: + return bls_bn254.GenerateKey(r) + case ecc.BLS12_381: + return bls_bls12381.GenerateKey(r) + case ecc.BLS12_377: + return bls_bls12377.GenerateKey(r) + case ecc.BLS12_378: + return bls_bls12378.GenerateKey(r) + case ecc.BW6_761: + return bls_bw6761.GenerateKey(r) + case ecc.BW6_756: + return bls_bw6756.GenerateKey(r) + case ecc.BLS24_315: + return bls_bls24315.GenerateKey(r) + case ecc.BLS24_317: + return bls_bls24317.GenerateKey(r) + case ecc.BW6_633: + return bls_bw6633.GenerateKey(r) + default: + panic("not implemented") + } +} From 86e44f07b862a7f845e528cb3d65c44e2d889d50 Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 26 Jan 2023 13:08:21 +0100 Subject: [PATCH 07/13] style: signatures directory instead of signature --- signature/bls/bls.go | 18 +++++++++--------- signature/ecdsa/ecdsa.go | 22 +++++++++++----------- signature/schnorr/schnorr.go | 22 +++++++++++----------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/signature/bls/bls.go b/signature/bls/bls.go index a2c8c96ad..26e84ecc7 100644 --- a/signature/bls/bls.go +++ b/signature/bls/bls.go @@ -20,15 +20,15 @@ import ( "io" "github.com/consensys/gnark-crypto/ecc" - bls_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signature/bls" - bls_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signature/bls" - bls_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signature/bls" - bls_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signature/bls" - bls_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signature/bls" - bls_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signature/bls" - bls_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signature/bls" - bls_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signature/bls" - bls_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signature/bls" + bls_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signatures/bls" + bls_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signatures/bls" + bls_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signatures/bls" + bls_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signatures/bls" + bls_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signatures/bls" + bls_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signatures/bls" + bls_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signatures/bls" + bls_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signatures/bls" + bls_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signatures/bls" "github.com/consensys/gnark-crypto/signature" ) diff --git a/signature/ecdsa/ecdsa.go b/signature/ecdsa/ecdsa.go index ffe16b590..d103aab15 100644 --- a/signature/ecdsa/ecdsa.go +++ b/signature/ecdsa/ecdsa.go @@ -20,17 +20,17 @@ import ( "io" "github.com/consensys/gnark-crypto/ecc" - ecdsa_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signature/ecdsa" - ecdsa_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signature/ecdsa" - ecdsa_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signature/ecdsa" - ecdsa_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signature/ecdsa" - ecdsa_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signature/ecdsa" - ecdsa_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signature/ecdsa" - ecdsa_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signature/ecdsa" - ecdsa_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signature/ecdsa" - ecdsa_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signature/ecdsa" - ecdsa_secp256k1 "github.com/consensys/gnark-crypto/ecc/secp256k1/signature/ecdsa" - ecdsa_starkcurve "github.com/consensys/gnark-crypto/ecc/stark-curve/signature/ecdsa" + ecdsa_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signatures/ecdsa" + ecdsa_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signatures/ecdsa" + ecdsa_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signatures/ecdsa" + ecdsa_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signatures/ecdsa" + ecdsa_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signatures/ecdsa" + ecdsa_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signatures/ecdsa" + ecdsa_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signatures/ecdsa" + ecdsa_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signatures/ecdsa" + ecdsa_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signatures/ecdsa" + ecdsa_secp256k1 "github.com/consensys/gnark-crypto/ecc/secp256k1/signatures/ecdsa" + ecdsa_starkcurve "github.com/consensys/gnark-crypto/ecc/stark-curve/signatures/ecdsa" "github.com/consensys/gnark-crypto/signature" ) diff --git a/signature/schnorr/schnorr.go b/signature/schnorr/schnorr.go index 9c432cd4b..f7255d0f3 100644 --- a/signature/schnorr/schnorr.go +++ b/signature/schnorr/schnorr.go @@ -20,17 +20,17 @@ import ( "io" "github.com/consensys/gnark-crypto/ecc" - schnorr_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signature/schnorr" - schnorr_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signature/schnorr" - schnorr_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signature/schnorr" - schnorr_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signature/schnorr" - schnorr_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signature/schnorr" - schnorr_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signature/schnorr" - schnorr_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signature/schnorr" - schnorr_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signature/schnorr" - schnorr_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signature/schnorr" - schnorr_secp256k1 "github.com/consensys/gnark-crypto/ecc/secp256k1/signature/schnorr" - schnorr_starkcurve "github.com/consensys/gnark-crypto/ecc/stark-curve/signature/schnorr" + schnorr_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signatures/schnorr" + schnorr_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signatures/schnorr" + schnorr_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signatures/schnorr" + schnorr_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signatures/schnorr" + schnorr_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signatures/schnorr" + schnorr_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signatures/schnorr" + schnorr_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signatures/schnorr" + schnorr_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signatures/schnorr" + schnorr_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signatures/schnorr" + schnorr_secp256k1 "github.com/consensys/gnark-crypto/ecc/secp256k1/signatures/schnorr" + schnorr_starkcurve "github.com/consensys/gnark-crypto/ecc/stark-curve/signatures/schnorr" "github.com/consensys/gnark-crypto/signature" ) From ec8d9b90ede2b0871dfeae7e56577736f99e4bdb Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 26 Jan 2023 14:58:50 +0100 Subject: [PATCH 08/13] fix: enforce hFunc to bil nil in BLS sig --- ecc/bls12-377/signatures/bls/bls.go | 18 ++++++++++++++---- ecc/bls12-377/signatures/ecdsa/ecdsa.go | 3 --- ecc/bls12-377/signatures/schnorr/schnorr.go | 3 --- ecc/bls12-378/signatures/bls/bls.go | 18 ++++++++++++++---- ecc/bls12-378/signatures/ecdsa/ecdsa.go | 3 --- ecc/bls12-378/signatures/schnorr/schnorr.go | 3 --- ecc/bls12-381/signatures/bls/bls.go | 18 ++++++++++++++---- ecc/bls12-381/signatures/ecdsa/ecdsa.go | 3 --- ecc/bls12-381/signatures/schnorr/schnorr.go | 3 --- ecc/bls24-315/signatures/bls/bls.go | 18 ++++++++++++++---- ecc/bls24-315/signatures/ecdsa/ecdsa.go | 3 --- ecc/bls24-315/signatures/schnorr/schnorr.go | 3 --- ecc/bls24-317/signatures/bls/bls.go | 18 ++++++++++++++---- ecc/bls24-317/signatures/ecdsa/ecdsa.go | 3 --- ecc/bls24-317/signatures/schnorr/schnorr.go | 3 --- ecc/bn254/signatures/bls/bls.go | 18 ++++++++++++++---- ecc/bn254/signatures/ecdsa/ecdsa.go | 3 --- ecc/bn254/signatures/schnorr/schnorr.go | 3 --- ecc/bw6-633/signatures/bls/bls.go | 18 ++++++++++++++---- ecc/bw6-633/signatures/ecdsa/ecdsa.go | 3 --- ecc/bw6-633/signatures/schnorr/schnorr.go | 3 --- ecc/bw6-756/signatures/bls/bls.go | 18 ++++++++++++++---- ecc/bw6-756/signatures/ecdsa/ecdsa.go | 3 --- ecc/bw6-756/signatures/schnorr/schnorr.go | 3 --- ecc/bw6-761/signatures/bls/bls.go | 18 ++++++++++++++---- ecc/bw6-761/signatures/ecdsa/ecdsa.go | 3 --- ecc/bw6-761/signatures/schnorr/schnorr.go | 3 --- ecc/secp256k1/signatures/ecdsa/ecdsa.go | 3 --- ecc/secp256k1/signatures/schnorr/schnorr.go | 3 --- ecc/stark-curve/signatures/ecdsa/ecdsa.go | 3 --- ecc/stark-curve/signatures/schnorr/schnorr.go | 3 --- .../signature/bls/template/bls.go.tmpl | 18 ++++++++++++++---- .../signature/ecdsa/template/ecdsa.go.tmpl | 3 --- .../signature/schnorr/template/schnorr.go.tmpl | 3 --- 34 files changed, 140 insertions(+), 112 deletions(-) diff --git a/ecc/bls12-377/signatures/bls/bls.go b/ecc/bls12-377/signatures/bls/bls.go index 4898a1c25..cedf17d11 100644 --- a/ecc/bls12-377/signatures/bls/bls.go +++ b/ecc/bls12-377/signatures/bls/bls.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNotNil = errors.New("hFunc not nil. Hashing the message is done in HashToG2.") const ( sizeFr = fr.Bytes @@ -190,10 +190,14 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // H(m) ← m (hash to G₂) // S = sk ⋅ H(m) ∈ G₂ // signature = S -// -// hFunc should always be nil. -// Hashing the message first with hFunc is not needed, as it is included in HashToG2. func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return nil, errHashNotNil + } + // Hash the message into G2 dst := []byte("0x01") H, err := bls12377.HashToG2(message, dst) @@ -215,6 +219,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // e(G1, sig.S) ?= e(pk, G2) func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return false, errHashNotNil + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { diff --git a/ecc/bls12-377/signatures/ecdsa/ecdsa.go b/ecc/bls12-377/signatures/ecdsa/ecdsa.go index 6f27e1535..274344c65 100644 --- a/ecc/bls12-377/signatures/ecdsa/ecdsa.go +++ b/ecc/bls12-377/signatures/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls12-377/signatures/schnorr/schnorr.go b/ecc/bls12-377/signatures/schnorr/schnorr.go index 328b33516..c5ba8f633 100644 --- a/ecc/bls12-377/signatures/schnorr/schnorr.go +++ b/ecc/bls12-377/signatures/schnorr/schnorr.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls12-378/signatures/bls/bls.go b/ecc/bls12-378/signatures/bls/bls.go index 951e1c227..c98e6c2ca 100644 --- a/ecc/bls12-378/signatures/bls/bls.go +++ b/ecc/bls12-378/signatures/bls/bls.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNotNil = errors.New("hFunc not nil. Hashing the message is done in HashToG2.") const ( sizeFr = fr.Bytes @@ -190,10 +190,14 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // H(m) ← m (hash to G₂) // S = sk ⋅ H(m) ∈ G₂ // signature = S -// -// hFunc should always be nil. -// Hashing the message first with hFunc is not needed, as it is included in HashToG2. func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return nil, errHashNotNil + } + // Hash the message into G2 dst := []byte("0x01") H, err := bls12378.HashToG2(message, dst) @@ -215,6 +219,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // e(G1, sig.S) ?= e(pk, G2) func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return false, errHashNotNil + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { diff --git a/ecc/bls12-378/signatures/ecdsa/ecdsa.go b/ecc/bls12-378/signatures/ecdsa/ecdsa.go index bfee7fe4e..3035e2b92 100644 --- a/ecc/bls12-378/signatures/ecdsa/ecdsa.go +++ b/ecc/bls12-378/signatures/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls12-378/signatures/schnorr/schnorr.go b/ecc/bls12-378/signatures/schnorr/schnorr.go index 344c3f6f3..f992d5b17 100644 --- a/ecc/bls12-378/signatures/schnorr/schnorr.go +++ b/ecc/bls12-378/signatures/schnorr/schnorr.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls12-381/signatures/bls/bls.go b/ecc/bls12-381/signatures/bls/bls.go index 5af9e435e..bebca876b 100644 --- a/ecc/bls12-381/signatures/bls/bls.go +++ b/ecc/bls12-381/signatures/bls/bls.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNotNil = errors.New("hFunc not nil. Hashing the message is done in HashToG2.") const ( sizeFr = fr.Bytes @@ -190,10 +190,14 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // H(m) ← m (hash to G₂) // S = sk ⋅ H(m) ∈ G₂ // signature = S -// -// hFunc should always be nil. -// Hashing the message first with hFunc is not needed, as it is included in HashToG2. func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return nil, errHashNotNil + } + // Hash the message into G2 dst := []byte("0x01") H, err := bls12381.HashToG2(message, dst) @@ -215,6 +219,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // e(G1, sig.S) ?= e(pk, G2) func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return false, errHashNotNil + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { diff --git a/ecc/bls12-381/signatures/ecdsa/ecdsa.go b/ecc/bls12-381/signatures/ecdsa/ecdsa.go index 82925c627..4af89070e 100644 --- a/ecc/bls12-381/signatures/ecdsa/ecdsa.go +++ b/ecc/bls12-381/signatures/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls12-381/signatures/schnorr/schnorr.go b/ecc/bls12-381/signatures/schnorr/schnorr.go index f1d16026f..6507ee5b4 100644 --- a/ecc/bls12-381/signatures/schnorr/schnorr.go +++ b/ecc/bls12-381/signatures/schnorr/schnorr.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls24-315/signatures/bls/bls.go b/ecc/bls24-315/signatures/bls/bls.go index ed6bc4791..ff9c24da2 100644 --- a/ecc/bls24-315/signatures/bls/bls.go +++ b/ecc/bls24-315/signatures/bls/bls.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNotNil = errors.New("hFunc not nil. Hashing the message is done in HashToG2.") const ( sizeFr = fr.Bytes @@ -190,10 +190,14 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // H(m) ← m (hash to G₂) // S = sk ⋅ H(m) ∈ G₂ // signature = S -// -// hFunc should always be nil. -// Hashing the message first with hFunc is not needed, as it is included in HashToG2. func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return nil, errHashNotNil + } + // Hash the message into G2 dst := []byte("0x01") H, err := bls24315.HashToG2(message, dst) @@ -215,6 +219,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // e(G1, sig.S) ?= e(pk, G2) func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return false, errHashNotNil + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { diff --git a/ecc/bls24-315/signatures/ecdsa/ecdsa.go b/ecc/bls24-315/signatures/ecdsa/ecdsa.go index c9fe0878f..8ca4a8071 100644 --- a/ecc/bls24-315/signatures/ecdsa/ecdsa.go +++ b/ecc/bls24-315/signatures/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls24-315/signatures/schnorr/schnorr.go b/ecc/bls24-315/signatures/schnorr/schnorr.go index 83cb61540..67058ccc5 100644 --- a/ecc/bls24-315/signatures/schnorr/schnorr.go +++ b/ecc/bls24-315/signatures/schnorr/schnorr.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls24-317/signatures/bls/bls.go b/ecc/bls24-317/signatures/bls/bls.go index 97c6d1ea7..2779a7596 100644 --- a/ecc/bls24-317/signatures/bls/bls.go +++ b/ecc/bls24-317/signatures/bls/bls.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNotNil = errors.New("hFunc not nil. Hashing the message is done in HashToG2.") const ( sizeFr = fr.Bytes @@ -190,10 +190,14 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // H(m) ← m (hash to G₂) // S = sk ⋅ H(m) ∈ G₂ // signature = S -// -// hFunc should always be nil. -// Hashing the message first with hFunc is not needed, as it is included in HashToG2. func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return nil, errHashNotNil + } + // Hash the message into G2 dst := []byte("0x01") H, err := bls24317.HashToG2(message, dst) @@ -215,6 +219,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // e(G1, sig.S) ?= e(pk, G2) func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return false, errHashNotNil + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { diff --git a/ecc/bls24-317/signatures/ecdsa/ecdsa.go b/ecc/bls24-317/signatures/ecdsa/ecdsa.go index 97c553246..dc0719492 100644 --- a/ecc/bls24-317/signatures/ecdsa/ecdsa.go +++ b/ecc/bls24-317/signatures/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls24-317/signatures/schnorr/schnorr.go b/ecc/bls24-317/signatures/schnorr/schnorr.go index b45b7d147..6b81eff6a 100644 --- a/ecc/bls24-317/signatures/schnorr/schnorr.go +++ b/ecc/bls24-317/signatures/schnorr/schnorr.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bn254/signatures/bls/bls.go b/ecc/bn254/signatures/bls/bls.go index 59b90373a..8836c2efa 100644 --- a/ecc/bn254/signatures/bls/bls.go +++ b/ecc/bn254/signatures/bls/bls.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNotNil = errors.New("hFunc not nil. Hashing the message is done in HashToG2.") const ( sizeFr = fr.Bytes @@ -190,10 +190,14 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // H(m) ← m (hash to G₂) // S = sk ⋅ H(m) ∈ G₂ // signature = S -// -// hFunc should always be nil. -// Hashing the message first with hFunc is not needed, as it is included in HashToG2. func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return nil, errHashNotNil + } + // Hash the message into G2 dst := []byte("0x01") H, err := bn254.HashToG2(message, dst) @@ -215,6 +219,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // e(G1, sig.S) ?= e(pk, G2) func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return false, errHashNotNil + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { diff --git a/ecc/bn254/signatures/ecdsa/ecdsa.go b/ecc/bn254/signatures/ecdsa/ecdsa.go index e55205377..2907acda4 100644 --- a/ecc/bn254/signatures/ecdsa/ecdsa.go +++ b/ecc/bn254/signatures/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bn254/signatures/schnorr/schnorr.go b/ecc/bn254/signatures/schnorr/schnorr.go index d28e3d63f..981259779 100644 --- a/ecc/bn254/signatures/schnorr/schnorr.go +++ b/ecc/bn254/signatures/schnorr/schnorr.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bw6-633/signatures/bls/bls.go b/ecc/bw6-633/signatures/bls/bls.go index 28d2ed07c..271ab7f66 100644 --- a/ecc/bw6-633/signatures/bls/bls.go +++ b/ecc/bw6-633/signatures/bls/bls.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNotNil = errors.New("hFunc not nil. Hashing the message is done in HashToG2.") const ( sizeFr = fr.Bytes @@ -190,10 +190,14 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // H(m) ← m (hash to G₂) // S = sk ⋅ H(m) ∈ G₂ // signature = S -// -// hFunc should always be nil. -// Hashing the message first with hFunc is not needed, as it is included in HashToG2. func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return nil, errHashNotNil + } + // Hash the message into G2 dst := []byte("0x01") H, err := bw6633.HashToG2(message, dst) @@ -215,6 +219,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // e(G1, sig.S) ?= e(pk, G2) func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return false, errHashNotNil + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { diff --git a/ecc/bw6-633/signatures/ecdsa/ecdsa.go b/ecc/bw6-633/signatures/ecdsa/ecdsa.go index 67efe8ea1..6bd55d1c0 100644 --- a/ecc/bw6-633/signatures/ecdsa/ecdsa.go +++ b/ecc/bw6-633/signatures/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bw6-633/signatures/schnorr/schnorr.go b/ecc/bw6-633/signatures/schnorr/schnorr.go index 9e8631b49..b13c510c6 100644 --- a/ecc/bw6-633/signatures/schnorr/schnorr.go +++ b/ecc/bw6-633/signatures/schnorr/schnorr.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bw6-756/signatures/bls/bls.go b/ecc/bw6-756/signatures/bls/bls.go index 76c6356b6..dcf841edd 100644 --- a/ecc/bw6-756/signatures/bls/bls.go +++ b/ecc/bw6-756/signatures/bls/bls.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNotNil = errors.New("hFunc not nil. Hashing the message is done in HashToG2.") const ( sizeFr = fr.Bytes @@ -190,10 +190,14 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // H(m) ← m (hash to G₂) // S = sk ⋅ H(m) ∈ G₂ // signature = S -// -// hFunc should always be nil. -// Hashing the message first with hFunc is not needed, as it is included in HashToG2. func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return nil, errHashNotNil + } + // Hash the message into G2 dst := []byte("0x01") H, err := bw6756.HashToG2(message, dst) @@ -215,6 +219,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // e(G1, sig.S) ?= e(pk, G2) func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return false, errHashNotNil + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { diff --git a/ecc/bw6-756/signatures/ecdsa/ecdsa.go b/ecc/bw6-756/signatures/ecdsa/ecdsa.go index 1131bb1f7..3e15ea055 100644 --- a/ecc/bw6-756/signatures/ecdsa/ecdsa.go +++ b/ecc/bw6-756/signatures/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bw6-756/signatures/schnorr/schnorr.go b/ecc/bw6-756/signatures/schnorr/schnorr.go index f44046979..3f5ab1f14 100644 --- a/ecc/bw6-756/signatures/schnorr/schnorr.go +++ b/ecc/bw6-756/signatures/schnorr/schnorr.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bw6-761/signatures/bls/bls.go b/ecc/bw6-761/signatures/bls/bls.go index 5f1f13676..c575e10cb 100644 --- a/ecc/bw6-761/signatures/bls/bls.go +++ b/ecc/bw6-761/signatures/bls/bls.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNotNil = errors.New("hFunc not nil. Hashing the message is done in HashToG2.") const ( sizeFr = fr.Bytes @@ -190,10 +190,14 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // H(m) ← m (hash to G₂) // S = sk ⋅ H(m) ∈ G₂ // signature = S -// -// hFunc should always be nil. -// Hashing the message first with hFunc is not needed, as it is included in HashToG2. func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return nil, errHashNotNil + } + // Hash the message into G2 dst := []byte("0x01") H, err := bw6761.HashToG2(message, dst) @@ -215,6 +219,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // e(G1, sig.S) ?= e(pk, G2) func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return false, errHashNotNil + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { diff --git a/ecc/bw6-761/signatures/ecdsa/ecdsa.go b/ecc/bw6-761/signatures/ecdsa/ecdsa.go index 8ad854c43..ac056f8d9 100644 --- a/ecc/bw6-761/signatures/ecdsa/ecdsa.go +++ b/ecc/bw6-761/signatures/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bw6-761/signatures/schnorr/schnorr.go b/ecc/bw6-761/signatures/schnorr/schnorr.go index 90e97627b..bb9245e48 100644 --- a/ecc/bw6-761/signatures/schnorr/schnorr.go +++ b/ecc/bw6-761/signatures/schnorr/schnorr.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/secp256k1/signatures/ecdsa/ecdsa.go b/ecc/secp256k1/signatures/ecdsa/ecdsa.go index a2abdbbab..799036a76 100644 --- a/ecc/secp256k1/signatures/ecdsa/ecdsa.go +++ b/ecc/secp256k1/signatures/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/secp256k1/signatures/schnorr/schnorr.go b/ecc/secp256k1/signatures/schnorr/schnorr.go index b168333d9..359d3332d 100644 --- a/ecc/secp256k1/signatures/schnorr/schnorr.go +++ b/ecc/secp256k1/signatures/schnorr/schnorr.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/stark-curve/signatures/ecdsa/ecdsa.go b/ecc/stark-curve/signatures/ecdsa/ecdsa.go index bd1221196..3a12ff123 100644 --- a/ecc/stark-curve/signatures/ecdsa/ecdsa.go +++ b/ecc/stark-curve/signatures/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/stark-curve/signatures/schnorr/schnorr.go b/ecc/stark-curve/signatures/schnorr/schnorr.go index 852b48ac9..b72c6645f 100644 --- a/ecc/stark-curve/signatures/schnorr/schnorr.go +++ b/ecc/stark-curve/signatures/schnorr/schnorr.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/internal/generator/signature/bls/template/bls.go.tmpl b/internal/generator/signature/bls/template/bls.go.tmpl index a8dcdf8d5..f29730102 100644 --- a/internal/generator/signature/bls/template/bls.go.tmpl +++ b/internal/generator/signature/bls/template/bls.go.tmpl @@ -15,7 +15,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNotNil = errors.New("hFunc not nil. Hashing the message is done in HashToG2.") const ( sizeFr = fr.Bytes @@ -177,10 +177,14 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // H(m) ← m (hash to G₂) // S = sk ⋅ H(m) ∈ G₂ // signature = S -// -// hFunc should always be nil. -// Hashing the message first with hFunc is not needed, as it is included in HashToG2. func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return nil, errHashNotNil + } + // Hash the message into G2 dst := []byte("0x01") H, err := {{ .CurvePackage }}.HashToG2(message, dst) @@ -202,6 +206,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // e(G1, sig.S) ?= e(pk, G2) func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc should always be nil. + // Hashing the message first with hFunc is not needed, as it is included in HashToG2. + if hFunc != nil { + return false, errHashNotNil + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { diff --git a/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl b/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl index dd536c0e1..c5923ca8b 100644 --- a/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl +++ b/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl @@ -4,7 +4,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -15,8 +14,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/internal/generator/signature/schnorr/template/schnorr.go.tmpl b/internal/generator/signature/schnorr/template/schnorr.go.tmpl index 99b0846c3..01facdf92 100644 --- a/internal/generator/signature/schnorr/template/schnorr.go.tmpl +++ b/internal/generator/signature/schnorr/template/schnorr.go.tmpl @@ -4,7 +4,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -15,8 +14,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes From 57ef244fe7793e37dff920da3128ba7666c77561 Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 26 Jan 2023 20:49:50 +0100 Subject: [PATCH 09/13] refactor: share HashToInt function between signatures --- .../{signatures => signature}/bls/bls.go | 15 -------- .../{signatures => signature}/bls/bls_test.go | 0 .../{signatures => signature}/bls/doc.go | 0 .../{signatures => signature}/bls/marshal.go | 0 .../bls/marshal_test.go | 0 .../{signatures => signature}/ecdsa/doc.go | 0 .../{signatures => signature}/ecdsa/ecdsa.go | 24 +++--------- .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signatures => signature}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 24 +++--------- .../schnorr/schnorr_test.go | 0 ecc/bls12-377/signature/signature/utils.go | 38 +++++++++++++++++++ ecc/bls12-377/signature/utils.go | 38 +++++++++++++++++++ .../{signatures => signature}/bls/bls.go | 15 -------- .../{signatures => signature}/bls/bls_test.go | 0 .../{signatures => signature}/bls/doc.go | 0 .../{signatures => signature}/bls/marshal.go | 0 .../bls/marshal_test.go | 0 .../{signatures => signature}/ecdsa/doc.go | 0 .../{signatures => signature}/ecdsa/ecdsa.go | 24 +++--------- .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signatures => signature}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 24 +++--------- .../schnorr/schnorr_test.go | 0 ecc/bls12-378/signature/utils.go | 38 +++++++++++++++++++ .../{signatures => signature}/bls/bls.go | 15 -------- .../{signatures => signature}/bls/bls_test.go | 0 .../{signatures => signature}/bls/doc.go | 0 .../{signatures => signature}/bls/marshal.go | 0 .../bls/marshal_test.go | 0 .../{signatures => signature}/ecdsa/doc.go | 0 .../{signatures => signature}/ecdsa/ecdsa.go | 24 +++--------- .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signatures => signature}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 24 +++--------- .../schnorr/schnorr_test.go | 0 ecc/bls12-381/signature/utils.go | 38 +++++++++++++++++++ .../{signatures => signature}/bls/bls.go | 15 -------- .../{signatures => signature}/bls/bls_test.go | 0 .../{signatures => signature}/bls/doc.go | 0 .../{signatures => signature}/bls/marshal.go | 0 .../bls/marshal_test.go | 0 .../{signatures => signature}/ecdsa/doc.go | 0 .../{signatures => signature}/ecdsa/ecdsa.go | 24 +++--------- .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signatures => signature}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 24 +++--------- .../schnorr/schnorr_test.go | 0 ecc/bls24-315/signature/utils.go | 38 +++++++++++++++++++ .../{signatures => signature}/bls/bls.go | 15 -------- .../{signatures => signature}/bls/bls_test.go | 0 .../{signatures => signature}/bls/doc.go | 0 .../{signatures => signature}/bls/marshal.go | 0 .../bls/marshal_test.go | 0 .../{signatures => signature}/ecdsa/doc.go | 0 .../{signatures => signature}/ecdsa/ecdsa.go | 24 +++--------- .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signatures => signature}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 24 +++--------- .../schnorr/schnorr_test.go | 0 ecc/bls24-317/signature/utils.go | 38 +++++++++++++++++++ .../{signatures => signature}/bls/bls.go | 15 -------- .../{signatures => signature}/bls/bls_test.go | 0 .../{signatures => signature}/bls/doc.go | 0 .../{signatures => signature}/bls/marshal.go | 0 .../bls/marshal_test.go | 0 .../{signatures => signature}/ecdsa/doc.go | 0 .../{signatures => signature}/ecdsa/ecdsa.go | 24 +++--------- .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signatures => signature}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 24 +++--------- .../schnorr/schnorr_test.go | 0 ecc/bn254/signature/utils.go | 38 +++++++++++++++++++ .../{signatures => signature}/bls/bls.go | 15 -------- .../{signatures => signature}/bls/bls_test.go | 0 .../{signatures => signature}/bls/doc.go | 0 .../{signatures => signature}/bls/marshal.go | 0 .../bls/marshal_test.go | 0 .../{signatures => signature}/ecdsa/doc.go | 0 .../{signatures => signature}/ecdsa/ecdsa.go | 24 +++--------- .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signatures => signature}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 24 +++--------- .../schnorr/schnorr_test.go | 0 ecc/bw6-633/signature/utils.go | 38 +++++++++++++++++++ .../{signatures => signature}/bls/bls.go | 15 -------- .../{signatures => signature}/bls/bls_test.go | 0 .../{signatures => signature}/bls/doc.go | 0 .../{signatures => signature}/bls/marshal.go | 0 .../bls/marshal_test.go | 0 .../{signatures => signature}/ecdsa/doc.go | 0 .../{signatures => signature}/ecdsa/ecdsa.go | 24 +++--------- .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signatures => signature}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 24 +++--------- .../schnorr/schnorr_test.go | 0 ecc/bw6-756/signature/utils.go | 38 +++++++++++++++++++ .../{signatures => signature}/bls/bls.go | 15 -------- .../{signatures => signature}/bls/bls_test.go | 0 .../{signatures => signature}/bls/doc.go | 0 .../{signatures => signature}/bls/marshal.go | 0 .../bls/marshal_test.go | 0 .../{signatures => signature}/ecdsa/doc.go | 0 .../{signatures => signature}/ecdsa/ecdsa.go | 24 +++--------- .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signatures => signature}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 24 +++--------- .../schnorr/schnorr_test.go | 0 ecc/bw6-761/signature/utils.go | 38 +++++++++++++++++++ .../{signatures => signature}/ecdsa/doc.go | 0 .../{signatures => signature}/ecdsa/ecdsa.go | 24 +++--------- .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signatures => signature}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 24 +++--------- .../schnorr/schnorr_test.go | 0 ecc/secp256k1/signature/utils.go | 38 +++++++++++++++++++ .../{signatures => signature}/ecdsa/doc.go | 0 .../{signatures => signature}/ecdsa/ecdsa.go | 24 +++--------- .../ecdsa/ecdsa_test.go | 0 .../ecdsa/marshal.go | 0 .../ecdsa/marshal_test.go | 0 .../{signatures => signature}/schnorr/doc.go | 0 .../schnorr/marshal.go | 0 .../schnorr/marshal_test.go | 0 .../schnorr/schnorr.go | 24 +++--------- .../schnorr/schnorr_test.go | 0 ecc/stark-curve/signature/utils.go | 38 +++++++++++++++++++ internal/generator/main.go | 10 +++-- .../signature/bls/template/bls.go.tmpl | 15 -------- .../signature/ecdsa/template/ecdsa.go.tmpl | 24 +++--------- internal/generator/signature/generate.go | 18 +++++++++ .../schnorr/template/schnorr.go.tmpl | 24 +++--------- .../signature/template/utils.go.tmpl | 20 ++++++++++ 173 files changed, 621 insertions(+), 609 deletions(-) rename ecc/bls12-377/{signatures => signature}/bls/bls.go (92%) rename ecc/bls12-377/{signatures => signature}/bls/bls_test.go (100%) rename ecc/bls12-377/{signatures => signature}/bls/doc.go (100%) rename ecc/bls12-377/{signatures => signature}/bls/marshal.go (100%) rename ecc/bls12-377/{signatures => signature}/bls/marshal_test.go (100%) rename ecc/bls12-377/{signatures => signature}/ecdsa/doc.go (100%) rename ecc/bls12-377/{signatures => signature}/ecdsa/ecdsa.go (92%) rename ecc/bls12-377/{signatures => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bls12-377/{signatures => signature}/ecdsa/marshal.go (100%) rename ecc/bls12-377/{signatures => signature}/ecdsa/marshal_test.go (100%) rename ecc/bls12-377/{signatures => signature}/schnorr/doc.go (100%) rename ecc/bls12-377/{signatures => signature}/schnorr/marshal.go (100%) rename ecc/bls12-377/{signatures => signature}/schnorr/marshal_test.go (100%) rename ecc/bls12-377/{signatures => signature}/schnorr/schnorr.go (92%) rename ecc/bls12-377/{signatures => signature}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bls12-377/signature/signature/utils.go create mode 100644 ecc/bls12-377/signature/utils.go rename ecc/bls12-378/{signatures => signature}/bls/bls.go (92%) rename ecc/bls12-378/{signatures => signature}/bls/bls_test.go (100%) rename ecc/bls12-378/{signatures => signature}/bls/doc.go (100%) rename ecc/bls12-378/{signatures => signature}/bls/marshal.go (100%) rename ecc/bls12-378/{signatures => signature}/bls/marshal_test.go (100%) rename ecc/bls12-378/{signatures => signature}/ecdsa/doc.go (100%) rename ecc/bls12-378/{signatures => signature}/ecdsa/ecdsa.go (92%) rename ecc/bls12-378/{signatures => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bls12-378/{signatures => signature}/ecdsa/marshal.go (100%) rename ecc/bls12-378/{signatures => signature}/ecdsa/marshal_test.go (100%) rename ecc/bls12-378/{signatures => signature}/schnorr/doc.go (100%) rename ecc/bls12-378/{signatures => signature}/schnorr/marshal.go (100%) rename ecc/bls12-378/{signatures => signature}/schnorr/marshal_test.go (100%) rename ecc/bls12-378/{signatures => signature}/schnorr/schnorr.go (92%) rename ecc/bls12-378/{signatures => signature}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bls12-378/signature/utils.go rename ecc/bls12-381/{signatures => signature}/bls/bls.go (92%) rename ecc/bls12-381/{signatures => signature}/bls/bls_test.go (100%) rename ecc/bls12-381/{signatures => signature}/bls/doc.go (100%) rename ecc/bls12-381/{signatures => signature}/bls/marshal.go (100%) rename ecc/bls12-381/{signatures => signature}/bls/marshal_test.go (100%) rename ecc/bls12-381/{signatures => signature}/ecdsa/doc.go (100%) rename ecc/bls12-381/{signatures => signature}/ecdsa/ecdsa.go (92%) rename ecc/bls12-381/{signatures => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bls12-381/{signatures => signature}/ecdsa/marshal.go (100%) rename ecc/bls12-381/{signatures => signature}/ecdsa/marshal_test.go (100%) rename ecc/bls12-381/{signatures => signature}/schnorr/doc.go (100%) rename ecc/bls12-381/{signatures => signature}/schnorr/marshal.go (100%) rename ecc/bls12-381/{signatures => signature}/schnorr/marshal_test.go (100%) rename ecc/bls12-381/{signatures => signature}/schnorr/schnorr.go (92%) rename ecc/bls12-381/{signatures => signature}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bls12-381/signature/utils.go rename ecc/bls24-315/{signatures => signature}/bls/bls.go (92%) rename ecc/bls24-315/{signatures => signature}/bls/bls_test.go (100%) rename ecc/bls24-315/{signatures => signature}/bls/doc.go (100%) rename ecc/bls24-315/{signatures => signature}/bls/marshal.go (100%) rename ecc/bls24-315/{signatures => signature}/bls/marshal_test.go (100%) rename ecc/bls24-315/{signatures => signature}/ecdsa/doc.go (100%) rename ecc/bls24-315/{signatures => signature}/ecdsa/ecdsa.go (92%) rename ecc/bls24-315/{signatures => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bls24-315/{signatures => signature}/ecdsa/marshal.go (100%) rename ecc/bls24-315/{signatures => signature}/ecdsa/marshal_test.go (100%) rename ecc/bls24-315/{signatures => signature}/schnorr/doc.go (100%) rename ecc/bls24-315/{signatures => signature}/schnorr/marshal.go (100%) rename ecc/bls24-315/{signatures => signature}/schnorr/marshal_test.go (100%) rename ecc/bls24-315/{signatures => signature}/schnorr/schnorr.go (92%) rename ecc/bls24-315/{signatures => signature}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bls24-315/signature/utils.go rename ecc/bls24-317/{signatures => signature}/bls/bls.go (92%) rename ecc/bls24-317/{signatures => signature}/bls/bls_test.go (100%) rename ecc/bls24-317/{signatures => signature}/bls/doc.go (100%) rename ecc/bls24-317/{signatures => signature}/bls/marshal.go (100%) rename ecc/bls24-317/{signatures => signature}/bls/marshal_test.go (100%) rename ecc/bls24-317/{signatures => signature}/ecdsa/doc.go (100%) rename ecc/bls24-317/{signatures => signature}/ecdsa/ecdsa.go (92%) rename ecc/bls24-317/{signatures => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bls24-317/{signatures => signature}/ecdsa/marshal.go (100%) rename ecc/bls24-317/{signatures => signature}/ecdsa/marshal_test.go (100%) rename ecc/bls24-317/{signatures => signature}/schnorr/doc.go (100%) rename ecc/bls24-317/{signatures => signature}/schnorr/marshal.go (100%) rename ecc/bls24-317/{signatures => signature}/schnorr/marshal_test.go (100%) rename ecc/bls24-317/{signatures => signature}/schnorr/schnorr.go (92%) rename ecc/bls24-317/{signatures => signature}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bls24-317/signature/utils.go rename ecc/bn254/{signatures => signature}/bls/bls.go (92%) rename ecc/bn254/{signatures => signature}/bls/bls_test.go (100%) rename ecc/bn254/{signatures => signature}/bls/doc.go (100%) rename ecc/bn254/{signatures => signature}/bls/marshal.go (100%) rename ecc/bn254/{signatures => signature}/bls/marshal_test.go (100%) rename ecc/bn254/{signatures => signature}/ecdsa/doc.go (100%) rename ecc/bn254/{signatures => signature}/ecdsa/ecdsa.go (92%) rename ecc/bn254/{signatures => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bn254/{signatures => signature}/ecdsa/marshal.go (100%) rename ecc/bn254/{signatures => signature}/ecdsa/marshal_test.go (100%) rename ecc/bn254/{signatures => signature}/schnorr/doc.go (100%) rename ecc/bn254/{signatures => signature}/schnorr/marshal.go (100%) rename ecc/bn254/{signatures => signature}/schnorr/marshal_test.go (100%) rename ecc/bn254/{signatures => signature}/schnorr/schnorr.go (92%) rename ecc/bn254/{signatures => signature}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bn254/signature/utils.go rename ecc/bw6-633/{signatures => signature}/bls/bls.go (92%) rename ecc/bw6-633/{signatures => signature}/bls/bls_test.go (100%) rename ecc/bw6-633/{signatures => signature}/bls/doc.go (100%) rename ecc/bw6-633/{signatures => signature}/bls/marshal.go (100%) rename ecc/bw6-633/{signatures => signature}/bls/marshal_test.go (100%) rename ecc/bw6-633/{signatures => signature}/ecdsa/doc.go (100%) rename ecc/bw6-633/{signatures => signature}/ecdsa/ecdsa.go (92%) rename ecc/bw6-633/{signatures => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bw6-633/{signatures => signature}/ecdsa/marshal.go (100%) rename ecc/bw6-633/{signatures => signature}/ecdsa/marshal_test.go (100%) rename ecc/bw6-633/{signatures => signature}/schnorr/doc.go (100%) rename ecc/bw6-633/{signatures => signature}/schnorr/marshal.go (100%) rename ecc/bw6-633/{signatures => signature}/schnorr/marshal_test.go (100%) rename ecc/bw6-633/{signatures => signature}/schnorr/schnorr.go (92%) rename ecc/bw6-633/{signatures => signature}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bw6-633/signature/utils.go rename ecc/bw6-756/{signatures => signature}/bls/bls.go (92%) rename ecc/bw6-756/{signatures => signature}/bls/bls_test.go (100%) rename ecc/bw6-756/{signatures => signature}/bls/doc.go (100%) rename ecc/bw6-756/{signatures => signature}/bls/marshal.go (100%) rename ecc/bw6-756/{signatures => signature}/bls/marshal_test.go (100%) rename ecc/bw6-756/{signatures => signature}/ecdsa/doc.go (100%) rename ecc/bw6-756/{signatures => signature}/ecdsa/ecdsa.go (92%) rename ecc/bw6-756/{signatures => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bw6-756/{signatures => signature}/ecdsa/marshal.go (100%) rename ecc/bw6-756/{signatures => signature}/ecdsa/marshal_test.go (100%) rename ecc/bw6-756/{signatures => signature}/schnorr/doc.go (100%) rename ecc/bw6-756/{signatures => signature}/schnorr/marshal.go (100%) rename ecc/bw6-756/{signatures => signature}/schnorr/marshal_test.go (100%) rename ecc/bw6-756/{signatures => signature}/schnorr/schnorr.go (92%) rename ecc/bw6-756/{signatures => signature}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bw6-756/signature/utils.go rename ecc/bw6-761/{signatures => signature}/bls/bls.go (92%) rename ecc/bw6-761/{signatures => signature}/bls/bls_test.go (100%) rename ecc/bw6-761/{signatures => signature}/bls/doc.go (100%) rename ecc/bw6-761/{signatures => signature}/bls/marshal.go (100%) rename ecc/bw6-761/{signatures => signature}/bls/marshal_test.go (100%) rename ecc/bw6-761/{signatures => signature}/ecdsa/doc.go (100%) rename ecc/bw6-761/{signatures => signature}/ecdsa/ecdsa.go (92%) rename ecc/bw6-761/{signatures => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/bw6-761/{signatures => signature}/ecdsa/marshal.go (100%) rename ecc/bw6-761/{signatures => signature}/ecdsa/marshal_test.go (100%) rename ecc/bw6-761/{signatures => signature}/schnorr/doc.go (100%) rename ecc/bw6-761/{signatures => signature}/schnorr/marshal.go (100%) rename ecc/bw6-761/{signatures => signature}/schnorr/marshal_test.go (100%) rename ecc/bw6-761/{signatures => signature}/schnorr/schnorr.go (92%) rename ecc/bw6-761/{signatures => signature}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/bw6-761/signature/utils.go rename ecc/secp256k1/{signatures => signature}/ecdsa/doc.go (100%) rename ecc/secp256k1/{signatures => signature}/ecdsa/ecdsa.go (92%) rename ecc/secp256k1/{signatures => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/secp256k1/{signatures => signature}/ecdsa/marshal.go (100%) rename ecc/secp256k1/{signatures => signature}/ecdsa/marshal_test.go (100%) rename ecc/secp256k1/{signatures => signature}/schnorr/doc.go (100%) rename ecc/secp256k1/{signatures => signature}/schnorr/marshal.go (100%) rename ecc/secp256k1/{signatures => signature}/schnorr/marshal_test.go (100%) rename ecc/secp256k1/{signatures => signature}/schnorr/schnorr.go (92%) rename ecc/secp256k1/{signatures => signature}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/secp256k1/signature/utils.go rename ecc/stark-curve/{signatures => signature}/ecdsa/doc.go (100%) rename ecc/stark-curve/{signatures => signature}/ecdsa/ecdsa.go (92%) rename ecc/stark-curve/{signatures => signature}/ecdsa/ecdsa_test.go (100%) rename ecc/stark-curve/{signatures => signature}/ecdsa/marshal.go (100%) rename ecc/stark-curve/{signatures => signature}/ecdsa/marshal_test.go (100%) rename ecc/stark-curve/{signatures => signature}/schnorr/doc.go (100%) rename ecc/stark-curve/{signatures => signature}/schnorr/marshal.go (100%) rename ecc/stark-curve/{signatures => signature}/schnorr/marshal_test.go (100%) rename ecc/stark-curve/{signatures => signature}/schnorr/schnorr.go (92%) rename ecc/stark-curve/{signatures => signature}/schnorr/schnorr_test.go (100%) create mode 100644 ecc/stark-curve/signature/utils.go create mode 100644 internal/generator/signature/generate.go create mode 100644 internal/generator/signature/template/utils.go.tmpl diff --git a/ecc/bls12-377/signatures/bls/bls.go b/ecc/bls12-377/signature/bls/bls.go similarity index 92% rename from ecc/bls12-377/signatures/bls/bls.go rename to ecc/bls12-377/signature/bls/bls.go index cedf17d11..a4ad13069 100644 --- a/ecc/bls12-377/signatures/bls/bls.go +++ b/ecc/bls12-377/signature/bls/bls.go @@ -95,21 +95,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. diff --git a/ecc/bls12-377/signatures/bls/bls_test.go b/ecc/bls12-377/signature/bls/bls_test.go similarity index 100% rename from ecc/bls12-377/signatures/bls/bls_test.go rename to ecc/bls12-377/signature/bls/bls_test.go diff --git a/ecc/bls12-377/signatures/bls/doc.go b/ecc/bls12-377/signature/bls/doc.go similarity index 100% rename from ecc/bls12-377/signatures/bls/doc.go rename to ecc/bls12-377/signature/bls/doc.go diff --git a/ecc/bls12-377/signatures/bls/marshal.go b/ecc/bls12-377/signature/bls/marshal.go similarity index 100% rename from ecc/bls12-377/signatures/bls/marshal.go rename to ecc/bls12-377/signature/bls/marshal.go diff --git a/ecc/bls12-377/signatures/bls/marshal_test.go b/ecc/bls12-377/signature/bls/marshal_test.go similarity index 100% rename from ecc/bls12-377/signatures/bls/marshal_test.go rename to ecc/bls12-377/signature/bls/marshal_test.go diff --git a/ecc/bls12-377/signatures/ecdsa/doc.go b/ecc/bls12-377/signature/ecdsa/doc.go similarity index 100% rename from ecc/bls12-377/signatures/ecdsa/doc.go rename to ecc/bls12-377/signature/ecdsa/doc.go diff --git a/ecc/bls12-377/signatures/ecdsa/ecdsa.go b/ecc/bls12-377/signature/ecdsa/ecdsa.go similarity index 92% rename from ecc/bls12-377/signatures/ecdsa/ecdsa.go rename to ecc/bls12-377/signature/ecdsa/ecdsa.go index 274344c65..c0c1538e7 100644 --- a/ecc/bls12-377/signatures/ecdsa/ecdsa.go +++ b/ecc/bls12-377/signature/ecdsa/ecdsa.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-377" "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" + utils "github.com/consensys/gnark-crypto/ecc/bls12-377/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -228,9 +214,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -278,9 +264,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/ecc/bls12-377/signatures/ecdsa/ecdsa_test.go b/ecc/bls12-377/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls12-377/signatures/ecdsa/ecdsa_test.go rename to ecc/bls12-377/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bls12-377/signatures/ecdsa/marshal.go b/ecc/bls12-377/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bls12-377/signatures/ecdsa/marshal.go rename to ecc/bls12-377/signature/ecdsa/marshal.go diff --git a/ecc/bls12-377/signatures/ecdsa/marshal_test.go b/ecc/bls12-377/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls12-377/signatures/ecdsa/marshal_test.go rename to ecc/bls12-377/signature/ecdsa/marshal_test.go diff --git a/ecc/bls12-377/signatures/schnorr/doc.go b/ecc/bls12-377/signature/schnorr/doc.go similarity index 100% rename from ecc/bls12-377/signatures/schnorr/doc.go rename to ecc/bls12-377/signature/schnorr/doc.go diff --git a/ecc/bls12-377/signatures/schnorr/marshal.go b/ecc/bls12-377/signature/schnorr/marshal.go similarity index 100% rename from ecc/bls12-377/signatures/schnorr/marshal.go rename to ecc/bls12-377/signature/schnorr/marshal.go diff --git a/ecc/bls12-377/signatures/schnorr/marshal_test.go b/ecc/bls12-377/signature/schnorr/marshal_test.go similarity index 100% rename from ecc/bls12-377/signatures/schnorr/marshal_test.go rename to ecc/bls12-377/signature/schnorr/marshal_test.go diff --git a/ecc/bls12-377/signatures/schnorr/schnorr.go b/ecc/bls12-377/signature/schnorr/schnorr.go similarity index 92% rename from ecc/bls12-377/signatures/schnorr/schnorr.go rename to ecc/bls12-377/signature/schnorr/schnorr.go index c5ba8f633..b3318a761 100644 --- a/ecc/bls12-377/signatures/schnorr/schnorr.go +++ b/ecc/bls12-377/signature/schnorr/schnorr.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-377" "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" + utils "github.com/consensys/gnark-crypto/ecc/bls12-377/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -220,9 +206,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -273,9 +259,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/ecc/bls12-377/signatures/schnorr/schnorr_test.go b/ecc/bls12-377/signature/schnorr/schnorr_test.go similarity index 100% rename from ecc/bls12-377/signatures/schnorr/schnorr_test.go rename to ecc/bls12-377/signature/schnorr/schnorr_test.go diff --git a/ecc/bls12-377/signature/signature/utils.go b/ecc/bls12-377/signature/signature/utils.go new file mode 100644 index 000000000..145ed611a --- /dev/null +++ b/ecc/bls12-377/signature/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/ecc/bls12-377/signature/utils.go b/ecc/bls12-377/signature/utils.go new file mode 100644 index 000000000..145ed611a --- /dev/null +++ b/ecc/bls12-377/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/ecc/bls12-378/signatures/bls/bls.go b/ecc/bls12-378/signature/bls/bls.go similarity index 92% rename from ecc/bls12-378/signatures/bls/bls.go rename to ecc/bls12-378/signature/bls/bls.go index c98e6c2ca..85a040b22 100644 --- a/ecc/bls12-378/signatures/bls/bls.go +++ b/ecc/bls12-378/signature/bls/bls.go @@ -95,21 +95,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. diff --git a/ecc/bls12-378/signatures/bls/bls_test.go b/ecc/bls12-378/signature/bls/bls_test.go similarity index 100% rename from ecc/bls12-378/signatures/bls/bls_test.go rename to ecc/bls12-378/signature/bls/bls_test.go diff --git a/ecc/bls12-378/signatures/bls/doc.go b/ecc/bls12-378/signature/bls/doc.go similarity index 100% rename from ecc/bls12-378/signatures/bls/doc.go rename to ecc/bls12-378/signature/bls/doc.go diff --git a/ecc/bls12-378/signatures/bls/marshal.go b/ecc/bls12-378/signature/bls/marshal.go similarity index 100% rename from ecc/bls12-378/signatures/bls/marshal.go rename to ecc/bls12-378/signature/bls/marshal.go diff --git a/ecc/bls12-378/signatures/bls/marshal_test.go b/ecc/bls12-378/signature/bls/marshal_test.go similarity index 100% rename from ecc/bls12-378/signatures/bls/marshal_test.go rename to ecc/bls12-378/signature/bls/marshal_test.go diff --git a/ecc/bls12-378/signatures/ecdsa/doc.go b/ecc/bls12-378/signature/ecdsa/doc.go similarity index 100% rename from ecc/bls12-378/signatures/ecdsa/doc.go rename to ecc/bls12-378/signature/ecdsa/doc.go diff --git a/ecc/bls12-378/signatures/ecdsa/ecdsa.go b/ecc/bls12-378/signature/ecdsa/ecdsa.go similarity index 92% rename from ecc/bls12-378/signatures/ecdsa/ecdsa.go rename to ecc/bls12-378/signature/ecdsa/ecdsa.go index 3035e2b92..85cf0b066 100644 --- a/ecc/bls12-378/signatures/ecdsa/ecdsa.go +++ b/ecc/bls12-378/signature/ecdsa/ecdsa.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-378" "github.com/consensys/gnark-crypto/ecc/bls12-378/fp" "github.com/consensys/gnark-crypto/ecc/bls12-378/fr" + utils "github.com/consensys/gnark-crypto/ecc/bls12-378/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -228,9 +214,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -278,9 +264,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/ecc/bls12-378/signatures/ecdsa/ecdsa_test.go b/ecc/bls12-378/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls12-378/signatures/ecdsa/ecdsa_test.go rename to ecc/bls12-378/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bls12-378/signatures/ecdsa/marshal.go b/ecc/bls12-378/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bls12-378/signatures/ecdsa/marshal.go rename to ecc/bls12-378/signature/ecdsa/marshal.go diff --git a/ecc/bls12-378/signatures/ecdsa/marshal_test.go b/ecc/bls12-378/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls12-378/signatures/ecdsa/marshal_test.go rename to ecc/bls12-378/signature/ecdsa/marshal_test.go diff --git a/ecc/bls12-378/signatures/schnorr/doc.go b/ecc/bls12-378/signature/schnorr/doc.go similarity index 100% rename from ecc/bls12-378/signatures/schnorr/doc.go rename to ecc/bls12-378/signature/schnorr/doc.go diff --git a/ecc/bls12-378/signatures/schnorr/marshal.go b/ecc/bls12-378/signature/schnorr/marshal.go similarity index 100% rename from ecc/bls12-378/signatures/schnorr/marshal.go rename to ecc/bls12-378/signature/schnorr/marshal.go diff --git a/ecc/bls12-378/signatures/schnorr/marshal_test.go b/ecc/bls12-378/signature/schnorr/marshal_test.go similarity index 100% rename from ecc/bls12-378/signatures/schnorr/marshal_test.go rename to ecc/bls12-378/signature/schnorr/marshal_test.go diff --git a/ecc/bls12-378/signatures/schnorr/schnorr.go b/ecc/bls12-378/signature/schnorr/schnorr.go similarity index 92% rename from ecc/bls12-378/signatures/schnorr/schnorr.go rename to ecc/bls12-378/signature/schnorr/schnorr.go index f992d5b17..9949486ee 100644 --- a/ecc/bls12-378/signatures/schnorr/schnorr.go +++ b/ecc/bls12-378/signature/schnorr/schnorr.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-378" "github.com/consensys/gnark-crypto/ecc/bls12-378/fp" "github.com/consensys/gnark-crypto/ecc/bls12-378/fr" + utils "github.com/consensys/gnark-crypto/ecc/bls12-378/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -220,9 +206,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -273,9 +259,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/ecc/bls12-378/signatures/schnorr/schnorr_test.go b/ecc/bls12-378/signature/schnorr/schnorr_test.go similarity index 100% rename from ecc/bls12-378/signatures/schnorr/schnorr_test.go rename to ecc/bls12-378/signature/schnorr/schnorr_test.go diff --git a/ecc/bls12-378/signature/utils.go b/ecc/bls12-378/signature/utils.go new file mode 100644 index 000000000..de7631a6c --- /dev/null +++ b/ecc/bls12-378/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-378/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/ecc/bls12-381/signatures/bls/bls.go b/ecc/bls12-381/signature/bls/bls.go similarity index 92% rename from ecc/bls12-381/signatures/bls/bls.go rename to ecc/bls12-381/signature/bls/bls.go index bebca876b..a9a96eb97 100644 --- a/ecc/bls12-381/signatures/bls/bls.go +++ b/ecc/bls12-381/signature/bls/bls.go @@ -95,21 +95,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. diff --git a/ecc/bls12-381/signatures/bls/bls_test.go b/ecc/bls12-381/signature/bls/bls_test.go similarity index 100% rename from ecc/bls12-381/signatures/bls/bls_test.go rename to ecc/bls12-381/signature/bls/bls_test.go diff --git a/ecc/bls12-381/signatures/bls/doc.go b/ecc/bls12-381/signature/bls/doc.go similarity index 100% rename from ecc/bls12-381/signatures/bls/doc.go rename to ecc/bls12-381/signature/bls/doc.go diff --git a/ecc/bls12-381/signatures/bls/marshal.go b/ecc/bls12-381/signature/bls/marshal.go similarity index 100% rename from ecc/bls12-381/signatures/bls/marshal.go rename to ecc/bls12-381/signature/bls/marshal.go diff --git a/ecc/bls12-381/signatures/bls/marshal_test.go b/ecc/bls12-381/signature/bls/marshal_test.go similarity index 100% rename from ecc/bls12-381/signatures/bls/marshal_test.go rename to ecc/bls12-381/signature/bls/marshal_test.go diff --git a/ecc/bls12-381/signatures/ecdsa/doc.go b/ecc/bls12-381/signature/ecdsa/doc.go similarity index 100% rename from ecc/bls12-381/signatures/ecdsa/doc.go rename to ecc/bls12-381/signature/ecdsa/doc.go diff --git a/ecc/bls12-381/signatures/ecdsa/ecdsa.go b/ecc/bls12-381/signature/ecdsa/ecdsa.go similarity index 92% rename from ecc/bls12-381/signatures/ecdsa/ecdsa.go rename to ecc/bls12-381/signature/ecdsa/ecdsa.go index 4af89070e..cbf2e42c8 100644 --- a/ecc/bls12-381/signatures/ecdsa/ecdsa.go +++ b/ecc/bls12-381/signature/ecdsa/ecdsa.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + utils "github.com/consensys/gnark-crypto/ecc/bls12-381/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -228,9 +214,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -278,9 +264,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/ecc/bls12-381/signatures/ecdsa/ecdsa_test.go b/ecc/bls12-381/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls12-381/signatures/ecdsa/ecdsa_test.go rename to ecc/bls12-381/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bls12-381/signatures/ecdsa/marshal.go b/ecc/bls12-381/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bls12-381/signatures/ecdsa/marshal.go rename to ecc/bls12-381/signature/ecdsa/marshal.go diff --git a/ecc/bls12-381/signatures/ecdsa/marshal_test.go b/ecc/bls12-381/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls12-381/signatures/ecdsa/marshal_test.go rename to ecc/bls12-381/signature/ecdsa/marshal_test.go diff --git a/ecc/bls12-381/signatures/schnorr/doc.go b/ecc/bls12-381/signature/schnorr/doc.go similarity index 100% rename from ecc/bls12-381/signatures/schnorr/doc.go rename to ecc/bls12-381/signature/schnorr/doc.go diff --git a/ecc/bls12-381/signatures/schnorr/marshal.go b/ecc/bls12-381/signature/schnorr/marshal.go similarity index 100% rename from ecc/bls12-381/signatures/schnorr/marshal.go rename to ecc/bls12-381/signature/schnorr/marshal.go diff --git a/ecc/bls12-381/signatures/schnorr/marshal_test.go b/ecc/bls12-381/signature/schnorr/marshal_test.go similarity index 100% rename from ecc/bls12-381/signatures/schnorr/marshal_test.go rename to ecc/bls12-381/signature/schnorr/marshal_test.go diff --git a/ecc/bls12-381/signatures/schnorr/schnorr.go b/ecc/bls12-381/signature/schnorr/schnorr.go similarity index 92% rename from ecc/bls12-381/signatures/schnorr/schnorr.go rename to ecc/bls12-381/signature/schnorr/schnorr.go index 6507ee5b4..a4617d15f 100644 --- a/ecc/bls12-381/signatures/schnorr/schnorr.go +++ b/ecc/bls12-381/signature/schnorr/schnorr.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + utils "github.com/consensys/gnark-crypto/ecc/bls12-381/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -220,9 +206,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -273,9 +259,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/ecc/bls12-381/signatures/schnorr/schnorr_test.go b/ecc/bls12-381/signature/schnorr/schnorr_test.go similarity index 100% rename from ecc/bls12-381/signatures/schnorr/schnorr_test.go rename to ecc/bls12-381/signature/schnorr/schnorr_test.go diff --git a/ecc/bls12-381/signature/utils.go b/ecc/bls12-381/signature/utils.go new file mode 100644 index 000000000..2dced4b1b --- /dev/null +++ b/ecc/bls12-381/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/ecc/bls24-315/signatures/bls/bls.go b/ecc/bls24-315/signature/bls/bls.go similarity index 92% rename from ecc/bls24-315/signatures/bls/bls.go rename to ecc/bls24-315/signature/bls/bls.go index ff9c24da2..1cb69259a 100644 --- a/ecc/bls24-315/signatures/bls/bls.go +++ b/ecc/bls24-315/signature/bls/bls.go @@ -95,21 +95,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. diff --git a/ecc/bls24-315/signatures/bls/bls_test.go b/ecc/bls24-315/signature/bls/bls_test.go similarity index 100% rename from ecc/bls24-315/signatures/bls/bls_test.go rename to ecc/bls24-315/signature/bls/bls_test.go diff --git a/ecc/bls24-315/signatures/bls/doc.go b/ecc/bls24-315/signature/bls/doc.go similarity index 100% rename from ecc/bls24-315/signatures/bls/doc.go rename to ecc/bls24-315/signature/bls/doc.go diff --git a/ecc/bls24-315/signatures/bls/marshal.go b/ecc/bls24-315/signature/bls/marshal.go similarity index 100% rename from ecc/bls24-315/signatures/bls/marshal.go rename to ecc/bls24-315/signature/bls/marshal.go diff --git a/ecc/bls24-315/signatures/bls/marshal_test.go b/ecc/bls24-315/signature/bls/marshal_test.go similarity index 100% rename from ecc/bls24-315/signatures/bls/marshal_test.go rename to ecc/bls24-315/signature/bls/marshal_test.go diff --git a/ecc/bls24-315/signatures/ecdsa/doc.go b/ecc/bls24-315/signature/ecdsa/doc.go similarity index 100% rename from ecc/bls24-315/signatures/ecdsa/doc.go rename to ecc/bls24-315/signature/ecdsa/doc.go diff --git a/ecc/bls24-315/signatures/ecdsa/ecdsa.go b/ecc/bls24-315/signature/ecdsa/ecdsa.go similarity index 92% rename from ecc/bls24-315/signatures/ecdsa/ecdsa.go rename to ecc/bls24-315/signature/ecdsa/ecdsa.go index 8ca4a8071..01b39bba3 100644 --- a/ecc/bls24-315/signatures/ecdsa/ecdsa.go +++ b/ecc/bls24-315/signature/ecdsa/ecdsa.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls24-315" "github.com/consensys/gnark-crypto/ecc/bls24-315/fp" "github.com/consensys/gnark-crypto/ecc/bls24-315/fr" + utils "github.com/consensys/gnark-crypto/ecc/bls24-315/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -228,9 +214,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -278,9 +264,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/ecc/bls24-315/signatures/ecdsa/ecdsa_test.go b/ecc/bls24-315/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls24-315/signatures/ecdsa/ecdsa_test.go rename to ecc/bls24-315/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bls24-315/signatures/ecdsa/marshal.go b/ecc/bls24-315/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bls24-315/signatures/ecdsa/marshal.go rename to ecc/bls24-315/signature/ecdsa/marshal.go diff --git a/ecc/bls24-315/signatures/ecdsa/marshal_test.go b/ecc/bls24-315/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls24-315/signatures/ecdsa/marshal_test.go rename to ecc/bls24-315/signature/ecdsa/marshal_test.go diff --git a/ecc/bls24-315/signatures/schnorr/doc.go b/ecc/bls24-315/signature/schnorr/doc.go similarity index 100% rename from ecc/bls24-315/signatures/schnorr/doc.go rename to ecc/bls24-315/signature/schnorr/doc.go diff --git a/ecc/bls24-315/signatures/schnorr/marshal.go b/ecc/bls24-315/signature/schnorr/marshal.go similarity index 100% rename from ecc/bls24-315/signatures/schnorr/marshal.go rename to ecc/bls24-315/signature/schnorr/marshal.go diff --git a/ecc/bls24-315/signatures/schnorr/marshal_test.go b/ecc/bls24-315/signature/schnorr/marshal_test.go similarity index 100% rename from ecc/bls24-315/signatures/schnorr/marshal_test.go rename to ecc/bls24-315/signature/schnorr/marshal_test.go diff --git a/ecc/bls24-315/signatures/schnorr/schnorr.go b/ecc/bls24-315/signature/schnorr/schnorr.go similarity index 92% rename from ecc/bls24-315/signatures/schnorr/schnorr.go rename to ecc/bls24-315/signature/schnorr/schnorr.go index 67058ccc5..e142038b8 100644 --- a/ecc/bls24-315/signatures/schnorr/schnorr.go +++ b/ecc/bls24-315/signature/schnorr/schnorr.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls24-315" "github.com/consensys/gnark-crypto/ecc/bls24-315/fp" "github.com/consensys/gnark-crypto/ecc/bls24-315/fr" + utils "github.com/consensys/gnark-crypto/ecc/bls24-315/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -220,9 +206,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -273,9 +259,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/ecc/bls24-315/signatures/schnorr/schnorr_test.go b/ecc/bls24-315/signature/schnorr/schnorr_test.go similarity index 100% rename from ecc/bls24-315/signatures/schnorr/schnorr_test.go rename to ecc/bls24-315/signature/schnorr/schnorr_test.go diff --git a/ecc/bls24-315/signature/utils.go b/ecc/bls24-315/signature/utils.go new file mode 100644 index 000000000..7128cecb4 --- /dev/null +++ b/ecc/bls24-315/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls24-315/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/ecc/bls24-317/signatures/bls/bls.go b/ecc/bls24-317/signature/bls/bls.go similarity index 92% rename from ecc/bls24-317/signatures/bls/bls.go rename to ecc/bls24-317/signature/bls/bls.go index 2779a7596..9235cfb61 100644 --- a/ecc/bls24-317/signatures/bls/bls.go +++ b/ecc/bls24-317/signature/bls/bls.go @@ -95,21 +95,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. diff --git a/ecc/bls24-317/signatures/bls/bls_test.go b/ecc/bls24-317/signature/bls/bls_test.go similarity index 100% rename from ecc/bls24-317/signatures/bls/bls_test.go rename to ecc/bls24-317/signature/bls/bls_test.go diff --git a/ecc/bls24-317/signatures/bls/doc.go b/ecc/bls24-317/signature/bls/doc.go similarity index 100% rename from ecc/bls24-317/signatures/bls/doc.go rename to ecc/bls24-317/signature/bls/doc.go diff --git a/ecc/bls24-317/signatures/bls/marshal.go b/ecc/bls24-317/signature/bls/marshal.go similarity index 100% rename from ecc/bls24-317/signatures/bls/marshal.go rename to ecc/bls24-317/signature/bls/marshal.go diff --git a/ecc/bls24-317/signatures/bls/marshal_test.go b/ecc/bls24-317/signature/bls/marshal_test.go similarity index 100% rename from ecc/bls24-317/signatures/bls/marshal_test.go rename to ecc/bls24-317/signature/bls/marshal_test.go diff --git a/ecc/bls24-317/signatures/ecdsa/doc.go b/ecc/bls24-317/signature/ecdsa/doc.go similarity index 100% rename from ecc/bls24-317/signatures/ecdsa/doc.go rename to ecc/bls24-317/signature/ecdsa/doc.go diff --git a/ecc/bls24-317/signatures/ecdsa/ecdsa.go b/ecc/bls24-317/signature/ecdsa/ecdsa.go similarity index 92% rename from ecc/bls24-317/signatures/ecdsa/ecdsa.go rename to ecc/bls24-317/signature/ecdsa/ecdsa.go index dc0719492..692a1474c 100644 --- a/ecc/bls24-317/signatures/ecdsa/ecdsa.go +++ b/ecc/bls24-317/signature/ecdsa/ecdsa.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls24-317" "github.com/consensys/gnark-crypto/ecc/bls24-317/fp" "github.com/consensys/gnark-crypto/ecc/bls24-317/fr" + utils "github.com/consensys/gnark-crypto/ecc/bls24-317/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -228,9 +214,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -278,9 +264,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/ecc/bls24-317/signatures/ecdsa/ecdsa_test.go b/ecc/bls24-317/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bls24-317/signatures/ecdsa/ecdsa_test.go rename to ecc/bls24-317/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bls24-317/signatures/ecdsa/marshal.go b/ecc/bls24-317/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bls24-317/signatures/ecdsa/marshal.go rename to ecc/bls24-317/signature/ecdsa/marshal.go diff --git a/ecc/bls24-317/signatures/ecdsa/marshal_test.go b/ecc/bls24-317/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bls24-317/signatures/ecdsa/marshal_test.go rename to ecc/bls24-317/signature/ecdsa/marshal_test.go diff --git a/ecc/bls24-317/signatures/schnorr/doc.go b/ecc/bls24-317/signature/schnorr/doc.go similarity index 100% rename from ecc/bls24-317/signatures/schnorr/doc.go rename to ecc/bls24-317/signature/schnorr/doc.go diff --git a/ecc/bls24-317/signatures/schnorr/marshal.go b/ecc/bls24-317/signature/schnorr/marshal.go similarity index 100% rename from ecc/bls24-317/signatures/schnorr/marshal.go rename to ecc/bls24-317/signature/schnorr/marshal.go diff --git a/ecc/bls24-317/signatures/schnorr/marshal_test.go b/ecc/bls24-317/signature/schnorr/marshal_test.go similarity index 100% rename from ecc/bls24-317/signatures/schnorr/marshal_test.go rename to ecc/bls24-317/signature/schnorr/marshal_test.go diff --git a/ecc/bls24-317/signatures/schnorr/schnorr.go b/ecc/bls24-317/signature/schnorr/schnorr.go similarity index 92% rename from ecc/bls24-317/signatures/schnorr/schnorr.go rename to ecc/bls24-317/signature/schnorr/schnorr.go index 6b81eff6a..f451ef4e4 100644 --- a/ecc/bls24-317/signatures/schnorr/schnorr.go +++ b/ecc/bls24-317/signature/schnorr/schnorr.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls24-317" "github.com/consensys/gnark-crypto/ecc/bls24-317/fp" "github.com/consensys/gnark-crypto/ecc/bls24-317/fr" + utils "github.com/consensys/gnark-crypto/ecc/bls24-317/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -220,9 +206,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -273,9 +259,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/ecc/bls24-317/signatures/schnorr/schnorr_test.go b/ecc/bls24-317/signature/schnorr/schnorr_test.go similarity index 100% rename from ecc/bls24-317/signatures/schnorr/schnorr_test.go rename to ecc/bls24-317/signature/schnorr/schnorr_test.go diff --git a/ecc/bls24-317/signature/utils.go b/ecc/bls24-317/signature/utils.go new file mode 100644 index 000000000..72456b372 --- /dev/null +++ b/ecc/bls24-317/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls24-317/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/ecc/bn254/signatures/bls/bls.go b/ecc/bn254/signature/bls/bls.go similarity index 92% rename from ecc/bn254/signatures/bls/bls.go rename to ecc/bn254/signature/bls/bls.go index 8836c2efa..961555e8f 100644 --- a/ecc/bn254/signatures/bls/bls.go +++ b/ecc/bn254/signature/bls/bls.go @@ -95,21 +95,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. diff --git a/ecc/bn254/signatures/bls/bls_test.go b/ecc/bn254/signature/bls/bls_test.go similarity index 100% rename from ecc/bn254/signatures/bls/bls_test.go rename to ecc/bn254/signature/bls/bls_test.go diff --git a/ecc/bn254/signatures/bls/doc.go b/ecc/bn254/signature/bls/doc.go similarity index 100% rename from ecc/bn254/signatures/bls/doc.go rename to ecc/bn254/signature/bls/doc.go diff --git a/ecc/bn254/signatures/bls/marshal.go b/ecc/bn254/signature/bls/marshal.go similarity index 100% rename from ecc/bn254/signatures/bls/marshal.go rename to ecc/bn254/signature/bls/marshal.go diff --git a/ecc/bn254/signatures/bls/marshal_test.go b/ecc/bn254/signature/bls/marshal_test.go similarity index 100% rename from ecc/bn254/signatures/bls/marshal_test.go rename to ecc/bn254/signature/bls/marshal_test.go diff --git a/ecc/bn254/signatures/ecdsa/doc.go b/ecc/bn254/signature/ecdsa/doc.go similarity index 100% rename from ecc/bn254/signatures/ecdsa/doc.go rename to ecc/bn254/signature/ecdsa/doc.go diff --git a/ecc/bn254/signatures/ecdsa/ecdsa.go b/ecc/bn254/signature/ecdsa/ecdsa.go similarity index 92% rename from ecc/bn254/signatures/ecdsa/ecdsa.go rename to ecc/bn254/signature/ecdsa/ecdsa.go index 2907acda4..6dcd39f22 100644 --- a/ecc/bn254/signatures/ecdsa/ecdsa.go +++ b/ecc/bn254/signature/ecdsa/ecdsa.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/fr" + utils "github.com/consensys/gnark-crypto/ecc/bn254/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -228,9 +214,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -278,9 +264,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/ecc/bn254/signatures/ecdsa/ecdsa_test.go b/ecc/bn254/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bn254/signatures/ecdsa/ecdsa_test.go rename to ecc/bn254/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bn254/signatures/ecdsa/marshal.go b/ecc/bn254/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bn254/signatures/ecdsa/marshal.go rename to ecc/bn254/signature/ecdsa/marshal.go diff --git a/ecc/bn254/signatures/ecdsa/marshal_test.go b/ecc/bn254/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bn254/signatures/ecdsa/marshal_test.go rename to ecc/bn254/signature/ecdsa/marshal_test.go diff --git a/ecc/bn254/signatures/schnorr/doc.go b/ecc/bn254/signature/schnorr/doc.go similarity index 100% rename from ecc/bn254/signatures/schnorr/doc.go rename to ecc/bn254/signature/schnorr/doc.go diff --git a/ecc/bn254/signatures/schnorr/marshal.go b/ecc/bn254/signature/schnorr/marshal.go similarity index 100% rename from ecc/bn254/signatures/schnorr/marshal.go rename to ecc/bn254/signature/schnorr/marshal.go diff --git a/ecc/bn254/signatures/schnorr/marshal_test.go b/ecc/bn254/signature/schnorr/marshal_test.go similarity index 100% rename from ecc/bn254/signatures/schnorr/marshal_test.go rename to ecc/bn254/signature/schnorr/marshal_test.go diff --git a/ecc/bn254/signatures/schnorr/schnorr.go b/ecc/bn254/signature/schnorr/schnorr.go similarity index 92% rename from ecc/bn254/signatures/schnorr/schnorr.go rename to ecc/bn254/signature/schnorr/schnorr.go index 981259779..d185432b6 100644 --- a/ecc/bn254/signatures/schnorr/schnorr.go +++ b/ecc/bn254/signature/schnorr/schnorr.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/fr" + utils "github.com/consensys/gnark-crypto/ecc/bn254/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -220,9 +206,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -273,9 +259,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/ecc/bn254/signatures/schnorr/schnorr_test.go b/ecc/bn254/signature/schnorr/schnorr_test.go similarity index 100% rename from ecc/bn254/signatures/schnorr/schnorr_test.go rename to ecc/bn254/signature/schnorr/schnorr_test.go diff --git a/ecc/bn254/signature/utils.go b/ecc/bn254/signature/utils.go new file mode 100644 index 000000000..47fd0bcff --- /dev/null +++ b/ecc/bn254/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bn254/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/ecc/bw6-633/signatures/bls/bls.go b/ecc/bw6-633/signature/bls/bls.go similarity index 92% rename from ecc/bw6-633/signatures/bls/bls.go rename to ecc/bw6-633/signature/bls/bls.go index 271ab7f66..e36d97013 100644 --- a/ecc/bw6-633/signatures/bls/bls.go +++ b/ecc/bw6-633/signature/bls/bls.go @@ -95,21 +95,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. diff --git a/ecc/bw6-633/signatures/bls/bls_test.go b/ecc/bw6-633/signature/bls/bls_test.go similarity index 100% rename from ecc/bw6-633/signatures/bls/bls_test.go rename to ecc/bw6-633/signature/bls/bls_test.go diff --git a/ecc/bw6-633/signatures/bls/doc.go b/ecc/bw6-633/signature/bls/doc.go similarity index 100% rename from ecc/bw6-633/signatures/bls/doc.go rename to ecc/bw6-633/signature/bls/doc.go diff --git a/ecc/bw6-633/signatures/bls/marshal.go b/ecc/bw6-633/signature/bls/marshal.go similarity index 100% rename from ecc/bw6-633/signatures/bls/marshal.go rename to ecc/bw6-633/signature/bls/marshal.go diff --git a/ecc/bw6-633/signatures/bls/marshal_test.go b/ecc/bw6-633/signature/bls/marshal_test.go similarity index 100% rename from ecc/bw6-633/signatures/bls/marshal_test.go rename to ecc/bw6-633/signature/bls/marshal_test.go diff --git a/ecc/bw6-633/signatures/ecdsa/doc.go b/ecc/bw6-633/signature/ecdsa/doc.go similarity index 100% rename from ecc/bw6-633/signatures/ecdsa/doc.go rename to ecc/bw6-633/signature/ecdsa/doc.go diff --git a/ecc/bw6-633/signatures/ecdsa/ecdsa.go b/ecc/bw6-633/signature/ecdsa/ecdsa.go similarity index 92% rename from ecc/bw6-633/signatures/ecdsa/ecdsa.go rename to ecc/bw6-633/signature/ecdsa/ecdsa.go index 6bd55d1c0..9bc1fac9a 100644 --- a/ecc/bw6-633/signatures/ecdsa/ecdsa.go +++ b/ecc/bw6-633/signature/ecdsa/ecdsa.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-633" "github.com/consensys/gnark-crypto/ecc/bw6-633/fp" "github.com/consensys/gnark-crypto/ecc/bw6-633/fr" + utils "github.com/consensys/gnark-crypto/ecc/bw6-633/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -228,9 +214,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -278,9 +264,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/ecc/bw6-633/signatures/ecdsa/ecdsa_test.go b/ecc/bw6-633/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bw6-633/signatures/ecdsa/ecdsa_test.go rename to ecc/bw6-633/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bw6-633/signatures/ecdsa/marshal.go b/ecc/bw6-633/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bw6-633/signatures/ecdsa/marshal.go rename to ecc/bw6-633/signature/ecdsa/marshal.go diff --git a/ecc/bw6-633/signatures/ecdsa/marshal_test.go b/ecc/bw6-633/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bw6-633/signatures/ecdsa/marshal_test.go rename to ecc/bw6-633/signature/ecdsa/marshal_test.go diff --git a/ecc/bw6-633/signatures/schnorr/doc.go b/ecc/bw6-633/signature/schnorr/doc.go similarity index 100% rename from ecc/bw6-633/signatures/schnorr/doc.go rename to ecc/bw6-633/signature/schnorr/doc.go diff --git a/ecc/bw6-633/signatures/schnorr/marshal.go b/ecc/bw6-633/signature/schnorr/marshal.go similarity index 100% rename from ecc/bw6-633/signatures/schnorr/marshal.go rename to ecc/bw6-633/signature/schnorr/marshal.go diff --git a/ecc/bw6-633/signatures/schnorr/marshal_test.go b/ecc/bw6-633/signature/schnorr/marshal_test.go similarity index 100% rename from ecc/bw6-633/signatures/schnorr/marshal_test.go rename to ecc/bw6-633/signature/schnorr/marshal_test.go diff --git a/ecc/bw6-633/signatures/schnorr/schnorr.go b/ecc/bw6-633/signature/schnorr/schnorr.go similarity index 92% rename from ecc/bw6-633/signatures/schnorr/schnorr.go rename to ecc/bw6-633/signature/schnorr/schnorr.go index b13c510c6..96b5bb6d0 100644 --- a/ecc/bw6-633/signatures/schnorr/schnorr.go +++ b/ecc/bw6-633/signature/schnorr/schnorr.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-633" "github.com/consensys/gnark-crypto/ecc/bw6-633/fp" "github.com/consensys/gnark-crypto/ecc/bw6-633/fr" + utils "github.com/consensys/gnark-crypto/ecc/bw6-633/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -220,9 +206,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -273,9 +259,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/ecc/bw6-633/signatures/schnorr/schnorr_test.go b/ecc/bw6-633/signature/schnorr/schnorr_test.go similarity index 100% rename from ecc/bw6-633/signatures/schnorr/schnorr_test.go rename to ecc/bw6-633/signature/schnorr/schnorr_test.go diff --git a/ecc/bw6-633/signature/utils.go b/ecc/bw6-633/signature/utils.go new file mode 100644 index 000000000..eb8b9eba9 --- /dev/null +++ b/ecc/bw6-633/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bw6-633/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/ecc/bw6-756/signatures/bls/bls.go b/ecc/bw6-756/signature/bls/bls.go similarity index 92% rename from ecc/bw6-756/signatures/bls/bls.go rename to ecc/bw6-756/signature/bls/bls.go index dcf841edd..ac30c208e 100644 --- a/ecc/bw6-756/signatures/bls/bls.go +++ b/ecc/bw6-756/signature/bls/bls.go @@ -95,21 +95,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. diff --git a/ecc/bw6-756/signatures/bls/bls_test.go b/ecc/bw6-756/signature/bls/bls_test.go similarity index 100% rename from ecc/bw6-756/signatures/bls/bls_test.go rename to ecc/bw6-756/signature/bls/bls_test.go diff --git a/ecc/bw6-756/signatures/bls/doc.go b/ecc/bw6-756/signature/bls/doc.go similarity index 100% rename from ecc/bw6-756/signatures/bls/doc.go rename to ecc/bw6-756/signature/bls/doc.go diff --git a/ecc/bw6-756/signatures/bls/marshal.go b/ecc/bw6-756/signature/bls/marshal.go similarity index 100% rename from ecc/bw6-756/signatures/bls/marshal.go rename to ecc/bw6-756/signature/bls/marshal.go diff --git a/ecc/bw6-756/signatures/bls/marshal_test.go b/ecc/bw6-756/signature/bls/marshal_test.go similarity index 100% rename from ecc/bw6-756/signatures/bls/marshal_test.go rename to ecc/bw6-756/signature/bls/marshal_test.go diff --git a/ecc/bw6-756/signatures/ecdsa/doc.go b/ecc/bw6-756/signature/ecdsa/doc.go similarity index 100% rename from ecc/bw6-756/signatures/ecdsa/doc.go rename to ecc/bw6-756/signature/ecdsa/doc.go diff --git a/ecc/bw6-756/signatures/ecdsa/ecdsa.go b/ecc/bw6-756/signature/ecdsa/ecdsa.go similarity index 92% rename from ecc/bw6-756/signatures/ecdsa/ecdsa.go rename to ecc/bw6-756/signature/ecdsa/ecdsa.go index 3e15ea055..c12ffdb6c 100644 --- a/ecc/bw6-756/signatures/ecdsa/ecdsa.go +++ b/ecc/bw6-756/signature/ecdsa/ecdsa.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-756" "github.com/consensys/gnark-crypto/ecc/bw6-756/fp" "github.com/consensys/gnark-crypto/ecc/bw6-756/fr" + utils "github.com/consensys/gnark-crypto/ecc/bw6-756/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -228,9 +214,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -278,9 +264,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/ecc/bw6-756/signatures/ecdsa/ecdsa_test.go b/ecc/bw6-756/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bw6-756/signatures/ecdsa/ecdsa_test.go rename to ecc/bw6-756/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bw6-756/signatures/ecdsa/marshal.go b/ecc/bw6-756/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bw6-756/signatures/ecdsa/marshal.go rename to ecc/bw6-756/signature/ecdsa/marshal.go diff --git a/ecc/bw6-756/signatures/ecdsa/marshal_test.go b/ecc/bw6-756/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bw6-756/signatures/ecdsa/marshal_test.go rename to ecc/bw6-756/signature/ecdsa/marshal_test.go diff --git a/ecc/bw6-756/signatures/schnorr/doc.go b/ecc/bw6-756/signature/schnorr/doc.go similarity index 100% rename from ecc/bw6-756/signatures/schnorr/doc.go rename to ecc/bw6-756/signature/schnorr/doc.go diff --git a/ecc/bw6-756/signatures/schnorr/marshal.go b/ecc/bw6-756/signature/schnorr/marshal.go similarity index 100% rename from ecc/bw6-756/signatures/schnorr/marshal.go rename to ecc/bw6-756/signature/schnorr/marshal.go diff --git a/ecc/bw6-756/signatures/schnorr/marshal_test.go b/ecc/bw6-756/signature/schnorr/marshal_test.go similarity index 100% rename from ecc/bw6-756/signatures/schnorr/marshal_test.go rename to ecc/bw6-756/signature/schnorr/marshal_test.go diff --git a/ecc/bw6-756/signatures/schnorr/schnorr.go b/ecc/bw6-756/signature/schnorr/schnorr.go similarity index 92% rename from ecc/bw6-756/signatures/schnorr/schnorr.go rename to ecc/bw6-756/signature/schnorr/schnorr.go index 3f5ab1f14..ba5425b27 100644 --- a/ecc/bw6-756/signatures/schnorr/schnorr.go +++ b/ecc/bw6-756/signature/schnorr/schnorr.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-756" "github.com/consensys/gnark-crypto/ecc/bw6-756/fp" "github.com/consensys/gnark-crypto/ecc/bw6-756/fr" + utils "github.com/consensys/gnark-crypto/ecc/bw6-756/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -220,9 +206,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -273,9 +259,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/ecc/bw6-756/signatures/schnorr/schnorr_test.go b/ecc/bw6-756/signature/schnorr/schnorr_test.go similarity index 100% rename from ecc/bw6-756/signatures/schnorr/schnorr_test.go rename to ecc/bw6-756/signature/schnorr/schnorr_test.go diff --git a/ecc/bw6-756/signature/utils.go b/ecc/bw6-756/signature/utils.go new file mode 100644 index 000000000..1f6e961e3 --- /dev/null +++ b/ecc/bw6-756/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bw6-756/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/ecc/bw6-761/signatures/bls/bls.go b/ecc/bw6-761/signature/bls/bls.go similarity index 92% rename from ecc/bw6-761/signatures/bls/bls.go rename to ecc/bw6-761/signature/bls/bls.go index c575e10cb..9b907185f 100644 --- a/ecc/bw6-761/signatures/bls/bls.go +++ b/ecc/bw6-761/signature/bls/bls.go @@ -95,21 +95,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. diff --git a/ecc/bw6-761/signatures/bls/bls_test.go b/ecc/bw6-761/signature/bls/bls_test.go similarity index 100% rename from ecc/bw6-761/signatures/bls/bls_test.go rename to ecc/bw6-761/signature/bls/bls_test.go diff --git a/ecc/bw6-761/signatures/bls/doc.go b/ecc/bw6-761/signature/bls/doc.go similarity index 100% rename from ecc/bw6-761/signatures/bls/doc.go rename to ecc/bw6-761/signature/bls/doc.go diff --git a/ecc/bw6-761/signatures/bls/marshal.go b/ecc/bw6-761/signature/bls/marshal.go similarity index 100% rename from ecc/bw6-761/signatures/bls/marshal.go rename to ecc/bw6-761/signature/bls/marshal.go diff --git a/ecc/bw6-761/signatures/bls/marshal_test.go b/ecc/bw6-761/signature/bls/marshal_test.go similarity index 100% rename from ecc/bw6-761/signatures/bls/marshal_test.go rename to ecc/bw6-761/signature/bls/marshal_test.go diff --git a/ecc/bw6-761/signatures/ecdsa/doc.go b/ecc/bw6-761/signature/ecdsa/doc.go similarity index 100% rename from ecc/bw6-761/signatures/ecdsa/doc.go rename to ecc/bw6-761/signature/ecdsa/doc.go diff --git a/ecc/bw6-761/signatures/ecdsa/ecdsa.go b/ecc/bw6-761/signature/ecdsa/ecdsa.go similarity index 92% rename from ecc/bw6-761/signatures/ecdsa/ecdsa.go rename to ecc/bw6-761/signature/ecdsa/ecdsa.go index ac056f8d9..04e4a760a 100644 --- a/ecc/bw6-761/signatures/ecdsa/ecdsa.go +++ b/ecc/bw6-761/signature/ecdsa/ecdsa.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-761" "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" + utils "github.com/consensys/gnark-crypto/ecc/bw6-761/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -228,9 +214,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -278,9 +264,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/ecc/bw6-761/signatures/ecdsa/ecdsa_test.go b/ecc/bw6-761/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/bw6-761/signatures/ecdsa/ecdsa_test.go rename to ecc/bw6-761/signature/ecdsa/ecdsa_test.go diff --git a/ecc/bw6-761/signatures/ecdsa/marshal.go b/ecc/bw6-761/signature/ecdsa/marshal.go similarity index 100% rename from ecc/bw6-761/signatures/ecdsa/marshal.go rename to ecc/bw6-761/signature/ecdsa/marshal.go diff --git a/ecc/bw6-761/signatures/ecdsa/marshal_test.go b/ecc/bw6-761/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/bw6-761/signatures/ecdsa/marshal_test.go rename to ecc/bw6-761/signature/ecdsa/marshal_test.go diff --git a/ecc/bw6-761/signatures/schnorr/doc.go b/ecc/bw6-761/signature/schnorr/doc.go similarity index 100% rename from ecc/bw6-761/signatures/schnorr/doc.go rename to ecc/bw6-761/signature/schnorr/doc.go diff --git a/ecc/bw6-761/signatures/schnorr/marshal.go b/ecc/bw6-761/signature/schnorr/marshal.go similarity index 100% rename from ecc/bw6-761/signatures/schnorr/marshal.go rename to ecc/bw6-761/signature/schnorr/marshal.go diff --git a/ecc/bw6-761/signatures/schnorr/marshal_test.go b/ecc/bw6-761/signature/schnorr/marshal_test.go similarity index 100% rename from ecc/bw6-761/signatures/schnorr/marshal_test.go rename to ecc/bw6-761/signature/schnorr/marshal_test.go diff --git a/ecc/bw6-761/signatures/schnorr/schnorr.go b/ecc/bw6-761/signature/schnorr/schnorr.go similarity index 92% rename from ecc/bw6-761/signatures/schnorr/schnorr.go rename to ecc/bw6-761/signature/schnorr/schnorr.go index bb9245e48..d0afbcb23 100644 --- a/ecc/bw6-761/signatures/schnorr/schnorr.go +++ b/ecc/bw6-761/signature/schnorr/schnorr.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-761" "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" + utils "github.com/consensys/gnark-crypto/ecc/bw6-761/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -220,9 +206,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -273,9 +259,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/ecc/bw6-761/signatures/schnorr/schnorr_test.go b/ecc/bw6-761/signature/schnorr/schnorr_test.go similarity index 100% rename from ecc/bw6-761/signatures/schnorr/schnorr_test.go rename to ecc/bw6-761/signature/schnorr/schnorr_test.go diff --git a/ecc/bw6-761/signature/utils.go b/ecc/bw6-761/signature/utils.go new file mode 100644 index 000000000..fd4467c7b --- /dev/null +++ b/ecc/bw6-761/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/ecc/secp256k1/signatures/ecdsa/doc.go b/ecc/secp256k1/signature/ecdsa/doc.go similarity index 100% rename from ecc/secp256k1/signatures/ecdsa/doc.go rename to ecc/secp256k1/signature/ecdsa/doc.go diff --git a/ecc/secp256k1/signatures/ecdsa/ecdsa.go b/ecc/secp256k1/signature/ecdsa/ecdsa.go similarity index 92% rename from ecc/secp256k1/signatures/ecdsa/ecdsa.go rename to ecc/secp256k1/signature/ecdsa/ecdsa.go index 799036a76..3f553321f 100644 --- a/ecc/secp256k1/signatures/ecdsa/ecdsa.go +++ b/ecc/secp256k1/signature/ecdsa/ecdsa.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/secp256k1" "github.com/consensys/gnark-crypto/ecc/secp256k1/fp" "github.com/consensys/gnark-crypto/ecc/secp256k1/fr" + utils "github.com/consensys/gnark-crypto/ecc/secp256k1/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -228,9 +214,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -278,9 +264,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/ecc/secp256k1/signatures/ecdsa/ecdsa_test.go b/ecc/secp256k1/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/secp256k1/signatures/ecdsa/ecdsa_test.go rename to ecc/secp256k1/signature/ecdsa/ecdsa_test.go diff --git a/ecc/secp256k1/signatures/ecdsa/marshal.go b/ecc/secp256k1/signature/ecdsa/marshal.go similarity index 100% rename from ecc/secp256k1/signatures/ecdsa/marshal.go rename to ecc/secp256k1/signature/ecdsa/marshal.go diff --git a/ecc/secp256k1/signatures/ecdsa/marshal_test.go b/ecc/secp256k1/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/secp256k1/signatures/ecdsa/marshal_test.go rename to ecc/secp256k1/signature/ecdsa/marshal_test.go diff --git a/ecc/secp256k1/signatures/schnorr/doc.go b/ecc/secp256k1/signature/schnorr/doc.go similarity index 100% rename from ecc/secp256k1/signatures/schnorr/doc.go rename to ecc/secp256k1/signature/schnorr/doc.go diff --git a/ecc/secp256k1/signatures/schnorr/marshal.go b/ecc/secp256k1/signature/schnorr/marshal.go similarity index 100% rename from ecc/secp256k1/signatures/schnorr/marshal.go rename to ecc/secp256k1/signature/schnorr/marshal.go diff --git a/ecc/secp256k1/signatures/schnorr/marshal_test.go b/ecc/secp256k1/signature/schnorr/marshal_test.go similarity index 100% rename from ecc/secp256k1/signatures/schnorr/marshal_test.go rename to ecc/secp256k1/signature/schnorr/marshal_test.go diff --git a/ecc/secp256k1/signatures/schnorr/schnorr.go b/ecc/secp256k1/signature/schnorr/schnorr.go similarity index 92% rename from ecc/secp256k1/signatures/schnorr/schnorr.go rename to ecc/secp256k1/signature/schnorr/schnorr.go index 359d3332d..6cf43a1d4 100644 --- a/ecc/secp256k1/signatures/schnorr/schnorr.go +++ b/ecc/secp256k1/signature/schnorr/schnorr.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/secp256k1" "github.com/consensys/gnark-crypto/ecc/secp256k1/fp" "github.com/consensys/gnark-crypto/ecc/secp256k1/fr" + utils "github.com/consensys/gnark-crypto/ecc/secp256k1/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -220,9 +206,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -273,9 +259,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/ecc/secp256k1/signatures/schnorr/schnorr_test.go b/ecc/secp256k1/signature/schnorr/schnorr_test.go similarity index 100% rename from ecc/secp256k1/signatures/schnorr/schnorr_test.go rename to ecc/secp256k1/signature/schnorr/schnorr_test.go diff --git a/ecc/secp256k1/signature/utils.go b/ecc/secp256k1/signature/utils.go new file mode 100644 index 000000000..85cdb6e8a --- /dev/null +++ b/ecc/secp256k1/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/secp256k1/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/ecc/stark-curve/signatures/ecdsa/doc.go b/ecc/stark-curve/signature/ecdsa/doc.go similarity index 100% rename from ecc/stark-curve/signatures/ecdsa/doc.go rename to ecc/stark-curve/signature/ecdsa/doc.go diff --git a/ecc/stark-curve/signatures/ecdsa/ecdsa.go b/ecc/stark-curve/signature/ecdsa/ecdsa.go similarity index 92% rename from ecc/stark-curve/signatures/ecdsa/ecdsa.go rename to ecc/stark-curve/signature/ecdsa/ecdsa.go index 3a12ff123..49fd606f9 100644 --- a/ecc/stark-curve/signatures/ecdsa/ecdsa.go +++ b/ecc/stark-curve/signature/ecdsa/ecdsa.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/stark-curve" "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" "github.com/consensys/gnark-crypto/ecc/stark-curve/fr" + utils "github.com/consensys/gnark-crypto/ecc/stark-curve/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -228,9 +214,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -278,9 +264,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/ecc/stark-curve/signatures/ecdsa/ecdsa_test.go b/ecc/stark-curve/signature/ecdsa/ecdsa_test.go similarity index 100% rename from ecc/stark-curve/signatures/ecdsa/ecdsa_test.go rename to ecc/stark-curve/signature/ecdsa/ecdsa_test.go diff --git a/ecc/stark-curve/signatures/ecdsa/marshal.go b/ecc/stark-curve/signature/ecdsa/marshal.go similarity index 100% rename from ecc/stark-curve/signatures/ecdsa/marshal.go rename to ecc/stark-curve/signature/ecdsa/marshal.go diff --git a/ecc/stark-curve/signatures/ecdsa/marshal_test.go b/ecc/stark-curve/signature/ecdsa/marshal_test.go similarity index 100% rename from ecc/stark-curve/signatures/ecdsa/marshal_test.go rename to ecc/stark-curve/signature/ecdsa/marshal_test.go diff --git a/ecc/stark-curve/signatures/schnorr/doc.go b/ecc/stark-curve/signature/schnorr/doc.go similarity index 100% rename from ecc/stark-curve/signatures/schnorr/doc.go rename to ecc/stark-curve/signature/schnorr/doc.go diff --git a/ecc/stark-curve/signatures/schnorr/marshal.go b/ecc/stark-curve/signature/schnorr/marshal.go similarity index 100% rename from ecc/stark-curve/signatures/schnorr/marshal.go rename to ecc/stark-curve/signature/schnorr/marshal.go diff --git a/ecc/stark-curve/signatures/schnorr/marshal_test.go b/ecc/stark-curve/signature/schnorr/marshal_test.go similarity index 100% rename from ecc/stark-curve/signatures/schnorr/marshal_test.go rename to ecc/stark-curve/signature/schnorr/marshal_test.go diff --git a/ecc/stark-curve/signatures/schnorr/schnorr.go b/ecc/stark-curve/signature/schnorr/schnorr.go similarity index 92% rename from ecc/stark-curve/signatures/schnorr/schnorr.go rename to ecc/stark-curve/signature/schnorr/schnorr.go index b72c6645f..3bd408131 100644 --- a/ecc/stark-curve/signatures/schnorr/schnorr.go +++ b/ecc/stark-curve/signature/schnorr/schnorr.go @@ -29,6 +29,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/stark-curve" "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" "github.com/consensys/gnark-crypto/ecc/stark-curve/fr" + utils "github.com/consensys/gnark-crypto/ecc/stark-curve/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -92,21 +93,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -220,9 +206,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -273,9 +259,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/ecc/stark-curve/signatures/schnorr/schnorr_test.go b/ecc/stark-curve/signature/schnorr/schnorr_test.go similarity index 100% rename from ecc/stark-curve/signatures/schnorr/schnorr_test.go rename to ecc/stark-curve/signature/schnorr/schnorr_test.go diff --git a/ecc/stark-curve/signature/utils.go b/ecc/stark-curve/signature/utils.go new file mode 100644 index 000000000..759a3edaf --- /dev/null +++ b/ecc/stark-curve/signature/utils.go @@ -0,0 +1,38 @@ +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package signature + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/stark-curve/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} diff --git a/internal/generator/main.go b/internal/generator/main.go index e2e0d98dd..2cbbefadc 100644 --- a/internal/generator/main.go +++ b/internal/generator/main.go @@ -24,6 +24,7 @@ import ( "github.com/consensys/gnark-crypto/internal/generator/permutation" "github.com/consensys/gnark-crypto/internal/generator/plookup" "github.com/consensys/gnark-crypto/internal/generator/polynomial" + "github.com/consensys/gnark-crypto/internal/generator/signature" "github.com/consensys/gnark-crypto/internal/generator/signature/bls" "github.com/consensys/gnark-crypto/internal/generator/signature/ecdsa" "github.com/consensys/gnark-crypto/internal/generator/signature/schnorr" @@ -70,11 +71,14 @@ func main() { ElementType: "fr.Element", } + // generate utils for signatures + assertNoError(signature.Generate(conf, filepath.Join(curveDir, "signature"), bgen)) + // generate ecdsa signature - assertNoError(ecdsa.Generate(conf, filepath.Join(curveDir, "signatures"), bgen)) + assertNoError(ecdsa.Generate(conf, filepath.Join(curveDir, "signature"), bgen)) // generate schnorr signature - assertNoError(schnorr.Generate(conf, filepath.Join(curveDir, "signatures"), bgen)) + assertNoError(schnorr.Generate(conf, filepath.Join(curveDir, "signature"), bgen)) if conf.Equal(config.STARK_CURVE) { return // TODO @yelhousni @@ -88,7 +92,7 @@ func main() { } // generate bls signature - assertNoError(bls.Generate(conf, filepath.Join(curveDir, "signatures"), bgen)) + assertNoError(bls.Generate(conf, filepath.Join(curveDir, "signature"), bgen)) // generate tower of extension assertNoError(tower.Generate(conf, filepath.Join(curveDir, "internal", "fptower"), bgen)) diff --git a/internal/generator/signature/bls/template/bls.go.tmpl b/internal/generator/signature/bls/template/bls.go.tmpl index f29730102..dea55ee19 100644 --- a/internal/generator/signature/bls/template/bls.go.tmpl +++ b/internal/generator/signature/bls/template/bls.go.tmpl @@ -82,21 +82,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. diff --git a/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl b/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl index c5923ca8b..bde08a7ab 100644 --- a/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl +++ b/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl @@ -11,6 +11,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/{{ .Name }}" "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr" "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fp" + utils "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -83,21 +84,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -219,9 +205,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) return nil, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } s.Add(m, s). @@ -269,9 +255,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo return false, err } hramBin := hFunc.Sum(nil) - m = HashToInt(hramBin) + m = utils.HashToInt(hramBin) } else { - m = HashToInt(message) + m = utils.HashToInt(message) } u1 := new(big.Int).Mul(m, sInv) diff --git a/internal/generator/signature/generate.go b/internal/generator/signature/generate.go new file mode 100644 index 000000000..443f5465e --- /dev/null +++ b/internal/generator/signature/generate.go @@ -0,0 +1,18 @@ +package signature + +import ( + "path/filepath" + + "github.com/consensys/bavard" + "github.com/consensys/gnark-crypto/internal/generator/config" +) + +func Generate(conf config.Curve, baseDir string, bgen *bavard.BatchGenerator) error { + conf.Package = "signature" + + entries := []bavard.Entry{ + {File: filepath.Join(baseDir, "utils.go"), Templates: []string{"utils.go.tmpl"}}, + } + + return bgen.Generate(conf, conf.Package, "./signature/template", entries...) +} diff --git a/internal/generator/signature/schnorr/template/schnorr.go.tmpl b/internal/generator/signature/schnorr/template/schnorr.go.tmpl index 01facdf92..a109a88d2 100644 --- a/internal/generator/signature/schnorr/template/schnorr.go.tmpl +++ b/internal/generator/signature/schnorr/template/schnorr.go.tmpl @@ -11,6 +11,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/{{ .Name }}" "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr" "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fp" + utils "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/signature" "github.com/consensys/gnark-crypto/signature" ) @@ -83,21 +84,6 @@ func GenerateKey(rand io.Reader) (*PrivateKey, error) { return privateKey, nil } -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > sizeFr { - hash = hash[:sizeFr] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - sizeFr - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - type zr struct{} // Read replaces the contents of dst with zeros. It is safe for concurrent use. @@ -211,9 +197,9 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) + r = utils.HashToInt(hramBin) } else { - r = HashToInt(message) + r = utils.HashToInt(message) } s.Mul(scalar, r) @@ -264,9 +250,9 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo } hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) + e = utils.HashToInt(hramBin) } else { - e = HashToInt(message) + e = utils.HashToInt(message) } return e.Cmp(r) == 0, nil diff --git a/internal/generator/signature/template/utils.go.tmpl b/internal/generator/signature/template/utils.go.tmpl new file mode 100644 index 000000000..062b45c46 --- /dev/null +++ b/internal/generator/signature/template/utils.go.tmpl @@ -0,0 +1,20 @@ +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr" +) + +// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, +// we use the left-most bits of the hash to match the bit-length of the order of +// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. +func HashToInt(hash []byte) *big.Int { + if len(hash) > fr.Bytes { + hash = hash[:fr.Bytes] + } + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - fr.Bytes + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} From 55234cd34a64907031b2c7ca84756dd64dce000a Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 26 Jan 2023 21:19:17 +0100 Subject: [PATCH 10/13] revert(signature): remove old code --- ecc/bls12-377/signature/signature/utils.go | 38 ---------------------- 1 file changed, 38 deletions(-) delete mode 100644 ecc/bls12-377/signature/signature/utils.go diff --git a/ecc/bls12-377/signature/signature/utils.go b/ecc/bls12-377/signature/signature/utils.go deleted file mode 100644 index 145ed611a..000000000 --- a/ecc/bls12-377/signature/signature/utils.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package signature - -import ( - "math/big" - - "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" -) - -// HashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, -// we use the left-most bits of the hash to match the bit-length of the order of -// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. -func HashToInt(hash []byte) *big.Int { - if len(hash) > fr.Bytes { - hash = hash[:fr.Bytes] - } - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - fr.Bytes - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} From b3fe35d022ba0a71c687c450a1d17000fd4e377f Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 26 Jan 2023 21:51:49 +0100 Subject: [PATCH 11/13] revert(signature): remove old code --- signature/bls/bls.go | 18 +++++++++--------- signature/ecdsa/ecdsa.go | 22 +++++++++++----------- signature/schnorr/schnorr.go | 22 +++++++++++----------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/signature/bls/bls.go b/signature/bls/bls.go index 26e84ecc7..a2c8c96ad 100644 --- a/signature/bls/bls.go +++ b/signature/bls/bls.go @@ -20,15 +20,15 @@ import ( "io" "github.com/consensys/gnark-crypto/ecc" - bls_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signatures/bls" - bls_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signatures/bls" - bls_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signatures/bls" - bls_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signatures/bls" - bls_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signatures/bls" - bls_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signatures/bls" - bls_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signatures/bls" - bls_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signatures/bls" - bls_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signatures/bls" + bls_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signature/bls" + bls_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signature/bls" + bls_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signature/bls" + bls_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signature/bls" + bls_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signature/bls" + bls_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signature/bls" + bls_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signature/bls" + bls_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signature/bls" + bls_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signature/bls" "github.com/consensys/gnark-crypto/signature" ) diff --git a/signature/ecdsa/ecdsa.go b/signature/ecdsa/ecdsa.go index d103aab15..ffe16b590 100644 --- a/signature/ecdsa/ecdsa.go +++ b/signature/ecdsa/ecdsa.go @@ -20,17 +20,17 @@ import ( "io" "github.com/consensys/gnark-crypto/ecc" - ecdsa_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signatures/ecdsa" - ecdsa_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signatures/ecdsa" - ecdsa_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signatures/ecdsa" - ecdsa_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signatures/ecdsa" - ecdsa_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signatures/ecdsa" - ecdsa_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signatures/ecdsa" - ecdsa_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signatures/ecdsa" - ecdsa_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signatures/ecdsa" - ecdsa_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signatures/ecdsa" - ecdsa_secp256k1 "github.com/consensys/gnark-crypto/ecc/secp256k1/signatures/ecdsa" - ecdsa_starkcurve "github.com/consensys/gnark-crypto/ecc/stark-curve/signatures/ecdsa" + ecdsa_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signature/ecdsa" + ecdsa_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signature/ecdsa" + ecdsa_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signature/ecdsa" + ecdsa_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signature/ecdsa" + ecdsa_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signature/ecdsa" + ecdsa_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signature/ecdsa" + ecdsa_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signature/ecdsa" + ecdsa_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signature/ecdsa" + ecdsa_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signature/ecdsa" + ecdsa_secp256k1 "github.com/consensys/gnark-crypto/ecc/secp256k1/signature/ecdsa" + ecdsa_starkcurve "github.com/consensys/gnark-crypto/ecc/stark-curve/signature/ecdsa" "github.com/consensys/gnark-crypto/signature" ) diff --git a/signature/schnorr/schnorr.go b/signature/schnorr/schnorr.go index f7255d0f3..9c432cd4b 100644 --- a/signature/schnorr/schnorr.go +++ b/signature/schnorr/schnorr.go @@ -20,17 +20,17 @@ import ( "io" "github.com/consensys/gnark-crypto/ecc" - schnorr_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signatures/schnorr" - schnorr_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signatures/schnorr" - schnorr_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signatures/schnorr" - schnorr_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signatures/schnorr" - schnorr_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signatures/schnorr" - schnorr_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signatures/schnorr" - schnorr_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signatures/schnorr" - schnorr_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signatures/schnorr" - schnorr_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signatures/schnorr" - schnorr_secp256k1 "github.com/consensys/gnark-crypto/ecc/secp256k1/signatures/schnorr" - schnorr_starkcurve "github.com/consensys/gnark-crypto/ecc/stark-curve/signatures/schnorr" + schnorr_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/signature/schnorr" + schnorr_bls12378 "github.com/consensys/gnark-crypto/ecc/bls12-378/signature/schnorr" + schnorr_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/signature/schnorr" + schnorr_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/signature/schnorr" + schnorr_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/signature/schnorr" + schnorr_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/signature/schnorr" + schnorr_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/signature/schnorr" + schnorr_bw6756 "github.com/consensys/gnark-crypto/ecc/bw6-756/signature/schnorr" + schnorr_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/signature/schnorr" + schnorr_secp256k1 "github.com/consensys/gnark-crypto/ecc/secp256k1/signature/schnorr" + schnorr_starkcurve "github.com/consensys/gnark-crypto/ecc/stark-curve/signature/schnorr" "github.com/consensys/gnark-crypto/signature" ) From 1ebec7b351c7ca8b4ce786875f6f590e1606486a Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Fri, 27 Jan 2023 09:17:50 +0100 Subject: [PATCH 12/13] perf(ecdsa): no bigInt allocation --- ecc/bls12-377/signature/ecdsa/ecdsa.go | 4 ++-- ecc/bls12-378/signature/ecdsa/ecdsa.go | 4 ++-- ecc/bls12-381/signature/ecdsa/ecdsa.go | 4 ++-- ecc/bls24-315/signature/ecdsa/ecdsa.go | 4 ++-- ecc/bls24-317/signature/ecdsa/ecdsa.go | 4 ++-- ecc/bn254/signature/ecdsa/ecdsa.go | 4 ++-- ecc/bw6-633/signature/ecdsa/ecdsa.go | 4 ++-- ecc/bw6-756/signature/ecdsa/ecdsa.go | 4 ++-- ecc/bw6-761/signature/ecdsa/ecdsa.go | 4 ++-- ecc/secp256k1/signature/ecdsa/ecdsa.go | 4 ++-- ecc/stark-curve/signature/ecdsa/ecdsa.go | 4 ++-- internal/generator/signature/ecdsa/template/ecdsa.go.tmpl | 4 ++-- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/ecc/bls12-377/signature/ecdsa/ecdsa.go b/ecc/bls12-377/signature/ecdsa/ecdsa.go index 6f27e1535..cc13e8ac6 100644 --- a/ecc/bls12-377/signature/ecdsa/ecdsa.go +++ b/ecc/bls12-377/signature/ecdsa/ecdsa.go @@ -220,7 +220,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -270,7 +270,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) diff --git a/ecc/bls12-378/signature/ecdsa/ecdsa.go b/ecc/bls12-378/signature/ecdsa/ecdsa.go index bfee7fe4e..44c297cc8 100644 --- a/ecc/bls12-378/signature/ecdsa/ecdsa.go +++ b/ecc/bls12-378/signature/ecdsa/ecdsa.go @@ -220,7 +220,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -270,7 +270,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) diff --git a/ecc/bls12-381/signature/ecdsa/ecdsa.go b/ecc/bls12-381/signature/ecdsa/ecdsa.go index 82925c627..9039ee388 100644 --- a/ecc/bls12-381/signature/ecdsa/ecdsa.go +++ b/ecc/bls12-381/signature/ecdsa/ecdsa.go @@ -220,7 +220,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -270,7 +270,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) diff --git a/ecc/bls24-315/signature/ecdsa/ecdsa.go b/ecc/bls24-315/signature/ecdsa/ecdsa.go index c9fe0878f..e1309b2f3 100644 --- a/ecc/bls24-315/signature/ecdsa/ecdsa.go +++ b/ecc/bls24-315/signature/ecdsa/ecdsa.go @@ -220,7 +220,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -270,7 +270,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) diff --git a/ecc/bls24-317/signature/ecdsa/ecdsa.go b/ecc/bls24-317/signature/ecdsa/ecdsa.go index 97c553246..dfcbab66c 100644 --- a/ecc/bls24-317/signature/ecdsa/ecdsa.go +++ b/ecc/bls24-317/signature/ecdsa/ecdsa.go @@ -220,7 +220,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -270,7 +270,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) diff --git a/ecc/bn254/signature/ecdsa/ecdsa.go b/ecc/bn254/signature/ecdsa/ecdsa.go index e55205377..8593d6a72 100644 --- a/ecc/bn254/signature/ecdsa/ecdsa.go +++ b/ecc/bn254/signature/ecdsa/ecdsa.go @@ -220,7 +220,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -270,7 +270,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) diff --git a/ecc/bw6-633/signature/ecdsa/ecdsa.go b/ecc/bw6-633/signature/ecdsa/ecdsa.go index 67efe8ea1..f264a1e47 100644 --- a/ecc/bw6-633/signature/ecdsa/ecdsa.go +++ b/ecc/bw6-633/signature/ecdsa/ecdsa.go @@ -220,7 +220,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -270,7 +270,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) diff --git a/ecc/bw6-756/signature/ecdsa/ecdsa.go b/ecc/bw6-756/signature/ecdsa/ecdsa.go index 1131bb1f7..11c7725b5 100644 --- a/ecc/bw6-756/signature/ecdsa/ecdsa.go +++ b/ecc/bw6-756/signature/ecdsa/ecdsa.go @@ -220,7 +220,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -270,7 +270,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) diff --git a/ecc/bw6-761/signature/ecdsa/ecdsa.go b/ecc/bw6-761/signature/ecdsa/ecdsa.go index 8ad854c43..7a6669fca 100644 --- a/ecc/bw6-761/signature/ecdsa/ecdsa.go +++ b/ecc/bw6-761/signature/ecdsa/ecdsa.go @@ -220,7 +220,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -270,7 +270,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) diff --git a/ecc/secp256k1/signature/ecdsa/ecdsa.go b/ecc/secp256k1/signature/ecdsa/ecdsa.go index a2abdbbab..de7c735da 100644 --- a/ecc/secp256k1/signature/ecdsa/ecdsa.go +++ b/ecc/secp256k1/signature/ecdsa/ecdsa.go @@ -220,7 +220,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -270,7 +270,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) diff --git a/ecc/stark-curve/signature/ecdsa/ecdsa.go b/ecc/stark-curve/signature/ecdsa/ecdsa.go index bd1221196..4707f3219 100644 --- a/ecc/stark-curve/signature/ecdsa/ecdsa.go +++ b/ecc/stark-curve/signature/ecdsa/ecdsa.go @@ -220,7 +220,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -270,7 +270,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) diff --git a/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl b/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl index dd536c0e1..fd953cdf4 100644 --- a/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl +++ b/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl @@ -211,7 +211,7 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) } s.Mul(r, scalar) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) @@ -261,7 +261,7 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo sInv := new(big.Int).ModInverse(s, order) - m := new(big.Int) + var m *big.Int if hFunc != nil { // compute the hash of the message as an integer dataToHash := make([]byte, len(message)) From 0cc03c4860c1ff1284bc8060964b393e51f853ee Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Fri, 27 Jan 2023 13:23:53 +0100 Subject: [PATCH 13/13] fix(schnorr): enforce hash function as FS challenge --- ecc/bls12-377/signature/ecdsa/ecdsa.go | 3 - ecc/bls12-377/signature/schnorr/schnorr.go | 83 ++++++++++--------- .../signature/schnorr/schnorr_test.go | 22 ++--- ecc/bls12-378/signature/ecdsa/ecdsa.go | 3 - ecc/bls12-378/signature/schnorr/schnorr.go | 83 ++++++++++--------- .../signature/schnorr/schnorr_test.go | 22 ++--- ecc/bls12-381/signature/ecdsa/ecdsa.go | 3 - ecc/bls12-381/signature/schnorr/schnorr.go | 83 ++++++++++--------- .../signature/schnorr/schnorr_test.go | 22 ++--- ecc/bls24-315/signature/ecdsa/ecdsa.go | 3 - ecc/bls24-315/signature/schnorr/schnorr.go | 83 ++++++++++--------- .../signature/schnorr/schnorr_test.go | 22 ++--- ecc/bls24-317/signature/ecdsa/ecdsa.go | 3 - ecc/bls24-317/signature/schnorr/schnorr.go | 83 ++++++++++--------- .../signature/schnorr/schnorr_test.go | 22 ++--- ecc/bn254/signature/ecdsa/ecdsa.go | 3 - ecc/bn254/signature/schnorr/schnorr.go | 83 ++++++++++--------- ecc/bn254/signature/schnorr/schnorr_test.go | 22 ++--- ecc/bw6-633/signature/ecdsa/ecdsa.go | 3 - ecc/bw6-633/signature/schnorr/schnorr.go | 83 ++++++++++--------- ecc/bw6-633/signature/schnorr/schnorr_test.go | 22 ++--- ecc/bw6-756/signature/ecdsa/ecdsa.go | 3 - ecc/bw6-756/signature/schnorr/schnorr.go | 83 ++++++++++--------- ecc/bw6-756/signature/schnorr/schnorr_test.go | 22 ++--- ecc/bw6-761/signature/ecdsa/ecdsa.go | 3 - ecc/bw6-761/signature/schnorr/schnorr.go | 83 ++++++++++--------- ecc/bw6-761/signature/schnorr/schnorr_test.go | 22 ++--- ecc/secp256k1/signature/ecdsa/ecdsa.go | 3 - ecc/secp256k1/signature/schnorr/schnorr.go | 83 ++++++++++--------- .../signature/schnorr/schnorr_test.go | 22 ++--- ecc/stark-curve/signature/ecdsa/ecdsa.go | 3 - ecc/stark-curve/signature/schnorr/schnorr.go | 83 ++++++++++--------- .../signature/schnorr/schnorr_test.go | 22 ++--- .../signature/ecdsa/template/ecdsa.go.tmpl | 3 - .../schnorr/template/schnorr.go.tmpl | 83 ++++++++++--------- .../schnorr/template/schnorr.test.go.tmpl | 22 ++--- 36 files changed, 588 insertions(+), 708 deletions(-) diff --git a/ecc/bls12-377/signature/ecdsa/ecdsa.go b/ecc/bls12-377/signature/ecdsa/ecdsa.go index cc13e8ac6..395313d7f 100644 --- a/ecc/bls12-377/signature/ecdsa/ecdsa.go +++ b/ecc/bls12-377/signature/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls12-377/signature/schnorr/schnorr.go b/ecc/bls12-377/signature/schnorr/schnorr.go index 328b33516..bd0571b1b 100644 --- a/ecc/bls12-377/signature/schnorr/schnorr.go +++ b/ecc/bls12-377/signature/schnorr/schnorr.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -193,6 +193,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -207,27 +214,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bls12377.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -245,6 +248,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -260,27 +269,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bls12377.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/ecc/bls12-377/signature/schnorr/schnorr_test.go b/ecc/bls12-377/signature/schnorr/schnorr_test.go index 157c71856..68b7c8c57 100644 --- a/ecc/bls12-377/signature/schnorr/schnorr_test.go +++ b/ecc/bls12-377/signature/schnorr/schnorr_test.go @@ -46,20 +46,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[BLS12-377] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -71,9 +57,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -81,10 +68,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } } diff --git a/ecc/bls12-378/signature/ecdsa/ecdsa.go b/ecc/bls12-378/signature/ecdsa/ecdsa.go index 44c297cc8..57d13d572 100644 --- a/ecc/bls12-378/signature/ecdsa/ecdsa.go +++ b/ecc/bls12-378/signature/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls12-378/signature/schnorr/schnorr.go b/ecc/bls12-378/signature/schnorr/schnorr.go index 344c3f6f3..17ca91369 100644 --- a/ecc/bls12-378/signature/schnorr/schnorr.go +++ b/ecc/bls12-378/signature/schnorr/schnorr.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -193,6 +193,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -207,27 +214,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bls12378.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -245,6 +248,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -260,27 +269,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bls12378.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/ecc/bls12-378/signature/schnorr/schnorr_test.go b/ecc/bls12-378/signature/schnorr/schnorr_test.go index 12e42d9ca..69d54ce8f 100644 --- a/ecc/bls12-378/signature/schnorr/schnorr_test.go +++ b/ecc/bls12-378/signature/schnorr/schnorr_test.go @@ -46,20 +46,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[BLS12-378] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -71,9 +57,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -81,10 +68,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } } diff --git a/ecc/bls12-381/signature/ecdsa/ecdsa.go b/ecc/bls12-381/signature/ecdsa/ecdsa.go index 9039ee388..f110a9483 100644 --- a/ecc/bls12-381/signature/ecdsa/ecdsa.go +++ b/ecc/bls12-381/signature/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls12-381/signature/schnorr/schnorr.go b/ecc/bls12-381/signature/schnorr/schnorr.go index f1d16026f..a23d4cf37 100644 --- a/ecc/bls12-381/signature/schnorr/schnorr.go +++ b/ecc/bls12-381/signature/schnorr/schnorr.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -193,6 +193,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -207,27 +214,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bls12381.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -245,6 +248,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -260,27 +269,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bls12381.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/ecc/bls12-381/signature/schnorr/schnorr_test.go b/ecc/bls12-381/signature/schnorr/schnorr_test.go index 50d39e61b..ca692100c 100644 --- a/ecc/bls12-381/signature/schnorr/schnorr_test.go +++ b/ecc/bls12-381/signature/schnorr/schnorr_test.go @@ -46,20 +46,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[BLS12-381] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -71,9 +57,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -81,10 +68,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } } diff --git a/ecc/bls24-315/signature/ecdsa/ecdsa.go b/ecc/bls24-315/signature/ecdsa/ecdsa.go index e1309b2f3..1e419e34e 100644 --- a/ecc/bls24-315/signature/ecdsa/ecdsa.go +++ b/ecc/bls24-315/signature/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls24-315/signature/schnorr/schnorr.go b/ecc/bls24-315/signature/schnorr/schnorr.go index 83cb61540..8743a7dc7 100644 --- a/ecc/bls24-315/signature/schnorr/schnorr.go +++ b/ecc/bls24-315/signature/schnorr/schnorr.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -193,6 +193,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -207,27 +214,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bls24315.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -245,6 +248,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -260,27 +269,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bls24315.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/ecc/bls24-315/signature/schnorr/schnorr_test.go b/ecc/bls24-315/signature/schnorr/schnorr_test.go index aee5be60f..a36590b40 100644 --- a/ecc/bls24-315/signature/schnorr/schnorr_test.go +++ b/ecc/bls24-315/signature/schnorr/schnorr_test.go @@ -46,20 +46,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[BLS24-315] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -71,9 +57,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -81,10 +68,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } } diff --git a/ecc/bls24-317/signature/ecdsa/ecdsa.go b/ecc/bls24-317/signature/ecdsa/ecdsa.go index dfcbab66c..ce3ff756d 100644 --- a/ecc/bls24-317/signature/ecdsa/ecdsa.go +++ b/ecc/bls24-317/signature/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bls24-317/signature/schnorr/schnorr.go b/ecc/bls24-317/signature/schnorr/schnorr.go index b45b7d147..9c5fd5a59 100644 --- a/ecc/bls24-317/signature/schnorr/schnorr.go +++ b/ecc/bls24-317/signature/schnorr/schnorr.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -193,6 +193,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -207,27 +214,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bls24317.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -245,6 +248,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -260,27 +269,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bls24317.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/ecc/bls24-317/signature/schnorr/schnorr_test.go b/ecc/bls24-317/signature/schnorr/schnorr_test.go index fdadf0eca..49ec67942 100644 --- a/ecc/bls24-317/signature/schnorr/schnorr_test.go +++ b/ecc/bls24-317/signature/schnorr/schnorr_test.go @@ -46,20 +46,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[BLS24-317] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -71,9 +57,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -81,10 +68,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } } diff --git a/ecc/bn254/signature/ecdsa/ecdsa.go b/ecc/bn254/signature/ecdsa/ecdsa.go index 8593d6a72..165ff0b75 100644 --- a/ecc/bn254/signature/ecdsa/ecdsa.go +++ b/ecc/bn254/signature/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bn254/signature/schnorr/schnorr.go b/ecc/bn254/signature/schnorr/schnorr.go index d28e3d63f..b62b8668a 100644 --- a/ecc/bn254/signature/schnorr/schnorr.go +++ b/ecc/bn254/signature/schnorr/schnorr.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -193,6 +193,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -207,27 +214,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bn254.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -245,6 +248,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -260,27 +269,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bn254.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/ecc/bn254/signature/schnorr/schnorr_test.go b/ecc/bn254/signature/schnorr/schnorr_test.go index dcabca4f4..9e8496fc0 100644 --- a/ecc/bn254/signature/schnorr/schnorr_test.go +++ b/ecc/bn254/signature/schnorr/schnorr_test.go @@ -46,20 +46,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[BN254] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -71,9 +57,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -81,10 +68,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } } diff --git a/ecc/bw6-633/signature/ecdsa/ecdsa.go b/ecc/bw6-633/signature/ecdsa/ecdsa.go index f264a1e47..9e7ff866f 100644 --- a/ecc/bw6-633/signature/ecdsa/ecdsa.go +++ b/ecc/bw6-633/signature/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bw6-633/signature/schnorr/schnorr.go b/ecc/bw6-633/signature/schnorr/schnorr.go index 9e8631b49..74abc730f 100644 --- a/ecc/bw6-633/signature/schnorr/schnorr.go +++ b/ecc/bw6-633/signature/schnorr/schnorr.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -193,6 +193,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -207,27 +214,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bw6633.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -245,6 +248,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -260,27 +269,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bw6633.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/ecc/bw6-633/signature/schnorr/schnorr_test.go b/ecc/bw6-633/signature/schnorr/schnorr_test.go index a9bb91e56..ae4fd01ee 100644 --- a/ecc/bw6-633/signature/schnorr/schnorr_test.go +++ b/ecc/bw6-633/signature/schnorr/schnorr_test.go @@ -46,20 +46,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[BW6-633] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -71,9 +57,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -81,10 +68,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } } diff --git a/ecc/bw6-756/signature/ecdsa/ecdsa.go b/ecc/bw6-756/signature/ecdsa/ecdsa.go index 11c7725b5..ca52448b9 100644 --- a/ecc/bw6-756/signature/ecdsa/ecdsa.go +++ b/ecc/bw6-756/signature/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bw6-756/signature/schnorr/schnorr.go b/ecc/bw6-756/signature/schnorr/schnorr.go index f44046979..035fd172f 100644 --- a/ecc/bw6-756/signature/schnorr/schnorr.go +++ b/ecc/bw6-756/signature/schnorr/schnorr.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -193,6 +193,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -207,27 +214,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bw6756.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -245,6 +248,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -260,27 +269,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bw6756.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/ecc/bw6-756/signature/schnorr/schnorr_test.go b/ecc/bw6-756/signature/schnorr/schnorr_test.go index b8f3ff26a..becbf1070 100644 --- a/ecc/bw6-756/signature/schnorr/schnorr_test.go +++ b/ecc/bw6-756/signature/schnorr/schnorr_test.go @@ -46,20 +46,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[BW6-756] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -71,9 +57,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -81,10 +68,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } } diff --git a/ecc/bw6-761/signature/ecdsa/ecdsa.go b/ecc/bw6-761/signature/ecdsa/ecdsa.go index 7a6669fca..e996c7672 100644 --- a/ecc/bw6-761/signature/ecdsa/ecdsa.go +++ b/ecc/bw6-761/signature/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/bw6-761/signature/schnorr/schnorr.go b/ecc/bw6-761/signature/schnorr/schnorr.go index 90e97627b..697be7d85 100644 --- a/ecc/bw6-761/signature/schnorr/schnorr.go +++ b/ecc/bw6-761/signature/schnorr/schnorr.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -193,6 +193,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -207,27 +214,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P bw6761.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -245,6 +248,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -260,27 +269,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P bw6761.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/ecc/bw6-761/signature/schnorr/schnorr_test.go b/ecc/bw6-761/signature/schnorr/schnorr_test.go index ea0054339..f4ab6ce56 100644 --- a/ecc/bw6-761/signature/schnorr/schnorr_test.go +++ b/ecc/bw6-761/signature/schnorr/schnorr_test.go @@ -46,20 +46,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[BW6-761] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -71,9 +57,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -81,10 +68,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } } diff --git a/ecc/secp256k1/signature/ecdsa/ecdsa.go b/ecc/secp256k1/signature/ecdsa/ecdsa.go index de7c735da..f2acadbdc 100644 --- a/ecc/secp256k1/signature/ecdsa/ecdsa.go +++ b/ecc/secp256k1/signature/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/secp256k1/signature/schnorr/schnorr.go b/ecc/secp256k1/signature/schnorr/schnorr.go index b168333d9..cf7413347 100644 --- a/ecc/secp256k1/signature/schnorr/schnorr.go +++ b/ecc/secp256k1/signature/schnorr/schnorr.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -193,6 +193,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -207,27 +214,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P secp256k1.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -245,6 +248,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -260,27 +269,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P secp256k1.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/ecc/secp256k1/signature/schnorr/schnorr_test.go b/ecc/secp256k1/signature/schnorr/schnorr_test.go index 99fa41bec..8af13bee5 100644 --- a/ecc/secp256k1/signature/schnorr/schnorr_test.go +++ b/ecc/secp256k1/signature/schnorr/schnorr_test.go @@ -46,20 +46,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[SECP256K1] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -71,9 +57,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -81,10 +68,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } } diff --git a/ecc/stark-curve/signature/ecdsa/ecdsa.go b/ecc/stark-curve/signature/ecdsa/ecdsa.go index 4707f3219..9808f0f1e 100644 --- a/ecc/stark-curve/signature/ecdsa/ecdsa.go +++ b/ecc/stark-curve/signature/ecdsa/ecdsa.go @@ -22,7 +22,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -33,8 +32,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/ecc/stark-curve/signature/schnorr/schnorr.go b/ecc/stark-curve/signature/schnorr/schnorr.go index 852b48ac9..c42bcc188 100644 --- a/ecc/stark-curve/signature/schnorr/schnorr.go +++ b/ecc/stark-curve/signature/schnorr/schnorr.go @@ -33,7 +33,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -193,6 +193,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -207,27 +214,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P starkcurve.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -245,6 +248,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -260,27 +269,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P starkcurve.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/ecc/stark-curve/signature/schnorr/schnorr_test.go b/ecc/stark-curve/signature/schnorr/schnorr_test.go index b9b111eac..2b8ccdb3a 100644 --- a/ecc/stark-curve/signature/schnorr/schnorr_test.go +++ b/ecc/stark-curve/signature/schnorr/schnorr_test.go @@ -46,20 +46,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[STARK-CURVE] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -71,9 +57,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -81,10 +68,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } } diff --git a/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl b/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl index fd953cdf4..2dfe2a951 100644 --- a/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl +++ b/internal/generator/signature/ecdsa/template/ecdsa.go.tmpl @@ -4,7 +4,6 @@ import ( "crypto/rand" "crypto/sha512" "crypto/subtle" - "errors" "hash" "io" "math/big" @@ -15,8 +14,6 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") - const ( sizeFr = fr.Bytes sizeFp = fp.Bytes diff --git a/internal/generator/signature/schnorr/template/schnorr.go.tmpl b/internal/generator/signature/schnorr/template/schnorr.go.tmpl index 99b0846c3..01e83b44d 100644 --- a/internal/generator/signature/schnorr/template/schnorr.go.tmpl +++ b/internal/generator/signature/schnorr/template/schnorr.go.tmpl @@ -15,7 +15,7 @@ import ( "github.com/consensys/gnark-crypto/signature" ) -var errInvalidSig = errors.New("invalid signature") +var errHashNeeded = errors.New("hFunc cannot be nil. We need a hash for Fiat-Shamir.") const ( sizeFr = fr.Bytes @@ -184,6 +184,13 @@ func (privKey *PrivateKey) Public() signature.PublicKey { // s = k - x ⋅ r // signature = {r, s} func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) { + + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return nil, errHashNeeded + } + scalar, r, s := new(big.Int), new(big.Int), new(big.Int) scalar.SetBytes(privKey.scalar[:sizeFr]) csprng, err := nonce(privKey, message) @@ -198,27 +205,23 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) var P {{ .CurvePackage }}.G1Affine P.ScalarMultiplicationBase(k) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := P.X.Bytes() - PY := P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err = hFunc.Write(dataToHash[:]) - if err != nil { - return nil, err - } - - hramBin := hFunc.Sum(nil) - r = HashToInt(hramBin) - } else { - r = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := P.X.Bytes() + PY := P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err = hFunc.Write(dataToHash[:]) + if err != nil { + return nil, err } + hramBin := hFunc.Sum(nil) + r = HashToInt(hramBin) + s.Mul(scalar, r) s.Sub(k, s). Mod(s, order) @@ -236,6 +239,12 @@ func (privKey *PrivateKey) Sign(message []byte, hFunc hash.Hash) ([]byte, error) // H ( R || m ) ?= r func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (bool, error) { + // hFunc cannot be nil. + // We need a hash function for the Fiat-Shamir. + if hFunc == nil { + return false, errHashNeeded + } + // Deserialize the signature var sig Signature if _, err := sig.SetBytes(sigBin); err != nil { @@ -251,27 +260,23 @@ func (publicKey *PublicKey) Verify(sigBin, message []byte, hFunc hash.Hash) (boo var _P {{ .CurvePackage }}.G1Affine _P.FromJacobian(&P) - if hFunc != nil { - // compute H(R, M), all parameters in data are in Montgomery form - PX := _P.X.Bytes() - PY := _P.Y.Bytes() - sizeDataToHash := 2*sizeFp + len(message) - dataToHash := make([]byte, sizeDataToHash) - copy(dataToHash[:], PX[:]) - copy(dataToHash[sizeFp:], PY[:]) - copy(dataToHash[2*sizeFp:], message) - hFunc.Reset() - _, err := hFunc.Write(dataToHash[:]) - if err != nil { - return false, err - } - - hramBin := hFunc.Sum(nil) - e = HashToInt(hramBin) - } else { - e = HashToInt(message) + // compute H(R, M), all parameters in data are in Montgomery form + PX := _P.X.Bytes() + PY := _P.Y.Bytes() + sizeDataToHash := 2*sizeFp + len(message) + dataToHash := make([]byte, sizeDataToHash) + copy(dataToHash[:], PX[:]) + copy(dataToHash[sizeFp:], PY[:]) + copy(dataToHash[2*sizeFp:], message) + hFunc.Reset() + _, err := hFunc.Write(dataToHash[:]) + if err != nil { + return false, err } + hramBin := hFunc.Sum(nil) + e = HashToInt(hramBin) + return e.Cmp(r) == 0, nil } diff --git a/internal/generator/signature/schnorr/template/schnorr.test.go.tmpl b/internal/generator/signature/schnorr/template/schnorr.test.go.tmpl index 9f7293193..681c7fcf3 100644 --- a/internal/generator/signature/schnorr/template/schnorr.test.go.tmpl +++ b/internal/generator/signature/schnorr/template/schnorr.test.go.tmpl @@ -28,20 +28,6 @@ func TestSchnorr(t *testing.T) { }, )) - properties.Property("[{{ toUpper .Name }}] test the signing and verification (pre-hashed)", prop.ForAll( - func() bool { - - privKey, _ := GenerateKey(rand.Reader) - publicKey := privKey.PublicKey - - msg := []byte("testing Schnorr") - sig, _ := privKey.Sign(msg, nil) - flag, _ := publicKey.Verify(sig, msg, nil) - - return flag - }, - )) - properties.TestingRun(t, gopter.ConsoleReporter(false)) } @@ -53,9 +39,10 @@ func BenchmarkSignSchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") + hFunc := sha256.New() b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.Sign(msg, nil) + privKey.Sign(msg, hFunc) } } @@ -63,10 +50,11 @@ func BenchmarkVerifySchnorr(b *testing.B) { privKey, _ := GenerateKey(rand.Reader) msg := []byte("benchmarking Schnorr sign()") - sig, _ := privKey.Sign(msg, nil) + hFunc := sha256.New() + sig, _ := privKey.Sign(msg, hFunc) b.ResetTimer() for i := 0; i < b.N; i++ { - privKey.PublicKey.Verify(sig, msg, nil) + privKey.PublicKey.Verify(sig, msg, hFunc) } }