github.com/mavryk-network/mvgo@v1.19.9/mavryk/key.go (about) 1 // Copyright (c) 2020-2023 Blockwatch Data Inc. 2 // Author: alex@blockwatch.cc 3 4 package mavryk 5 6 import ( 7 "bytes" 8 "errors" 9 "fmt" 10 "strings" 11 12 "crypto/ecdsa" 13 "crypto/ed25519" 14 "crypto/elliptic" 15 "crypto/rand" 16 17 "github.com/mavryk-network/mvgo/base58" 18 19 "github.com/decred/dcrd/dcrec/secp256k1/v4" 20 "golang.org/x/crypto/blake2b" 21 ) 22 23 var ( 24 // ErrUnknownKeyType describes an error where a type for a 25 // public key is undefined. 26 ErrUnknownKeyType = errors.New("tezos: unknown key type") 27 28 // ErrPassphrase is returned when a required passphrase is missing 29 ErrPassphrase = errors.New("tezos: passphrase required") 30 31 InvalidKey = Key{Type: KeyTypeInvalid, Data: nil} 32 33 // Digest is an alias for blake2b checksum algorithm 34 Digest = blake2b.Sum256 35 ) 36 37 // PassphraseFunc is a callback used to obtain a passphrase for decrypting a private key 38 type PassphraseFunc func() ([]byte, error) 39 40 // KeyType is a type that describes which cryptograhic curve is used by a public or 41 // private key 42 type KeyType byte 43 44 const ( 45 KeyTypeEd25519 KeyType = iota 46 KeyTypeSecp256k1 47 KeyTypeP256 48 KeyTypeBls12_381 49 KeyTypeInvalid 50 ) 51 52 func (t KeyType) IsValid() bool { 53 return t < KeyTypeInvalid 54 } 55 56 func (t KeyType) String() string { 57 return t.PkPrefix() 58 } 59 60 func (t KeyType) Curve() elliptic.Curve { 61 switch t { 62 case KeyTypeSecp256k1: 63 return secp256k1.S256() 64 case KeyTypeP256: 65 return elliptic.P256() 66 default: 67 return nil 68 } 69 } 70 71 func (t KeyType) PkHashType() HashType { 72 switch t { 73 case KeyTypeEd25519: 74 return HashTypePkEd25519 75 case KeyTypeSecp256k1: 76 return HashTypePkSecp256k1 77 case KeyTypeP256: 78 return HashTypePkP256 79 case KeyTypeBls12_381: 80 return HashTypePkBls12_381 81 default: 82 return HashTypeInvalid 83 } 84 } 85 86 func (t KeyType) SkHashType() HashType { 87 switch t { 88 case KeyTypeEd25519: 89 return HashTypeSkEd25519 90 case KeyTypeSecp256k1: 91 return HashTypeSkSecp256k1 92 case KeyTypeP256: 93 return HashTypeSkP256 94 case KeyTypeBls12_381: 95 return HashTypeSkBls12_381 96 default: 97 return HashTypeInvalid 98 } 99 } 100 101 func (t KeyType) AddressType() AddressType { 102 switch t { 103 case KeyTypeEd25519: 104 return AddressTypeEd25519 105 case KeyTypeSecp256k1: 106 return AddressTypeSecp256k1 107 case KeyTypeP256: 108 return AddressTypeP256 109 case KeyTypeBls12_381: 110 return AddressTypeBls12_381 111 default: 112 return AddressTypeInvalid 113 } 114 } 115 116 func (t KeyType) PkPrefixBytes() []byte { 117 switch t { 118 case KeyTypeEd25519: 119 return ED25519_PUBLIC_KEY_ID 120 case KeyTypeSecp256k1: 121 return SECP256K1_PUBLIC_KEY_ID 122 case KeyTypeP256: 123 return P256_PUBLIC_KEY_ID 124 case KeyTypeBls12_381: 125 return BLS12_381_PUBLIC_KEY_ID 126 default: 127 return nil 128 } 129 } 130 131 func (t KeyType) PkPrefix() string { 132 switch t { 133 case KeyTypeEd25519: 134 return ED25519_PUBLIC_KEY_PREFIX 135 case KeyTypeSecp256k1: 136 return SECP256K1_PUBLIC_KEY_PREFIX 137 case KeyTypeP256: 138 return P256_PUBLIC_KEY_PREFIX 139 case KeyTypeBls12_381: 140 return BLS12_381_PUBLIC_KEY_PREFIX 141 default: 142 return "" 143 } 144 } 145 146 func (t KeyType) SkPrefixBytes() []byte { 147 switch t { 148 case KeyTypeEd25519: 149 return ED25519_SEED_ID 150 case KeyTypeSecp256k1: 151 return SECP256K1_SECRET_KEY_ID 152 case KeyTypeP256: 153 return P256_SECRET_KEY_ID 154 case KeyTypeBls12_381: 155 return BLS12_381_SECRET_KEY_ID 156 default: 157 return nil 158 } 159 } 160 161 func (t KeyType) SkePrefixBytes() []byte { 162 switch t { 163 case KeyTypeEd25519: 164 return ED25519_ENCRYPTED_SEED_ID 165 case KeyTypeSecp256k1: 166 return SECP256K1_ENCRYPTED_SECRET_KEY_ID 167 case KeyTypeP256: 168 return P256_ENCRYPTED_SECRET_KEY_ID 169 case KeyTypeBls12_381: 170 return BLS12_381_SECRET_KEY_ID 171 default: 172 return nil 173 } 174 } 175 176 func (t KeyType) SkPrefix() string { 177 switch t { 178 case KeyTypeEd25519: 179 return ED25519_SECRET_KEY_PREFIX 180 case KeyTypeSecp256k1: 181 return SECP256K1_SECRET_KEY_PREFIX 182 case KeyTypeP256: 183 return P256_SECRET_KEY_PREFIX 184 case KeyTypeBls12_381: 185 return BLS12_381_SECRET_KEY_PREFIX 186 default: 187 return "" 188 } 189 } 190 191 func (t KeyType) SkePrefix() string { 192 switch t { 193 case KeyTypeEd25519: 194 return ED25519_ENCRYPTED_SEED_PREFIX 195 case KeyTypeSecp256k1: 196 return SECP256K1_ENCRYPTED_SECRET_KEY_PREFIX 197 case KeyTypeP256: 198 return P256_ENCRYPTED_SECRET_KEY_PREFIX 199 case KeyTypeBls12_381: 200 return BLS12_381_ENCRYPTED_SECRET_KEY_PREFIX 201 default: 202 return "" 203 } 204 } 205 206 func (t KeyType) Tag() byte { 207 switch t { 208 case KeyTypeEd25519: 209 return 0 210 case KeyTypeSecp256k1: 211 return 1 212 case KeyTypeP256: 213 return 2 214 case KeyTypeBls12_381: 215 return 3 216 default: 217 return 255 218 } 219 } 220 221 func ParseKeyTag(b byte) KeyType { 222 switch b { 223 case 0: 224 return KeyTypeEd25519 225 case 1: 226 return KeyTypeSecp256k1 227 case 2: 228 return KeyTypeP256 229 case 3: 230 return KeyTypeBls12_381 231 default: 232 return KeyTypeInvalid 233 } 234 } 235 236 func ParseKeyType(s string) (KeyType, bool) { 237 switch s { 238 case ED25519_ENCRYPTED_SEED_PREFIX: 239 return KeyTypeEd25519, true 240 case SECP256K1_ENCRYPTED_SECRET_KEY_PREFIX: 241 return KeyTypeSecp256k1, true 242 case P256_ENCRYPTED_SECRET_KEY_PREFIX: 243 return KeyTypeP256, true 244 case BLS12_381_ENCRYPTED_SECRET_KEY_PREFIX: 245 return KeyTypeBls12_381, true 246 case ED25519_SEED_PREFIX: // same as ED25519_SECRET_KEY_PREFIX 247 return KeyTypeEd25519, false 248 case SECP256K1_SECRET_KEY_PREFIX: 249 return KeyTypeSecp256k1, false 250 case P256_SECRET_KEY_PREFIX: 251 return KeyTypeP256, false 252 case BLS12_381_SECRET_KEY_PREFIX: 253 return KeyTypeBls12_381, false 254 default: 255 return KeyTypeInvalid, false 256 } 257 } 258 259 func IsPublicKey(s string) bool { 260 for _, prefix := range []string{ 261 ED25519_PUBLIC_KEY_PREFIX, 262 SECP256K1_PUBLIC_KEY_PREFIX, 263 P256_PUBLIC_KEY_PREFIX, 264 BLS12_381_PUBLIC_KEY_PREFIX, 265 } { 266 if strings.HasPrefix(s, prefix) { 267 return true 268 } 269 } 270 return false 271 } 272 273 func IsPrivateKey(s string) bool { 274 for _, prefix := range []string{ 275 ED25519_SEED_PREFIX, 276 ED25519_SECRET_KEY_PREFIX, 277 SECP256K1_SECRET_KEY_PREFIX, 278 P256_SECRET_KEY_PREFIX, 279 BLS12_381_SECRET_KEY_PREFIX, 280 ED25519_ENCRYPTED_SEED_PREFIX, 281 SECP256K1_ENCRYPTED_SECRET_KEY_PREFIX, 282 P256_ENCRYPTED_SECRET_KEY_PREFIX, 283 BLS12_381_ENCRYPTED_SECRET_KEY_PREFIX, 284 } { 285 if strings.HasPrefix(s, prefix) { 286 return true 287 } 288 } 289 return false 290 } 291 292 func IsEncryptedKey(s string) bool { 293 for _, prefix := range []string{ 294 ED25519_ENCRYPTED_SEED_PREFIX, 295 SECP256K1_ENCRYPTED_SECRET_KEY_PREFIX, 296 P256_ENCRYPTED_SECRET_KEY_PREFIX, 297 BLS12_381_ENCRYPTED_SECRET_KEY_PREFIX, 298 } { 299 if strings.HasPrefix(s, prefix) { 300 return true 301 } 302 } 303 return false 304 } 305 306 func HasKeyPrefix(s string) bool { 307 return IsPublicKey(s) || IsPrivateKey(s) 308 } 309 310 // Key represents a public key on the Tezos blockchain. 311 type Key struct { 312 Type KeyType 313 Data []byte 314 } 315 316 func NewKey(typ KeyType, data []byte) Key { 317 return Key{ 318 Type: typ, 319 Data: data, 320 } 321 } 322 323 // Verify verifies the signature using the public key. 324 func (k Key) Verify(hash []byte, sig Signature) error { 325 switch k.Type { 326 case KeyTypeEd25519: 327 pk := ed25519.PublicKey(k.Data) 328 if ok := ed25519.Verify(pk, hash, sig.Data); !ok { 329 return ErrSignature 330 } 331 case KeyTypeSecp256k1, KeyTypeP256: 332 curve := k.Type.Curve() 333 pk, err := ecUnmarshalCompressed(curve, k.Data) 334 if err != nil { 335 return err 336 } 337 if ok := ecVerifySignature(pk, hash, sig); !ok { 338 return ErrSignature 339 } 340 case KeyTypeBls12_381: 341 // TODO 342 } 343 return nil 344 } 345 346 func (k Key) IsValid() bool { 347 return k.Type.IsValid() && k.Type.PkHashType().Len == len(k.Data) 348 } 349 350 func (k Key) IsEqual(k2 Key) bool { 351 return k.Type == k2.Type && bytes.Equal(k.Data, k2.Data) 352 } 353 354 func (k Key) Clone() Key { 355 buf := make([]byte, len(k.Data)) 356 copy(buf, k.Data) 357 return Key{ 358 Type: k.Type, 359 Data: buf, 360 } 361 } 362 363 func (k Key) Hash() []byte { 364 h, _ := blake2b.New(20, nil) 365 h.Write(k.Data) 366 return h.Sum(nil) 367 } 368 369 func (k Key) Address() Address { 370 return NewAddress(k.Type.AddressType(), k.Hash()) 371 } 372 373 func (k Key) String() string { 374 if !k.IsValid() { 375 return "" 376 } 377 return base58.CheckEncode(k.Data, k.Type.PkPrefixBytes()) 378 } 379 380 func (k Key) MarshalText() ([]byte, error) { 381 return []byte(k.String()), nil 382 } 383 384 func (k *Key) UnmarshalText(data []byte) error { 385 key, err := ParseKey(string(data)) 386 if err != nil { 387 return err 388 } 389 *k = key 390 return nil 391 } 392 393 func (k Key) MarshalBinary() ([]byte, error) { 394 return k.Bytes(), nil 395 } 396 397 func (k Key) Bytes() []byte { 398 if !k.Type.IsValid() || len(k.Data) == 0 { 399 return nil 400 } 401 return append([]byte{k.Type.Tag()}, k.Data...) 402 } 403 404 func DecodeKey(buf []byte) (Key, error) { 405 k := Key{} 406 if len(buf) == 0 { 407 return k, nil 408 } 409 if err := k.UnmarshalBinary(buf); err != nil { 410 return k, err 411 } 412 return k, nil 413 } 414 415 func (k *Key) UnmarshalBinary(b []byte) error { 416 l := len(b) 417 // allow empty keys 418 if l == 0 { 419 k.Type = KeyTypeInvalid 420 return nil 421 } 422 // check data size 423 if l < 33 { 424 return fmt.Errorf("tezos: invalid binary key length %d", l) 425 } 426 if typ := ParseKeyTag(b[0]); !typ.IsValid() { 427 return fmt.Errorf("tezos: invalid binary key type %x", b[0]) 428 } else { 429 k.Type = typ 430 } 431 if cap(k.Data) < l-1 { 432 k.Data = make([]byte, l-1) 433 } else { 434 k.Data = k.Data[:l-1] 435 } 436 copy(k.Data, b[1:]) 437 return nil 438 } 439 440 func (k *Key) EncodeBuffer(buf *bytes.Buffer) error { 441 _, err := buf.Write(k.Bytes()) 442 return err 443 } 444 445 func (k *Key) DecodeBuffer(buf *bytes.Buffer) error { 446 if l := buf.Len(); l < 33 { 447 return fmt.Errorf("tezos: invalid binary key length %d", l) 448 } 449 tag := buf.Next(1)[0] 450 if typ := ParseKeyTag(tag); !typ.IsValid() { 451 return fmt.Errorf("tezos: invalid binary key type %x", tag) 452 } else { 453 k.Type = typ 454 } 455 l := k.Type.PkHashType().Len 456 k.Data = make([]byte, l) 457 copy(k.Data, buf.Next(l)) 458 if !k.IsValid() { 459 return fmt.Errorf("tezos: invalid binary key typ=%s len=%d", k.Type, len(k.Data)) 460 } 461 return nil 462 } 463 464 func ParseKey(s string) (Key, error) { 465 k := Key{} 466 if len(s) == 0 { 467 return k, nil 468 } 469 decoded, version, err := base58.CheckDecode(s, 4, nil) 470 if err != nil { 471 if err == base58.ErrChecksum { 472 return k, ErrChecksumMismatch 473 } 474 return k, fmt.Errorf("tezos: unknown format for key %s: %w", s, err) 475 } 476 switch { 477 case bytes.Equal(version, ED25519_PUBLIC_KEY_ID): 478 k.Type = KeyTypeEd25519 479 case bytes.Equal(version, SECP256K1_PUBLIC_KEY_ID): 480 k.Type = KeyTypeSecp256k1 481 case bytes.Equal(version, P256_PUBLIC_KEY_ID): 482 k.Type = KeyTypeP256 483 case bytes.Equal(version, BLS12_381_PUBLIC_KEY_ID): 484 k.Type = KeyTypeBls12_381 485 default: 486 return k, fmt.Errorf("tezos: unknown version %x for key %s", version, s) 487 } 488 if l := len(decoded); l != k.Type.PkHashType().Len { 489 return k, fmt.Errorf("tezos: invalid length %d for %s key data", l, k.Type.PkPrefix()) 490 } 491 k.Data = decoded 492 return k, nil 493 } 494 495 func MustParseKey(key string) Key { 496 k, err := ParseKey(key) 497 if err != nil { 498 panic(err) 499 } 500 return k 501 } 502 503 // Set implements the flags.Value interface for use in command line argument parsing. 504 func (k *Key) Set(key string) (err error) { 505 *k, err = ParseKey(key) 506 return 507 } 508 509 // PrivateKey represents a typed private key used for signing messages. 510 type PrivateKey struct { 511 Type KeyType 512 Data []byte 513 } 514 515 func (k PrivateKey) IsValid() bool { 516 return k.Type.IsValid() && k.Type.SkHashType().Len == len(k.Data) 517 } 518 519 func (k PrivateKey) String() string { 520 var buf []byte 521 switch k.Type { 522 case KeyTypeEd25519: 523 buf = ed25519.PrivateKey(k.Data).Seed() 524 case KeyTypeSecp256k1, KeyTypeP256, KeyTypeBls12_381: 525 buf = k.Data 526 default: 527 return "" 528 } 529 return base58.CheckEncode(buf, k.Type.SkPrefixBytes()) 530 } 531 532 func (k PrivateKey) Address() Address { 533 return k.Public().Address() 534 } 535 536 func (k PrivateKey) MarshalText() ([]byte, error) { 537 return []byte(k.String()), nil 538 } 539 540 func (k *PrivateKey) UnmarshalText(data []byte) error { 541 key, err := ParsePrivateKey(string(data)) 542 if err != nil { 543 return err 544 } 545 *k = key 546 return nil 547 } 548 549 // GenerateKey creates a random private key. 550 func GenerateKey(typ KeyType) (PrivateKey, error) { 551 key := PrivateKey{ 552 Type: typ, 553 } 554 switch typ { 555 case KeyTypeEd25519: 556 _, sk, err := ed25519.GenerateKey(nil) 557 if err != nil { 558 return key, err 559 } 560 key.Data = []byte(sk) 561 case KeyTypeSecp256k1, KeyTypeP256: 562 curve := typ.Curve() 563 ecKey, err := ecdsa.GenerateKey(curve, rand.Reader) 564 if err != nil { 565 return key, err 566 } 567 key.Data = make([]byte, typ.SkHashType().Len) 568 ecKey.D.FillBytes(key.Data) 569 case KeyTypeBls12_381: 570 // TODO 571 } 572 return key, nil 573 } 574 575 // Public returns the public key associated with the private key. 576 func (k PrivateKey) Public() Key { 577 pk := Key{ 578 Type: k.Type, 579 } 580 switch k.Type { 581 case KeyTypeEd25519: 582 pk.Data = []byte(ed25519.PrivateKey(k.Data).Public().(ed25519.PublicKey)) 583 case KeyTypeSecp256k1, KeyTypeP256: 584 curve := k.Type.Curve() 585 ecKey, err := ecPrivateKeyFromBytes(k.Data, curve) 586 if err != nil { 587 pk.Type = KeyTypeInvalid 588 return pk 589 } 590 pk.Data = elliptic.MarshalCompressed(curve, ecKey.PublicKey.X, ecKey.PublicKey.Y) 591 case KeyTypeBls12_381: 592 // TODO 593 } 594 return pk 595 } 596 597 // Encrypt encrypts the private key with a passphrase obtained from calling fn. 598 func (k PrivateKey) Encrypt(fn PassphraseFunc) (string, error) { 599 var buf []byte 600 switch k.Type { 601 case KeyTypeEd25519: 602 buf = ed25519.PrivateKey(k.Data).Seed() 603 case KeyTypeSecp256k1, KeyTypeP256: 604 buf = k.Data 605 case KeyTypeBls12_381: 606 // TODO 607 } 608 enc, err := encryptPrivateKey(buf, fn) 609 if err != nil { 610 return "", err 611 } 612 return base58.CheckEncode(enc, k.Type.SkePrefixBytes()), nil 613 } 614 615 // Sign signs the digest (hash) of a message with the private key. 616 func (k PrivateKey) Sign(hash []byte) (Signature, error) { 617 switch k.Type { 618 case KeyTypeEd25519: 619 return Signature{ 620 Type: SignatureTypeEd25519, 621 Data: ed25519.Sign(ed25519.PrivateKey(k.Data), hash), 622 }, nil 623 case KeyTypeSecp256k1, KeyTypeP256: 624 curve := k.Type.Curve() 625 sig := Signature{ 626 Type: SignatureTypeSecp256k1, 627 } 628 if k.Type == KeyTypeP256 { 629 sig.Type = SignatureTypeP256 630 } 631 ecKey, err := ecPrivateKeyFromBytes(k.Data, curve) 632 if err != nil { 633 return sig, err 634 } 635 sig.Data, err = ecSign(ecKey, hash) 636 return sig, err 637 case KeyTypeBls12_381: 638 // TODO 639 return Signature{}, ErrUnknownKeyType 640 default: 641 return Signature{}, ErrUnknownKeyType 642 } 643 } 644 645 // ParseEncryptedPrivateKey attempts to parse and optionally decrypt a 646 // Tezos private key. When an encrypted key is detected, fn is called 647 // and expected to return the decoding passphrase. 648 func ParseEncryptedPrivateKey(s string, fn PassphraseFunc) (k PrivateKey, err error) { 649 var ( 650 prefixLen int = 4 651 shouldDecrypt bool 652 ) 653 if IsEncryptedKey(s) { 654 prefixLen = 5 655 shouldDecrypt = true 656 } 657 658 // decode base58, version length differs between encrypted and non-encrypted keys 659 decoded, version, err := base58.CheckDecode(s, prefixLen, nil) 660 if err != nil { 661 if err == base58.ErrChecksum { 662 err = ErrChecksumMismatch 663 return 664 } 665 err = fmt.Errorf("tezos: unknown format for private key %s: %w", s, err) 666 return 667 } 668 669 // decrypt if necessary 670 if shouldDecrypt { 671 decoded, err = decryptPrivateKey(decoded, fn) 672 if err != nil { 673 return 674 } 675 switch { 676 case bytes.Equal(version, ED25519_ENCRYPTED_SEED_ID): 677 version = ED25519_SEED_ID 678 case bytes.Equal(version, SECP256K1_ENCRYPTED_SECRET_KEY_ID): 679 version = SECP256K1_SECRET_KEY_ID 680 case bytes.Equal(version, P256_ENCRYPTED_SECRET_KEY_ID): 681 version = P256_SECRET_KEY_ID 682 case bytes.Equal(version, BLS12_381_ENCRYPTED_SECRET_KEY_ID): 683 version = BLS12_381_SECRET_KEY_ID 684 } 685 } 686 687 // detect type 688 switch { 689 case bytes.Equal(version, ED25519_SEED_ID): 690 if l := len(decoded); l != ed25519.SeedSize { 691 return k, fmt.Errorf("tezos: invalid ed25519 seed length: %d", l) 692 } 693 k.Type = KeyTypeEd25519 694 // convert seed to key 695 decoded = []byte(ed25519.NewKeyFromSeed(decoded)) 696 case bytes.Equal(version, ED25519_SECRET_KEY_ID): 697 k.Type = KeyTypeEd25519 698 case bytes.Equal(version, SECP256K1_SECRET_KEY_ID): 699 k.Type = KeyTypeSecp256k1 700 case bytes.Equal(version, P256_SECRET_KEY_ID): 701 k.Type = KeyTypeP256 702 case bytes.Equal(version, BLS12_381_SECRET_KEY_ID): 703 k.Type = KeyTypeBls12_381 704 default: 705 err = fmt.Errorf("tezos: unknown version %x for private key %s", version, s) 706 return 707 } 708 if l := len(decoded); l != k.Type.SkHashType().Len { 709 return k, fmt.Errorf("tezos: invalid length %d for %s private key data", l, k.Type.SkPrefix()) 710 } 711 k.Data = decoded 712 return 713 } 714 715 func ParsePrivateKey(s string) (PrivateKey, error) { 716 return ParseEncryptedPrivateKey(s, nil) 717 } 718 719 func MustParsePrivateKey(key string) PrivateKey { 720 k, err := ParsePrivateKey(key) 721 if err != nil { 722 panic(err) 723 } 724 return k 725 } 726 727 // Set implements the flags.Value interface for use in command line argument parsing. 728 func (k *PrivateKey) Set(key string) (err error) { 729 *k, err = ParsePrivateKey(key) 730 return 731 }