-
Notifications
You must be signed in to change notification settings - Fork 188
/
public_key.go
140 lines (122 loc) · 4.25 KB
/
public_key.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
131
132
133
134
135
136
137
138
139
140
// Copyright 2019 The klaytn Authors
// This file is part of the klaytn library.
//
// The klaytn 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 klaytn 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 klaytn library. If not, see <http://www.gnu.org/licenses/>.
package accountkey
import (
"crypto/ecdsa"
"encoding/json"
"errors"
"fmt"
"io"
"math/big"
"github.com/klaytn/klaytn/common/hexutil"
"github.com/klaytn/klaytn/crypto"
"github.com/klaytn/klaytn/rlp"
)
var (
errNotS256Curve = errors.New("key is not on the S256 curve")
errNoXYValue = errors.New("X or Y value of the public key does not exist")
)
// Since ecdsa.PublicKey does not provide RLP/JSON serialization,
// PublicKeySerializable provides RLP/JSON serialization.
// It is used for AccountKey as an internal structure.
type PublicKeySerializable ecdsa.PublicKey
type publicKeySerializableInternalJSON struct {
X *hexutil.Big `json:"x"`
Y *hexutil.Big `json:"y"`
}
// newPublicKeySerializable creates a PublicKeySerializable object.
// The object is initialized with default values.
// Curve = S256 curve
// X = 0
// Y = 0
func newPublicKeySerializable() *PublicKeySerializable {
return &PublicKeySerializable{
Curve: crypto.S256(),
X: new(big.Int),
Y: new(big.Int),
}
}
// EncodeRLP encodes ecdsa.PublicKey using RLP.
// For now, it supports S256 curve only.
// For that reason, this function serializes only X and Y using CompressPubkey().
func (p *PublicKeySerializable) EncodeRLP(w io.Writer) error {
// Do not serialize if it is not on S256 curve.
if !crypto.S256().IsOnCurve(p.X, p.Y) {
return errNotS256Curve
}
return rlp.Encode(w, crypto.CompressPubkey((*ecdsa.PublicKey)(p)))
}
// DecodeRLP decodes PublicKeySerializable using RLP.
// For now, it supports S256 curve only.
// This function deserializes using UncompressPubkey().
func (p *PublicKeySerializable) DecodeRLP(s *rlp.Stream) error {
b := []byte{}
if err := s.Decode(&b); err != nil {
return err
}
pubkey, err := crypto.DecompressPubkey(b)
if err != nil {
return err
}
*p = *((*PublicKeySerializable)(pubkey))
return nil
}
// MarshalJSON encodes PublicKeySerializable using JSON.
// For now, it supports S256 curve only.
// For that reason, this function serializes only X and Y.
func (p *PublicKeySerializable) MarshalJSON() ([]byte, error) {
// Do not serialize if it is not on S256 curve.
if !crypto.S256().IsOnCurve(p.X, p.Y) {
return nil, errNotS256Curve
}
return json.Marshal(&publicKeySerializableInternalJSON{
(*hexutil.Big)(p.X), (*hexutil.Big)(p.Y),
})
}
// UnmarshalJSON decodes PublicKeySerializable using JSON.
// For now, it supports S256 curve only.
// For that reason, this function deserializes only X and Y. Refer to MarshalJSON() above.
func (p *PublicKeySerializable) UnmarshalJSON(b []byte) error {
var dec publicKeySerializableInternalJSON
if err := json.Unmarshal(b, &dec); err != nil {
return err
}
if dec.X == nil || dec.Y == nil {
return errNoXYValue
}
p.X = (*big.Int)(dec.X)
p.Y = (*big.Int)(dec.Y)
return nil
}
// DeepCopy creates a new PublicKeySerializable object and newly allocates memory for all its attributes.
// Then, the values of the original object are copied to those of the new object.
func (p *PublicKeySerializable) DeepCopy() *PublicKeySerializable {
pk := newPublicKeySerializable()
pk.X = new(big.Int).Set(p.X)
pk.Y = new(big.Int).Set(p.Y)
return pk
}
// Equal returns true if all attributes between p and pk are the same.
// Otherwise, it returns false.
func (p *PublicKeySerializable) Equal(pk *PublicKeySerializable) bool {
return p.X.Cmp(pk.X) == 0 &&
p.Y.Cmp(pk.Y) == 0
}
// String returns a string containing information of all attributes.
func (p *PublicKeySerializable) String() string {
b, _ := json.Marshal(p)
return fmt.Sprintf("S256Pubkey:%s", string(b))
}