github.com/klaytn/klaytn@v1.10.2/blockchain/types/accountkey/public_key.go (about) 1 // Copyright 2019 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The klaytn library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package accountkey 18 19 import ( 20 "crypto/ecdsa" 21 "encoding/json" 22 "errors" 23 "fmt" 24 "io" 25 "math/big" 26 27 "github.com/klaytn/klaytn/common/hexutil" 28 "github.com/klaytn/klaytn/crypto" 29 "github.com/klaytn/klaytn/rlp" 30 ) 31 32 var ( 33 errNotS256Curve = errors.New("key is not on the S256 curve") 34 errNoXYValue = errors.New("X or Y value of the public key does not exist") 35 ) 36 37 // Since ecdsa.PublicKey does not provide RLP/JSON serialization, 38 // PublicKeySerializable provides RLP/JSON serialization. 39 // It is used for AccountKey as an internal structure. 40 type PublicKeySerializable ecdsa.PublicKey 41 42 type publicKeySerializableInternalJSON struct { 43 X *hexutil.Big `json:"x"` 44 Y *hexutil.Big `json:"y"` 45 } 46 47 // newPublicKeySerializable creates a PublicKeySerializable object. 48 // The object is initialized with default values. 49 // Curve = S256 curve 50 // X = 0 51 // Y = 0 52 func newPublicKeySerializable() *PublicKeySerializable { 53 return &PublicKeySerializable{ 54 Curve: crypto.S256(), 55 X: new(big.Int), 56 Y: new(big.Int), 57 } 58 } 59 60 // EncodeRLP encodes ecdsa.PublicKey using RLP. 61 // For now, it supports S256 curve only. 62 // For that reason, this function serializes only X and Y using CompressPubkey(). 63 func (p *PublicKeySerializable) EncodeRLP(w io.Writer) error { 64 // Do not serialize if it is not on S256 curve. 65 if !crypto.S256().IsOnCurve(p.X, p.Y) { 66 return errNotS256Curve 67 } 68 return rlp.Encode(w, crypto.CompressPubkey((*ecdsa.PublicKey)(p))) 69 } 70 71 // DecodeRLP decodes PublicKeySerializable using RLP. 72 // For now, it supports S256 curve only. 73 // This function deserializes using UncompressPubkey(). 74 func (p *PublicKeySerializable) DecodeRLP(s *rlp.Stream) error { 75 b := []byte{} 76 if err := s.Decode(&b); err != nil { 77 return err 78 } 79 pubkey, err := crypto.DecompressPubkey(b) 80 if err != nil { 81 return err 82 } 83 *p = *((*PublicKeySerializable)(pubkey)) 84 85 return nil 86 } 87 88 // MarshalJSON encodes PublicKeySerializable using JSON. 89 // For now, it supports S256 curve only. 90 // For that reason, this function serializes only X and Y. 91 func (p *PublicKeySerializable) MarshalJSON() ([]byte, error) { 92 // Do not serialize if it is not on S256 curve. 93 if !crypto.S256().IsOnCurve(p.X, p.Y) { 94 return nil, errNotS256Curve 95 } 96 return json.Marshal(&publicKeySerializableInternalJSON{ 97 (*hexutil.Big)(p.X), (*hexutil.Big)(p.Y), 98 }) 99 } 100 101 // UnmarshalJSON decodes PublicKeySerializable using JSON. 102 // For now, it supports S256 curve only. 103 // For that reason, this function deserializes only X and Y. Refer to MarshalJSON() above. 104 func (p *PublicKeySerializable) UnmarshalJSON(b []byte) error { 105 var dec publicKeySerializableInternalJSON 106 if err := json.Unmarshal(b, &dec); err != nil { 107 return err 108 } 109 if dec.X == nil || dec.Y == nil { 110 return errNoXYValue 111 } 112 p.X = (*big.Int)(dec.X) 113 p.Y = (*big.Int)(dec.Y) 114 115 return nil 116 } 117 118 // DeepCopy creates a new PublicKeySerializable object and newly allocates memory for all its attributes. 119 // Then, the values of the original object are copied to those of the new object. 120 func (p *PublicKeySerializable) DeepCopy() *PublicKeySerializable { 121 pk := newPublicKeySerializable() 122 pk.X = new(big.Int).Set(p.X) 123 pk.Y = new(big.Int).Set(p.Y) 124 125 return pk 126 } 127 128 // Equal returns true if all attributes between p and pk are the same. 129 // Otherwise, it returns false. 130 func (p *PublicKeySerializable) Equal(pk *PublicKeySerializable) bool { 131 return p.X.Cmp(pk.X) == 0 && 132 p.Y.Cmp(pk.Y) == 0 133 } 134 135 // String returns a string containing information of all attributes. 136 func (p *PublicKeySerializable) String() string { 137 b, _ := json.Marshal(p) 138 139 return fmt.Sprintf("S256Pubkey:%s", string(b)) 140 }