cryptofun/schnorr/schnorr.go
schnorr/schnorr.goRaw
1package schnorr
2
3import (
4 "crypto/rand"
5 "crypto/sha256"
6 "math/big"
7
8 "github.com/arnaucube/cryptofun/ecc"
9)
10
11const (
12 bits = 512 // 2048
13)
14
15// PubK is the public key of the Schnorr scheme
16type PubK struct {
17 P ecc.Point
18 Q ecc.Point
19}
20
21// PrivK is the private key of the Schnorr scheme
22type PrivK struct {
23 PubK PubK
24 A *big.Int
25}
26
27// Schnorr is the data structure for the Schnorr scheme
28type Schnorr struct {
29 EC ecc.EC
30 D *big.Int // K
31 G ecc.Point
32 Q ecc.Point // P
33 N int // order of curve
34}
35
36// Hash calculates a hash concatenating a given message bytes with a given EC Point. H(M||R)
37func Hash(m []byte, c ecc.Point) *big.Int {
38 var b []byte
39 b = append(b, m...)
40 cXBytes := c.X.Bytes()
41 cYBytes := c.Y.Bytes()
42 b = append(b, cXBytes...)
43 b = append(b, cYBytes...)
44 h := sha256.New()
45 h.Write(b)
46 hash := h.Sum(nil)
47 r := new(big.Int).SetBytes(hash)
48 return r
49}
50
51// Gen generates the Schnorr scheme
52func Gen(ec ecc.EC, g ecc.Point, r *big.Int) (Schnorr, PrivK, error) {
53 var err error
54 var schnorr Schnorr
55 var sk PrivK
56 schnorr.EC = ec
57 schnorr.G = g
58
59 sk.PubK.P, _, err = ec.At(r)
60 if err != nil {
61 return schnorr, sk, err
62 }
63
64 orderP, err := ec.Order(sk.PubK.P)
65 if err != nil {
66 return schnorr, sk, err
67 }
68
69 // rand int between 1 and oerder of P
70 sk.A, err = rand.Int(rand.Reader, orderP)
71 if err != nil {
72 return schnorr, sk, err
73 }
74 sk.A = big.NewInt(int64(7))
75 skACopy := new(big.Int).SetBytes(sk.A.Bytes())
76 // pk.Q = k x P
77 sk.PubK.Q, err = ec.Mul(sk.PubK.P, skACopy)
78 if err != nil {
79 return schnorr, sk, err
80 }
81 return schnorr, sk, nil
82}
83
84// Sign performs the signature of the message m with the given private key
85func (schnorr Schnorr) Sign(sk PrivK, m []byte) (*big.Int, ecc.Point, error) {
86 var e *big.Int
87 orderP, err := schnorr.EC.Order(sk.PubK.P)
88 if err != nil {
89 return e, ecc.Point{}, err
90 }
91 // rand k <-[1,r]
92 k, err := rand.Int(rand.Reader, orderP)
93 if err != nil {
94 return e, ecc.Point{}, err
95 }
96
97 // R = k x P
98 rPoint, err := schnorr.EC.Mul(sk.PubK.P, k)
99 if err != nil {
100 return e, ecc.Point{}, err
101 }
102 // e = H(M||R)
103 e = Hash(m, rPoint)
104 // a*e
105 ae := new(big.Int).Mul(sk.A, e)
106 // k + a*e
107 kae := new(big.Int).Add(k, ae)
108 // k + a*e mod r, where r is order of P
109 s := new(big.Int).Mod(kae, orderP)
110 return s, rPoint, nil
111}
112
113// Verify checks if the given public key matches with the given signature of the message m, in the given EC
114func Verify(ec ecc.EC, pk PubK, m []byte, s *big.Int, rPoint ecc.Point) (bool, error) {
115 // e = H(M||R)
116 e := Hash(m, rPoint)
117 eCopy := new(big.Int).SetBytes(e.Bytes())
118
119 // e x Q
120 eQ, err := ec.Mul(pk.Q, eCopy)
121 if err != nil {
122 return false, err
123 }
124
125 // R + e x Q
126 // reQ, err := schnorr.EC.Add(rPoint, eQ)
127 // if err != nil {
128 // return false, err
129 // }
130
131 // s x P
132 sp, err := ec.Mul(pk.P, s)
133
134 // return reQ.Equal(sp), nil
135 return eQ.Equal(sp), nil
136}