aboutsummaryrefslogtreecommitdiffstats
path: root/core/crypto/ecdsa/ecdsa.go
blob: 8ac335dd415d5860b8265a050ffa12f6be3196a5 (plain) (blame)
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
131
132
133
134
135
// Copyright 2018 The dexon-consensus Authors
// This file is part of the dexon-consensus library.
//
// The dexon-consensus library is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// The dexon-consensus library is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
// General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the dexon-consensus library. If not, see
// <http://www.gnu.org/licenses/>.

package ecdsa

import (
    "crypto/ecdsa"

    dexCrypto "github.com/byzantine-lab/go-tangerine/crypto"

    "gitlab.com/byzantine-lab/tangerine-consensus/common"
    "gitlab.com/byzantine-lab/tangerine-consensus/core/crypto"
)

const cryptoType = "ecdsa"

func init() {
    if err := crypto.RegisterSigToPub(cryptoType, SigToPub); err != nil {
        panic(err)
    }
}

// PrivateKey represents a private key structure used in geth and implments
// Crypto.PrivateKey interface.
type PrivateKey struct {
    privateKey *ecdsa.PrivateKey
}

// PublicKey represents a public key structure used in geth and implements
// Crypto.PublicKey interface.
type PublicKey struct {
    publicKey *ecdsa.PublicKey
}

// NewPrivateKey creates a new PrivateKey structure.
func NewPrivateKey() (*PrivateKey, error) {
    key, err := dexCrypto.GenerateKey()
    if err != nil {
        return nil, err
    }
    return &PrivateKey{privateKey: key}, nil
}

// NewPrivateKeyFromECDSA creates a new PrivateKey structure from
// ecdsa.PrivateKey.
func NewPrivateKeyFromECDSA(key *ecdsa.PrivateKey) *PrivateKey {
    return &PrivateKey{privateKey: key}
}

// NewPublicKeyFromECDSA creates a new PublicKey structure from
// ecdsa.PublicKey.
func NewPublicKeyFromECDSA(key *ecdsa.PublicKey) *PublicKey {
    return &PublicKey{publicKey: key}
}

// NewPublicKeyFromByteSlice constructs an eth.publicKey instance from
// a byte slice.
func NewPublicKeyFromByteSlice(b []byte) (crypto.PublicKey, error) {
    pub, err := dexCrypto.UnmarshalPubkey(b)
    if err != nil {
        return &PublicKey{}, err
    }
    return &PublicKey{publicKey: pub}, nil
}

// PublicKey returns the public key associate this private key.
func (prv *PrivateKey) PublicKey() crypto.PublicKey {
    return NewPublicKeyFromECDSA(&(prv.privateKey.PublicKey))
}

// Sign calculates an ECDSA signature.
//
// This function is susceptible to chosen plaintext attacks that can leak
// information about the private key that is used for signing. Callers must
// be aware that the given hash cannot be chosen by an adversery. Common
// solution is to hash any input before calculating the signature.
//
// The produced signature is in the [R || S || V] format where V is 0 or 1.
func (prv *PrivateKey) Sign(hash common.Hash) (
    sig crypto.Signature, err error) {
    s, err := dexCrypto.Sign(hash[:], prv.privateKey)
    sig = crypto.Signature{
        Type:      cryptoType,
        Signature: s,
    }
    return
}

// VerifySignature checks that the given public key created signature over hash.
// The public key should be in compressed (33 bytes) or uncompressed (65 bytes)
// format.
// The signature should have the 64 byte [R || S] format.
func (pub *PublicKey) VerifySignature(
    hash common.Hash, signature crypto.Signature) bool {
    sig := signature.Signature
    if len(sig) == 65 {
        // The last byte is for ecrecover.
        sig = sig[:64]
    }
    return dexCrypto.VerifySignature(pub.Bytes(), hash[:], sig)
}

// Compress encodes a public key to the 33-byte compressed format.
func (pub *PublicKey) Compress() []byte {
    return dexCrypto.CompressPubkey(pub.publicKey)
}

// Bytes returns the []byte representation of uncompressed public key. (65 bytes)
func (pub *PublicKey) Bytes() []byte {
    return dexCrypto.FromECDSAPub(pub.publicKey)
}

// SigToPub returns the PublicKey that created the given signature.
func SigToPub(
    hash common.Hash, signature crypto.Signature) (crypto.PublicKey, error) {
    key, err := dexCrypto.SigToPub(hash[:], signature.Signature[:])
    if err != nil {
        return &PublicKey{}, err
    }
    return &PublicKey{publicKey: key}, nil
}