Skip to content

Commit 58b44c6

Browse files
committed
Added routes for generating/verifying schnorr signatures
1 parent 04b88df commit 58b44c6

6 files changed

+183
-5
lines changed

generate_handlers.go

+15
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,18 @@ func GenerateCommitment(w http.ResponseWriter, r *http.Request) {
5050
commitment := NewCurvePoint(C)
5151
encoder.Encode(Response{P: commitment})
5252
}
53+
54+
func GenerateSchnorr(w http.ResponseWriter, r *http.Request) {
55+
encoder := json.NewEncoder(w)
56+
var generateSchnorrInputs GenerateSchnorrInputs
57+
err := ReadContentsIntoStruct(r, &generateSchnorrInputs)
58+
if err != nil {
59+
encoder.Encode(Response{Err: &Error{Msg: err.Error()}})
60+
return
61+
}
62+
P, err := NewECPoint(generateSchnorrInputs.P.X, generateSchnorrInputs.P.Y, err)
63+
X, err := NewBigInt(generateSchnorrInputs.X, err)
64+
M := generateSchnorrInputs.M
65+
P_out, M_out, E_out, S_out, _ := GenerateSchnorrSignature(P, M, X, err)
66+
encoder.Encode(Response{Sig: &SchnorrSignature{P: NewCurvePoint(P_out), M: M_out, E: fmt.Sprintf("0x%064x", E_out), S: fmt.Sprintf("0x%064x", S_out)}})
67+
}

json_types.go

+19-4
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import (
77
)
88

99
type Response struct {
10-
Text string `json:"text,omitempty"`
11-
Num *Number `json:"number,omitempty"`
12-
P *CurvePoint `json:"curvepoint,omitempty"`
13-
Err *Error `json:"error,omitempty"`
10+
Text string `json:"text,omitempty"`
11+
Num *Number `json:"number,omitempty"`
12+
P *CurvePoint `json:"curvepoint,omitempty"`
13+
Sig *SchnorrSignature `json:"sig,omitempty"`
14+
Err *Error `json:"error,omitempty"`
1415
}
1516

