github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/ed25519_private_key.go (about) 1 package hedera 2 3 /*- 4 * 5 * Hedera Go SDK 6 * 7 * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 */ 22 23 import ( 24 "crypto/ed25519" 25 "crypto/hmac" 26 "crypto/rand" 27 "crypto/sha512" 28 "crypto/x509/pkix" 29 "encoding/asn1" 30 "encoding/hex" 31 "encoding/pem" 32 "fmt" 33 "io" 34 "strings" 35 36 "github.com/hashgraph/hedera-protobufs-go/services" 37 "github.com/pkg/errors" 38 "github.com/youmark/pkcs8" 39 ) 40 41 // _Ed25519PrivateKey is an ed25519 private key. 42 type _Ed25519PrivateKey struct { 43 keyData []byte 44 chainCode []byte 45 } 46 47 func _GenerateEd25519PrivateKey() (*_Ed25519PrivateKey, error) { 48 _, privateKey, err := ed25519.GenerateKey(rand.Reader) 49 if err != nil { 50 return &_Ed25519PrivateKey{}, err 51 } 52 53 return &_Ed25519PrivateKey{ 54 keyData: privateKey, 55 }, nil 56 } 57 58 // Deprecated 59 func GeneratePrivateKey() (PrivateKey, error) { 60 _, privateKey, err := ed25519.GenerateKey(rand.Reader) 61 if err != nil { 62 return PrivateKey{}, err 63 } 64 65 return PrivateKey{ 66 ed25519PrivateKey: &_Ed25519PrivateKey{ 67 keyData: privateKey, 68 }, 69 }, nil 70 } 71 72 // _Ed25519PrivateKeyFromBytes constructs an _Ed25519PrivateKey from a raw slice of either 32 or 64 bytes. 73 func _Ed25519PrivateKeyFromBytes(bytes []byte) (*_Ed25519PrivateKey, error) { 74 length := len(bytes) 75 switch length { 76 case 48: 77 return _Ed25519PrivateKeyFromBytesDer(bytes) 78 case 32: 79 return _Ed25519PrivateKeyFromBytesRaw(bytes) 80 case 64: 81 return _Ed25519PrivateKeyFromBytesRaw(bytes) 82 default: 83 return &_Ed25519PrivateKey{}, _NewErrBadKeyf("invalid private key length: %v bytes", len(bytes)) 84 } 85 } 86 87 // _Ed25519PrivateKeyFromBytes constructs an _Ed25519PrivateKey from a raw slice of either 32 or 64 bytes. 88 func _Ed25519PrivateKeyFromBytesRaw(bytes []byte) (*_Ed25519PrivateKey, error) { 89 return &_Ed25519PrivateKey{ 90 keyData: ed25519.NewKeyFromSeed(bytes[0:32]), 91 }, nil 92 } 93 94 // _Ed25519PrivateKeyFromBytes constructs an _Ed25519PrivateKey from a raw slice of either 32 or 64 bytes. 95 func _Ed25519PrivateKeyFromBytesDer(byt []byte) (*_Ed25519PrivateKey, error) { 96 given := hex.EncodeToString(byt) 97 result := strings.ReplaceAll(given, _Ed25519PrivateKeyPrefix, "") 98 decoded, err := hex.DecodeString(result) 99 if err != nil { 100 return &_Ed25519PrivateKey{}, err 101 } 102 103 length := len(decoded) 104 if length != 32 && length != 64 { 105 return &_Ed25519PrivateKey{}, _NewErrBadKeyf("invalid private key length: %v byt", len(byt)) 106 } 107 108 return &_Ed25519PrivateKey{ 109 keyData: ed25519.NewKeyFromSeed(decoded[0:32]), 110 }, nil 111 } 112 113 func _Ed25519PrivateKeyFromSeed(seed []byte) (*_Ed25519PrivateKey, error) { 114 h := hmac.New(sha512.New, []byte("ed25519 seed")) 115 116 _, err := h.Write(seed) 117 if err != nil { 118 return nil, err 119 } 120 121 digest := h.Sum(nil) 122 123 keyBytes := digest[0:32] 124 chainCode := digest[32:] 125 privateKey, err := _Ed25519PrivateKeyFromBytes(keyBytes) 126 127 if err != nil { 128 return nil, err 129 } 130 privateKey.chainCode = chainCode 131 132 return privateKey, nil 133 } 134 135 // Deprecated 136 // PrivateKeyFromMnemonic recovers an _Ed25519PrivateKey from a valid 24 word length mnemonic phrase and a 137 // passphrase. 138 // 139 // An empty string can be passed for passPhrase If the mnemonic phrase wasn't generated with a passphrase. This is 140 // required to recover a private key from a mnemonic generated by the Android and iOS wallets. 141 func _Ed25519PrivateKeyFromMnemonic(mnemonic Mnemonic, passPhrase string) (*_Ed25519PrivateKey, error) { 142 seed := mnemonic._ToSeed(passPhrase) 143 keyFromSeed, err := _Ed25519PrivateKeyFromSeed(seed) 144 if err != nil { 145 return nil, err 146 } 147 148 keyBytes := keyFromSeed.keyData 149 chainCode := keyFromSeed.chainCode 150 151 // note the index is for derivation, not the index of the slice 152 for _, index := range []uint32{44, 3030, 0, 0} { 153 keyBytes, chainCode, err = _DeriveEd25519ChildKey(keyBytes, chainCode, index) 154 if err != nil { 155 return nil, err 156 } 157 } 158 159 privateKey, err := _Ed25519PrivateKeyFromBytes(keyBytes) 160 161 if err != nil { 162 return nil, err 163 } 164 165 privateKey.chainCode = chainCode 166 167 return privateKey, nil 168 } 169 170 func _Ed25519PrivateKeyFromString(s string) (*_Ed25519PrivateKey, error) { 171 bytes, err := hex.DecodeString(strings.ToLower(s)) 172 if err != nil { 173 return &_Ed25519PrivateKey{}, err 174 } 175 176 return _Ed25519PrivateKeyFromBytes(bytes) 177 } 178 179 // PrivateKeyFromKeystore recovers an _Ed25519PrivateKey from an encrypted _Keystore encoded as a byte slice. 180 func _Ed25519PrivateKeyFromKeystore(ks []byte, passphrase string) (*_Ed25519PrivateKey, error) { 181 key, err := _ParseKeystore(ks, passphrase) 182 if err != nil { 183 return &_Ed25519PrivateKey{}, err 184 } 185 186 if key.ed25519PrivateKey != nil { 187 return key.ed25519PrivateKey, nil 188 } 189 190 return &_Ed25519PrivateKey{}, errors.New("only ed25519 keys are currently supported") 191 } 192 193 // PrivateKeyReadKeystore recovers an _Ed25519PrivateKey from an encrypted _Keystore file. 194 func _Ed25519PrivateKeyReadKeystore(source io.Reader, passphrase string) (*_Ed25519PrivateKey, error) { 195 keystoreBytes, err := io.ReadAll(source) 196 if err != nil { 197 return &_Ed25519PrivateKey{}, err 198 } 199 200 return _Ed25519PrivateKeyFromKeystore(keystoreBytes, passphrase) 201 } 202 203 func _Ed25519PrivateKeyFromPem(bytes []byte, passphrase string) (*_Ed25519PrivateKey, error) { 204 var blockType string 205 206 if len(passphrase) == 0 { 207 blockType = "PRIVATE KEY" 208 } else { 209 // the pem is encrypted 210 blockType = "ENCRYPTED PRIVATE KEY" 211 } 212 213 var pk *pem.Block 214 for block, rest := pem.Decode(bytes); block != nil; { 215 if block.Type == blockType { 216 pk = block 217 break 218 } 219 220 bytes = rest 221 if len(bytes) == 0 { 222 // no key was found 223 return &_Ed25519PrivateKey{}, _NewErrBadKeyf("pem file did not contain a private key") 224 } 225 } 226 227 if pk == nil { 228 // no key was found 229 return &_Ed25519PrivateKey{}, _NewErrBadKeyf("no PEM data is found") 230 } 231 232 if len(passphrase) == 0 { 233 // key does not need decrypted, end here 234 key, err := PrivateKeyFromString(hex.EncodeToString(pk.Bytes)) 235 if err != nil { 236 return &_Ed25519PrivateKey{}, err 237 } 238 return key.ed25519PrivateKey, nil 239 } 240 241 keyI, err := pkcs8.ParsePKCS8PrivateKey(pk.Bytes, []byte(passphrase)) 242 if err != nil { 243 return &_Ed25519PrivateKey{}, err 244 } 245 246 return _Ed25519PrivateKeyFromBytes(keyI.(ed25519.PrivateKey)) 247 } 248 249 func _Ed25519PrivateKeyReadPem(source io.Reader, passphrase string) (*_Ed25519PrivateKey, error) { 250 // note: Passphrases are currently not supported, but included in the function definition to avoid breaking 251 // changes in the future. 252 253 pemFileBytes, err := io.ReadAll(source) 254 if err != nil { 255 return &_Ed25519PrivateKey{}, err 256 } 257 258 return _Ed25519PrivateKeyFromPem(pemFileBytes, passphrase) 259 } 260 261 // _Ed25519PublicKey returns the _Ed25519PublicKey associated with this _Ed25519PrivateKey. 262 func (sk _Ed25519PrivateKey) _PublicKey() *_Ed25519PublicKey { 263 return &_Ed25519PublicKey{ 264 keyData: sk.keyData[32:], 265 } 266 } 267 268 // String returns the text-encoded representation of the _Ed25519PrivateKey. 269 func (sk _Ed25519PrivateKey) String() string { 270 return sk._StringRaw() 271 } 272 273 // String returns the text-encoded representation of the _Ed25519PrivateKey. 274 func (sk _Ed25519PrivateKey) _StringDer() string { 275 return fmt.Sprint(_Ed25519PrivateKeyPrefix, hex.EncodeToString(sk.keyData[:32])) 276 } 277 278 // String returns the text-encoded representation of the _Ed25519PrivateKey. 279 func (sk _Ed25519PrivateKey) _StringRaw() string { 280 return hex.EncodeToString(sk.keyData[:32]) 281 } 282 283 // _BytesRaw returns the byte slice representation of the _Ed25519PrivateKey. 284 func (sk _Ed25519PrivateKey) _BytesRaw() []byte { 285 return sk.keyData[0:32] 286 } 287 288 func (sk _Ed25519PrivateKey) _BytesDer() []byte { 289 type PrivateKeyInfo struct { 290 Version int 291 PrivateKeyAlgorithm pkix.AlgorithmIdentifier 292 PrivateKey asn1.RawValue 293 } 294 295 // AlgorithmIdentifier for Ed25519 keys 296 ed25519OID := asn1.ObjectIdentifier{1, 3, 101, 112} 297 privateKeyBytes, err := asn1.Marshal(sk.keyData[:32]) 298 if err != nil { 299 return nil 300 } 301 privateKeyInfo := PrivateKeyInfo{ 302 Version: 0, 303 PrivateKeyAlgorithm: pkix.AlgorithmIdentifier{ 304 Algorithm: ed25519OID, 305 }, 306 PrivateKey: asn1.RawValue{ 307 Tag: asn1.TagOctetString, 308 Class: asn1.ClassUniversal, 309 Bytes: privateKeyBytes, 310 }, 311 } 312 313 derBytes, err := asn1.Marshal(privateKeyInfo) 314 if err != nil { 315 return nil 316 } 317 318 return derBytes 319 } 320 321 // Keystore returns an encrypted _Keystore containing the _Ed25519PrivateKey. 322 func (sk _Ed25519PrivateKey) _Keystore(passphrase string) ([]byte, error) { 323 return _NewKeystore(sk.keyData, passphrase) 324 } 325 326 // WriteKeystore writes an encrypted _Keystore containing the _Ed25519PrivateKey to the provided destination. 327 func (sk _Ed25519PrivateKey) _WriteKeystore(destination io.Writer, passphrase string) error { 328 keystore, err := sk._Keystore(passphrase) 329 if err != nil { 330 return err 331 } 332 333 _, err = destination.Write(keystore) 334 335 return err 336 } 337 338 // Sign signs the provided message with the _Ed25519PrivateKey. 339 func (sk _Ed25519PrivateKey) _Sign(message []byte) []byte { 340 return ed25519.Sign(sk.keyData, message) 341 } 342 343 // SupportsDerivation returns true if the _Ed25519PrivateKey supports derivation. 344 func (sk _Ed25519PrivateKey) _SupportsDerivation() bool { 345 return sk.chainCode != nil 346 } 347 348 // Derive a child key compatible with the iOS and Android wallets using a provided wallet/account index. Use index 0 for 349 // the default account. 350 // 351 // This will fail if the key does not support derivation which can be checked by calling SupportsDerivation() 352 func (sk _Ed25519PrivateKey) _Derive(index uint32) (*_Ed25519PrivateKey, error) { 353 if !sk._SupportsDerivation() { 354 return nil, _NewErrBadKeyf("child key cannot be derived from this key") 355 } 356 357 derivedKeyBytes, chainCode, err := _DeriveEd25519ChildKey(sk._BytesRaw(), sk.chainCode, index) 358 if err != nil { 359 return nil, err 360 } 361 362 derivedKey, err := _Ed25519PrivateKeyFromBytes(derivedKeyBytes) 363 364 if err != nil { 365 return nil, err 366 } 367 368 derivedKey.chainCode = chainCode 369 370 return derivedKey, nil 371 } 372 373 func (sk _Ed25519PrivateKey) _LegacyDerive(index int64) (*_Ed25519PrivateKey, error) { 374 keyData, err := _DeriveLegacyChildKey(sk._BytesRaw(), index) 375 if err != nil { 376 return nil, err 377 } 378 379 return _Ed25519PrivateKeyFromBytes(keyData) 380 } 381 382 func (sk _Ed25519PrivateKey) _ToProtoKey() *services.Key { 383 return sk._PublicKey()._ToProtoKey() 384 } 385 386 func (sk _Ed25519PrivateKey) _SignTransaction(tx *Transaction) ([]byte, error) { 387 tx._RequireOneNodeAccountID() 388 389 if tx.signedTransactions._Length() == 0 { 390 return make([]byte, 0), errTransactionRequiresSingleNodeAccountID 391 } 392 393 signature := sk._Sign(tx.signedTransactions._Get(0).(*services.SignedTransaction).GetBodyBytes()) 394 395 publicKey := sk._PublicKey() 396 if publicKey == nil { 397 return []byte{}, errors.New("public key is nil") 398 } 399 400 wrappedPublicKey := PublicKey{ 401 ed25519PublicKey: publicKey, 402 } 403 404 if tx._KeyAlreadySigned(wrappedPublicKey) { 405 return []byte{}, nil 406 } 407 408 tx.transactions = _NewLockableSlice() 409 tx.publicKeys = append(tx.publicKeys, wrappedPublicKey) 410 tx.transactionSigners = append(tx.transactionSigners, nil) 411 tx.transactionIDs.locked = true 412 413 for index := 0; index < tx.signedTransactions._Length(); index++ { 414 temp := tx.signedTransactions._Get(index).(*services.SignedTransaction) 415 temp.SigMap.SigPair = append( 416 temp.SigMap.SigPair, 417 publicKey._ToSignaturePairProtobuf(signature), 418 ) 419 tx.signedTransactions._Set(index, temp) 420 } 421 422 return signature, nil 423 }