/
ecdsa.go
99 lines (86 loc) · 2.78 KB
/
ecdsa.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
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package security
import (
"crypto/ecdsa"
"crypto/rand"
"crypto/x509"
"fmt"
"math/big"
)
// NewECDSAPublicKey creates a PublicKey object that uses the ECDSA algorithm and the provided ECDSA public key.
func NewECDSAPublicKey(key *ecdsa.PublicKey) PublicKey {
return newECDSAPublicKeyImpl(key)
}
type ecdsaPublicKey struct {
key *ecdsa.PublicKey
}
func (pk *ecdsaPublicKey) MarshalBinary() ([]byte, error) { return x509.MarshalPKIXPublicKey(pk.key) }
func (pk *ecdsaPublicKey) String() string { return publicKeyString(pk) }
func (pk *ecdsaPublicKey) verify(digest []byte, sig *Signature) bool {
var r, s big.Int
return ecdsa.Verify(pk.key, digest, r.SetBytes(sig.R), s.SetBytes(sig.S))
}
func (pk *ecdsaPublicKey) hash() Hash {
nbits := pk.key.Curve.Params().BitSize
switch {
case nbits <= 160:
return SHA1Hash
case nbits <= 256:
return SHA256Hash
case nbits <= 384:
return SHA384Hash
default:
return SHA512Hash
}
}
// NewInMemoryECDSASigner creates a Signer that uses the provided ECDSA private
// key to sign messages. This private key is kept in the clear in the memory
// of the running process.
func NewInMemoryECDSASigner(key *ecdsa.PrivateKey) (Signer, error) {
signer, err := newInMemoryECDSASignerImpl(key)
if err != nil {
return nil, err
}
return signer, nil
}
// NewECDSASigner creates a Signer that uses the provided function to sign
// messages.
func NewECDSASigner(key *ecdsa.PublicKey, sign func(data []byte) (r, s *big.Int, err error)) Signer {
return &ecdsaSigner{sign: sign, pubkey: NewECDSAPublicKey(key)}
}
type ecdsaSigner struct {
sign func(data []byte) (r, s *big.Int, err error)
pubkey PublicKey
// Object to hold on to for garbage collection
impl interface{} //nolint:structcheck,unused
}
func (c *ecdsaSigner) Sign(purpose, message []byte) (Signature, error) {
hash := c.pubkey.hash()
if message = messageDigest(hash, purpose, message, c.pubkey); message == nil {
return Signature{}, fmt.Errorf("unable to create bytes to sign from message with hashing function: %v", hash)
}
r, s, err := c.sign(message)
if err != nil {
return Signature{}, err
}
return Signature{
Purpose: purpose,
Hash: hash,
R: r.Bytes(),
S: s.Bytes(),
}, nil
}
func (c *ecdsaSigner) PublicKey() PublicKey {
return c.pubkey
}
func newGoStdlibECDSASigner(key *ecdsa.PrivateKey) (Signer, error) {
sign := func(data []byte) (r, s *big.Int, err error) {
return ecdsa.Sign(rand.Reader, key, data)
}
return &ecdsaSigner{sign: sign, pubkey: newGoStdlibECDSAPublicKey(&key.PublicKey)}, nil
}
func newGoStdlibECDSAPublicKey(key *ecdsa.PublicKey) PublicKey {
return &ecdsaPublicKey{key}
}