1617
type Text struct {
@@ -57,6 +58,20 @@ type CommitmentInputs struct {
5758
G *CurvePoint `json:"g"`
5859
}
5960

61+
type GenerateSchnorrInputs struct {
62+
P *CurvePoint `json:"p"`
63+
M string `json:"m"`
64+
X string `json:"x"`
65+
}
66+
67+
type SchnorrSignature struct {
68+
P *CurvePoint `json:"p"`
69+
K *CurvePoint `json:"kg,omitempty"`
70+
M string `json:"m"`
71+
E string `json:"e"`
72+
S string `json:"s"`
73+
}
74+
6075
type Number struct {
6176
V string `json:"v"`
6277
}

server.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ var port = "8083"
1313
func main() {
1414
router := mux.NewRouter().StrictSlash(true)
1515
router.HandleFunc("/isalive", IsAlive).Methods("GET")
16-
router.HandleFunc("/generate/commitment/", GenerateCommitment).Methods("POST")
1716
router.HandleFunc("/generate/keccak256/", GenerateKeccak256).Methods("POST")
17+
router.HandleFunc("/generate/commitment/", GenerateCommitment).Methods("POST")
18+
router.HandleFunc("/generate/schnorr/", GenerateSchnorr).Methods("POST")
19+
router.HandleFunc("/verify/schnorr/", VerifySchnorr).Methods("POST")
1820
router.HandleFunc("/big/add/", BigIntAdd).Methods("POST")
1921
router.HandleFunc("/big/submod/", BigIntSubMod).Methods("POST")
2022
router.HandleFunc("/big/invmod/", BigIntInvMod).Methods("POST")

server_test.go

+83
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"testing"
5+
"crypto/rand"
56
"net/http"
67
"io/ioutil"
78
"encoding/json"
@@ -334,6 +335,88 @@ func TestGenerateCommitment(t *testing.T) {
334335
}
335336
}
336337

338+
func TestGenerateSchnorr(t *testing.T) {
339+
x, _ := rand.Int(rand.Reader, bn256.Order)
340+
P := new(bn256.G1).ScalarBaseMult(x)
341+
m := "This is the message to be signed"
342+
generateSchnorrInputs := GenerateSchnorrInputs{P: NewCurvePoint(P), X: fmt.Sprintf("0x%064x", x), M: m}
343+
marshalledJSON, _ := json.Marshal(generateSchnorrInputs)
344+
response, err := http.Post("http://localhost:" + port + "/generate/schnorr/", "application/json", bytes.NewBuffer(marshalledJSON))
345+
if err != nil {
346+
t.Errorf("An error occurred while making request to API: %s\n", err)
347+
return
348+
}
349+
defer response.Body.Close()
350+
contents, err := ioutil.ReadAll(response.Body)
351+
if err != nil {
352+
t.Errorf("An error occurred while reading response body: %s\n", err)
353+
return
354+
}
355+
var res Response
356+
err = json.Unmarshal(contents, &res)
357+
if err != nil {
358+
t.Errorf("An error occurred while reading into JSON object: %s\n", err)
359+
return
360+
}
361+
if res.Err != nil && res.Err.Msg != "" {
362+
t.Errorf(fmt.Sprintf("An error occurred: %s\n", res.Err.Msg))
363+
return
364+
}
365+
sig := res.Sig
366+
P_out := new(bn256.G1)
367+
marshalledPoint := sig.P.X[2:] + sig.P.Y[2:]
368+
marshalledBytes, err := hex.DecodeString(marshalledPoint)
369+
if err != nil {
370+
t.Errorf("An error occurred while decoding hex string: %s\n", err)
371+
return
372+
}
373+
_, err = P_out.Unmarshal(marshalledBytes)
374+
if err != nil {
375+
t.Errorf("An error occurred while unmarshalling BN256 curve point: %s\n", err)
376+
return
377+
}
378+
E_out, _ := new(big.Int).SetString(sig.E[2:], 16)
379+
S_out, _ := new(big.Int).SetString(sig.S[2:], 16)
380+
M_out := sig.M
381+
isValid, err := VerifySchnorrSignature(P_out, M_out, E_out, S_out, err)
382+
if (!isValid) {
383+
t.Errorf("Invalid Schnorr signature generated")
384+
}
385+
}
386+
387+
func TestVerifySchnorr(t *testing.T) {
388+
x, _ := rand.Int(rand.Reader, bn256.Order)
389+
P := new(bn256.G1).ScalarBaseMult(x)
390+
m := "This is the message to be signed"
391+
P_out, M_out, E_out, S_out, err := GenerateSchnorrSignature(P, m, x, nil)
392+
schnorrSignature := SchnorrSignature{P: NewCurvePoint(P_out), M: M_out, E: fmt.Sprintf("0x%064x", E_out), S: fmt.Sprintf("0x%064x", S_out)}
393+
marshalledJSON, _ := json.Marshal(schnorrSignature)
394+
response, err := http.Post("http://localhost:" + port + "/verify/schnorr/", "application/json", bytes.NewBuffer(marshalledJSON))
395+
if err != nil {
396+
t.Errorf("An error occurred while making request to API: %s\n", err)
397+
return
398+
}
399+
defer response.Body.Close()
400+
contents, err := ioutil.ReadAll(response.Body)
401+
if err != nil {
402+
t.Errorf("An error occurred while reading response body: %s\n", err)
403+
return
404+
}
405+
var res Response
406+
err = json.Unmarshal(contents, &res)
407+
if err != nil {
408+
t.Errorf("An error occurred while reading into JSON object: %s\n", err)
409+
return
410+
}
411+
if res.Err != nil && res.Err.Msg != "" {
412+
t.Errorf(fmt.Sprintf("An error occurred: %s\n", res.Err.Msg))
413+
return
414+
}
415+
if (res.Text != "true") {
416+
t.Errorf("Invalid Schnorr signature generated")
417+
}
418+
}
419+
337420
func TestBigAdd(t *testing.T) {
338421
a, _ := new(big.Int).SetString("20222222222222222222222222222222222222222222222222222222222222222222222222222", 10)
339422
b, _ := new(big.Int).SetString("11111111111111111111111111111111111111111111111111111111111111111111111111111", 10)

util.go

+32
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package main
22

33
import (
44
"errors"
5+
"crypto/rand"
56
"net/http"
67
"encoding/json"
78
"io/ioutil"
89
"math/big"
910
"github.com/rynobey/bn256"
1011
"encoding/hex"
1112
"fmt"
13+
"github.com/ethereum/go-ethereum/crypto/sha3"
1214
)
1315

1416
func Hex32ByteChunksToStr(hexChunks []string) (string) {
@@ -92,3 +94,33 @@ func NewECPoint(xCoord string, yCoord string, err error) (*bn256.G1, error) {
9294
return P, nil
9395
}
9496
}
97+
98+
func GenerateSchnorrSignature(P *bn256.G1, M string, X *big.Int, err error) (*bn256.G1, string, *big.Int, *big.Int, error) {
99+
if err != nil {
100+
return nil, "", nil, nil, err
101+
} else {
102+
k, _ := rand.Int(rand.Reader, bn256.Order)
103+
kG := new(bn256.G1).ScalarBaseMult(k)
104+
h := sha3.NewKeccak256()
105+
h.Reset()
106+
h.Write([]byte(fmt.Sprintf("%s%s%s", M, P, kG)))
107+
e, _ := new(big.Int).SetString(fmt.Sprintf("%x", h.Sum(nil)), 16)
108+
s := new(big.Int).Mod(new(big.Int).Add(k, new(big.Int).Mul(e, X)), bn256.Order)
109+
return P, M, e, s, nil
110+
}
111+
}
112+
113+
func VerifySchnorrSignature(P *bn256.G1, M string, E, S *big.Int, err error) (bool, error) {
114+
if err != nil {
115+
return false, err
116+
} else {
117+
sG := new(bn256.G1).ScalarBaseMult(S)
118+
eP := new(bn256.G1).ScalarMult(P, E)
119+
kG := new(bn256.G1).Add(sG, eP.Neg(eP))
120+
h := sha3.NewKeccak256()
121+
h.Reset()
122+
h.Write([]byte(fmt.Sprintf("%s%s%s", M, P, kG)))
123+
e, _ := new(big.Int).SetString(fmt.Sprintf("%x", h.Sum(nil)), 16)
124+
return (e.Cmp(E) == 0), nil
125+
}
126+
}

verify_handlers.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"encoding/json"
7+
)
8+
9+
func VerifySchnorr(w http.ResponseWriter, r *http.Request) {
10+
encoder := json.NewEncoder(w)
11+
var schnorrSignature SchnorrSignature
12+
err := ReadContentsIntoStruct(r, &schnorrSignature)
13+
if err != nil {
14+
encoder.Encode(Response{Err: &Error{Msg: err.Error()}})
15+
return
16+
}
17+
P, err := NewECPoint(schnorrSignature.P.X, schnorrSignature.P.Y, err)
18+
if err != nil {
19+
encoder.Encode(Response{Err: &Error{Msg: err.Error()}})
20+
return
21+
}
22+
M := schnorrSignature.M
23+
E, err := NewBigInt(schnorrSignature.E, err)
24+
S, err := NewBigInt(schnorrSignature.S, err)
25+
isValid, err := VerifySchnorrSignature(P, M, E, S, err)
26+
if err != nil {
27+
encoder.Encode(Response{Err: &Error{Msg: err.Error()}})
28+
return
29+
}
30+
encoder.Encode(Response{Text: fmt.Sprintf("%t", isValid)})
31+
}

0 commit comments

Comments
 (0)