/
signature.go
130 lines (107 loc) · 3.61 KB
/
signature.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (c) 2013-2014 The btcsuite developers
// Copyright (c) 2015-2018 The Hdfchain developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package edwards
import (
"fmt"
"math/big"
"github.com/agl/ed25519"
)
// Signature is a type representing an ecdsa signature.
type Signature struct {
R *big.Int
S *big.Int
}
// SignatureSize is the size of an encoded ECDSA signature.
const SignatureSize = 64
// NewSignature instantiates a new signature given some R,S values.
func NewSignature(r, s *big.Int) *Signature {
return &Signature{r, s}
}
// Serialize returns the ECDSA signature in the more strict format.
//
// The signatures are encoded as
// sig[0:32] R, a point encoded as little endian
// sig[32:64] S, scalar multiplication/addition results = (ab+c) mod l
// encoded also as little endian
func (sig Signature) Serialize() []byte {
rBytes := bigIntToEncodedBytes(sig.R)
sBytes := bigIntToEncodedBytes(sig.S)
all := append(rBytes[:], sBytes[:]...)
return all
}
// IsEqual compares this Signature instance to the one passed, returning true
// if both Signatures are equivalent. A signature is equivalent to another, if
// they both have the same scalar value for R and S.
func (sig *Signature) IsEqual(otherSig *Signature) bool {
return sig.R.Cmp(otherSig.R) == 0 &&
sig.S.Cmp(otherSig.S) == 0
}
// Verify verifies a message 'hash' using the given public keys and signature.
func (sig *Signature) Verify(hash []byte, pubKey *PublicKey) bool {
if pubKey == nil || hash == nil {
return false
}
pubBytes := pubKey.Serialize()
sigBytes := sig.Serialize()
pubArray := copyBytes(pubBytes)
sigArray := copyBytes64(sigBytes)
return ed25519.Verify(pubArray, hash, sigArray)
}
// parseSig is the default method of parsing a serialized Ed25519 signature.
func parseSig(sigStr []byte, der bool) (*Signature, error) {
if der {
return nil, fmt.Errorf("DER signatures not allowed in ed25519")
}
if len(sigStr) != SignatureSize {
return nil, fmt.Errorf("bad signature size; have %v, want %v",
len(sigStr), SignatureSize)
}
curve := Edwards()
rBytes := copyBytes(sigStr[0:32])
r := encodedBytesToBigInt(rBytes)
// r is a point on the curve as well. Evaluate it and make sure it's
// a valid point.
_, _, err := curve.encodedBytesToBigIntPoint(rBytes)
if err != nil {
return nil, err
}
sBytes := copyBytes(sigStr[32:64])
s := encodedBytesToBigInt(sBytes)
// s may not be zero or >= curve.N.
if s.Cmp(curve.N) >= 0 || s.Cmp(zero) == 0 {
return nil, fmt.Errorf("s scalar is empty or larger than the order of " +
"the curve")
}
return &Signature{r, s}, nil
}
// ParseSignature parses a signature in BER format for the curve type `curve'
// into a Signature type, performing some basic sanity checks.
func ParseSignature(sigStr []byte) (*Signature, error) {
return parseSig(sigStr, false)
}
// ParseDERSignature offers a legacy function for plugging into Hdfchain, which
// is based off btcec.
func ParseDERSignature(sigStr []byte) (*Signature, error) {
return parseSig(sigStr, false)
}
// RecoverCompact uses a signature and a hash to recover is private
// key, is not yet implemented.
// TODO: Implement.
func RecoverCompact(signature, hash []byte) (*PublicKey, bool, error) {
// TODO One day reimplement this? cj
return nil, false, nil
}
// GetR satisfies the chainec Signature interface.
func (sig Signature) GetR() *big.Int {
return sig.R
}
// GetS satisfies the chainec Signature interface.
func (sig Signature) GetS() *big.Int {
return sig.S
}
// GetType satisfies the chainec Signature interface.
func (sig Signature) GetType() int {
return ecTypeEdwards
}