1// SPDX-License-Identifier: ISC 2// Copyright (c) 2014-2020 Bitmark Inc. 3// Use of this source code is governed by an ISC 4// license that can be found in the LICENSE file. 5 6package account 7 8import ( 9 "bytes" 10 11 "golang.org/x/crypto/ed25519" 12 "golang.org/x/crypto/sha3" 13 14 "github.com/bitmark-inc/bitmarkd/fault" 15 "github.com/bitmark-inc/bitmarkd/util" 16) 17 18// PrivateKey - base type for PrivateKey 19type PrivateKey struct { 20 PrivateKeyInterface 21} 22 23// PrivateKeyInterface - interface type for private key methods 24type PrivateKeyInterface interface { 25 Account() *Account 26 KeyType() int 27 PrivateKeyBytes() []byte 28 Bytes() []byte 29 String() string 30 IsTesting() bool 31 MarshalText() ([]byte, error) 32} 33 34// ED25519PrivateKey - structure for ed25519 keys 35type ED25519PrivateKey struct { 36 Test bool 37 PrivateKey []byte 38} 39 40// NothingPrivateKey - just for debugging 41type NothingPrivateKey struct { 42 Test bool 43 PrivateKey []byte 44} 45 46// PrivateKeyFromBase58 - this converts a Base58 encoded string and returns an private key 47// 48// one of the specific private key types are returned using the base "PrivateKeyInterface" 49// interface type to allow individual methods to be called. 50func PrivateKeyFromBase58(privateKeyBase58Encoded string) (*PrivateKey, error) { 51 // Decode the privateKey 52 privateKeyDecoded := util.FromBase58(privateKeyBase58Encoded) 53 if 0 == len(privateKeyDecoded) { 54 return nil, fault.CannotDecodePrivateKey 55 } 56 57 // Parse the key variant 58 keyVariant, keyVariantLength := util.FromVarint64(privateKeyDecoded) 59 60 // Check key type 61 if 0 == keyVariantLength || keyVariant&publicKeyCode == publicKeyCode { 62 return nil, fault.NotPrivateKey 63 } 64 65 // compute algorithm 66 keyAlgorithm := keyVariant >> algorithmShift 67 if keyAlgorithm >= algorithmLimit { 68 return nil, fault.InvalidKeyType 69 } 70 71 // network selection 72 isTest := 0 != keyVariant&testKeyCode 73 74 // Compute key length 75 keyLength := len(privateKeyDecoded) - keyVariantLength - checksumLength 76 if keyLength <= 0 { 77 return nil, fault.InvalidKeyLength 78 } 79 80 // Checksum 81 checksumStart := len(privateKeyDecoded) - checksumLength 82 checksum := sha3.Sum256(privateKeyDecoded[:checksumStart]) 83 if !bytes.Equal(checksum[:checksumLength], privateKeyDecoded[checksumStart:]) { 84 return nil, fault.ChecksumMismatch 85 } 86 87 // return a pointer to the specific private key type 88 switch keyAlgorithm { 89 case ED25519: 90 if keyLength != ed25519.PrivateKeySize { 91 return nil, fault.InvalidKeyLength 92 } 93 priv := privateKeyDecoded[keyVariantLength:checksumStart] 94 privateKey := &PrivateKey{ 95 PrivateKeyInterface: &ED25519PrivateKey{ 96 Test: isTest, 97 PrivateKey: priv, 98 }, 99 } 100 return privateKey, nil 101 case Nothing: 102 if 2 != keyLength { 103 return nil, fault.InvalidKeyLength 104 } 105 priv := privateKeyDecoded[keyVariantLength:checksumStart] 106 privateKey := &PrivateKey{ 107 PrivateKeyInterface: &NothingPrivateKey{ 108 Test: isTest, 109 PrivateKey: priv, 110 }, 111 } 112 return privateKey, nil 113 default: 114 return nil, fault.InvalidKeyType 115 } 116} 117 118// PrivateKeyFromBytes - this converts a byte encoded buffer and returns an private key 119// 120// one of the specific private key types are returned using the base "PrivateKeyInterface" 121// interface type to allow individual methods to be called. 122func PrivateKeyFromBytes(privateKeyBytes []byte) (*PrivateKey, error) { 123 124 // Parse the key variant 125 keyVariant, keyVariantLength := util.FromVarint64(privateKeyBytes) 126 127 // Check key type 128 if 0 == keyVariantLength || keyVariant&publicKeyCode == publicKeyCode { 129 return nil, fault.NotPrivateKey 130 } 131 132 // compute algorithm 133 keyAlgorithm := keyVariant >> algorithmShift 134 if keyAlgorithm >= algorithmLimit { 135 return nil, fault.InvalidKeyType 136 } 137 138 // network selection 139 isTest := 0 != keyVariant&testKeyCode 140 141 // Compute key length 142 keyLength := len(privateKeyBytes) - keyVariantLength 143 if keyLength <= 0 { 144 return nil, fault.InvalidKeyLength 145 } 146 147 // return a pointer to the specific private key type 148 switch keyAlgorithm { 149 case ED25519: 150 if keyLength != ed25519.PrivateKeySize { 151 return nil, fault.InvalidKeyLength 152 } 153 priv := privateKeyBytes[keyVariantLength:] 154 privateKey := &PrivateKey{ 155 PrivateKeyInterface: &ED25519PrivateKey{ 156 Test: isTest, 157 PrivateKey: priv, 158 }, 159 } 160 return privateKey, nil 161 case Nothing: 162 if 2 != keyLength { 163 return nil, fault.InvalidKeyLength 164 } 165 priv := privateKeyBytes[keyVariantLength:] 166 privateKey := &PrivateKey{ 167 PrivateKeyInterface: &NothingPrivateKey{ 168 Test: isTest, 169 PrivateKey: priv, 170 }, 171 } 172 return privateKey, nil 173 default: 174 return nil, fault.InvalidKeyType 175 } 176} 177 178// UnmarshalText - convert string to private key structure 179func (privateKey *PrivateKey) UnmarshalText(s []byte) error { 180 a, err := PrivateKeyFromBase58(string(s)) 181 if nil != err { 182 return err 183 } 184 privateKey.PrivateKeyInterface = a.PrivateKeyInterface 185 return nil 186} 187 188// ED25519 189// ------- 190 191// IsTesting - return whether the private key is in test mode or not 192func (privateKey *ED25519PrivateKey) IsTesting() bool { 193 return privateKey.Test 194} 195 196// KeyType - key type code (see enumeration in account.go) 197func (privateKey *ED25519PrivateKey) KeyType() int { 198 return ED25519 199} 200 201// Account - return the corresponding account 202func (privateKey *ED25519PrivateKey) Account() *Account { 203 return &Account{ 204 AccountInterface: &ED25519Account{ 205 Test: privateKey.Test, 206 PublicKey: privateKey.PrivateKey[ed25519.PrivateKeySize-ed25519.PublicKeySize:], 207 }, 208 } 209} 210 211// PrivateKeyBytes - fetch the private key as byte slice 212func (privateKey *ED25519PrivateKey) PrivateKeyBytes() []byte { 213 return privateKey.PrivateKey[:] 214} 215 216// Bytes - byte slice for encoded key 217func (privateKey *ED25519PrivateKey) Bytes() []byte { 218 keyVariant := byte(ED25519 << algorithmShift) 219 if privateKey.Test { 220 keyVariant |= testKeyCode 221 } 222 return append([]byte{keyVariant}, privateKey.PrivateKey[:]...) 223} 224 225// String - base58 encoding of encoded key 226func (privateKey *ED25519PrivateKey) String() string { 227 buffer := privateKey.Bytes() 228 checksum := sha3.Sum256(buffer) 229 buffer = append(buffer, checksum[:checksumLength]...) 230 return util.ToBase58(buffer) 231} 232 233// MarshalText - convert an privateKey to its Base58 JSON form 234func (privateKey ED25519PrivateKey) MarshalText() ([]byte, error) { 235 return []byte(privateKey.String()), nil 236} 237 238// Nothing 239// ------- 240 241// IsTesting - return whether the private key is in test mode or not 242func (privateKey *NothingPrivateKey) IsTesting() bool { 243 return privateKey.Test 244} 245 246// KeyType - key type code (see enumeration in account.go) 247func (privateKey *NothingPrivateKey) KeyType() int { 248 return Nothing 249} 250 251// Account - return the corresponding account 252func (privateKey *NothingPrivateKey) Account() *Account { 253 return nil 254} 255 256// PrivateKeyBytes - fetch the private key as byte slice 257func (privateKey *NothingPrivateKey) PrivateKeyBytes() []byte { 258 return privateKey.PrivateKey[:] 259} 260 261// Bytes - byte slice for encoded key 262func (privateKey *NothingPrivateKey) Bytes() []byte { 263 keyVariant := byte(Nothing << algorithmShift) 264 if privateKey.Test { 265 keyVariant |= testKeyCode 266 } 267 return append([]byte{keyVariant}, privateKey.PrivateKey[:]...) 268} 269 270// String - base58 encoding of encoded key 271func (privateKey *NothingPrivateKey) String() string { 272 buffer := privateKey.Bytes() 273 checksum := sha3.Sum256(buffer) 274 buffer = append(buffer, checksum[:checksumLength]...) 275 return util.ToBase58(buffer) 276} 277 278// MarshalText - convert an privateKey to its Base58 JSON form 279func (privateKey NothingPrivateKey) MarshalText() ([]byte, error) { 280 return []byte(privateKey.String()), nil 281} 282