-
Notifications
You must be signed in to change notification settings - Fork 2
/
crypto.go
104 lines (69 loc) · 1.88 KB
/
crypto.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package core
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"math/big"
"github.com/izqui/helpers"
"github.com/tv42/base58"
)
// Key generation with proof of work
type Keypair struct {
Public []byte `json:"public"` // base58 (x y)
Private []byte `json:"private"` // d (base58 encoded)
}
func GenerateNewKeypair() *Keypair {
pk, _ := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
b := bigJoin(KEY_SIZE, pk.PublicKey.X, pk.PublicKey.Y)
public := base58.EncodeBig([]byte{}, b)
private := base58.EncodeBig([]byte{}, pk.D)
kp := Keypair{Public: public, Private: private}
return &kp
}
func (k *Keypair) Sign(hash []byte) ([]byte, error) {
d, err := base58.DecodeToBig(k.Private)
if err != nil {
return nil, err
}
b, _ := base58.DecodeToBig(k.Public)
pub := splitBig(b, 2)
x, y := pub[0], pub[1]
key := ecdsa.PrivateKey{ecdsa.PublicKey{elliptic.P224(), x, y}, d}
r, s, _ := ecdsa.Sign(rand.Reader, &key, hash)
return base58.EncodeBig([]byte{}, bigJoin(KEY_SIZE, r, s)), nil
}
func SignatureVerify(publicKey, sig, hash []byte) bool {
b, _ := base58.DecodeToBig(publicKey)
publ := splitBig(b, 2)
x, y := publ[0], publ[1]
b, _ = base58.DecodeToBig(sig)
sigg := splitBig(b, 2)
r, s := sigg[0], sigg[1]
pub := ecdsa.PublicKey{elliptic.P224(), x, y}
return ecdsa.Verify(&pub, hash, r, s)
}
func bigJoin(expectedLen int, bigs ...*big.Int) *big.Int {
bs := []byte{}
for i, b := range bigs {
by := b.Bytes()
dif := expectedLen - len(by)
if dif > 0 && i != 0 {
by = append(helpers.ArrayOfBytes(dif, 0), by...)
}
bs = append(bs, by...)
}
b := new(big.Int).SetBytes(bs)
return b
}
func splitBig(b *big.Int, parts int) []*big.Int {
bs := b.Bytes()
if len(bs)%2 != 0 {
bs = append([]byte{0}, bs...)
}
l := len(bs) / parts
as := make([]*big.Int, parts)
for i, _ := range as {
as[i] = new(big.Int).SetBytes(bs[i*l : (i+1)*l])
}
return as
}