identity.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (c)2019 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2023-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. package zerotier
  14. import (
  15. "encoding/hex"
  16. "encoding/json"
  17. "fmt"
  18. "strings"
  19. )
  20. // IdentityTypeC25519 is a classic Curve25519/Ed25519 identity
  21. const IdentityTypeC25519 = 0
  22. // IdentityTypeP384 is an identity containing both NIST P-384 and Curve25519/Ed25519 key types and leveraging both when possible
  23. const IdentityTypeP384 = 1
  24. // Sizes of components of different identity types
  25. const (
  26. IdentityTypeC25519PublicKeySize = 64 // C25519/Ed25519 keys
  27. IdentityTypeC25519PrivateKeySize = 64 // C25519/Ed25519 private keys
  28. IdentityTypeP384PublicKeySize = 209 // C25519/Ed25519, P-384 point-compressed public, P-384 self-signature
  29. IdentityTypeP384PrivateKeySize = 112 // C25519/Ed25519 and P-384 private keys
  30. )
  31. // Identity is precisely what it sounds like: the address and associated keys for a ZeroTier node
  32. type Identity struct {
  33. address Address
  34. idtype int
  35. publicKey []byte
  36. privateKey []byte
  37. }
  38. // NewIdentityFromString generates a new identity from its string representation.
  39. // The private key is imported as well if it is present.
  40. func NewIdentityFromString(s string) (*Identity, error) {
  41. ss := strings.Split(strings.TrimSpace(s), ":")
  42. if len(ss) < 3 {
  43. return nil, ErrInvalidParameter
  44. }
  45. var err error
  46. var id Identity
  47. id.address, err = NewAddressFromString(ss[0])
  48. if err != nil {
  49. return nil, err
  50. }
  51. if ss[1] == "0" {
  52. id.idtype = 0
  53. } else if ss[1] == "1" {
  54. id.idtype = 1
  55. } else {
  56. return nil, ErrUnrecognizedIdentityType
  57. }
  58. switch id.idtype {
  59. case 0:
  60. id.publicKey, err = hex.DecodeString(ss[2])
  61. if err != nil {
  62. return nil, err
  63. }
  64. if len(ss) >= 4 {
  65. id.privateKey, err = hex.DecodeString(ss[3])
  66. if err != nil {
  67. return nil, err
  68. }
  69. }
  70. case 1:
  71. id.publicKey, err = base32StdLowerCase.DecodeString(ss[2])
  72. if err != nil {
  73. return nil, err
  74. }
  75. if len(id.publicKey) != IdentityTypeP384PublicKeySize {
  76. return nil, ErrInvalidKey
  77. }
  78. if len(ss) >= 4 {
  79. id.privateKey, err = base32StdLowerCase.DecodeString(ss[3])
  80. if err != nil {
  81. return nil, err
  82. }
  83. if len(id.privateKey) != IdentityTypeP384PrivateKeySize {
  84. return nil, ErrInvalidKey
  85. }
  86. }
  87. }
  88. return &id, nil
  89. }
  90. // HasPrivate returns true if this identity has its own private portion.
  91. func (id *Identity) HasPrivate() bool { return len(id.privateKey) > 0 }
  92. // PrivateKeyString returns the full identity.secret if the private key is set, or an empty string if no private key is set.
  93. func (id *Identity) PrivateKeyString() string {
  94. switch id.idtype {
  95. case IdentityTypeC25519:
  96. if len(id.publicKey) == IdentityTypeC25519PublicKeySize && len(id.privateKey) == IdentityTypeC25519PrivateKeySize {
  97. return fmt.Sprintf("%.10x:0:%x:%x", uint64(id.address), id.publicKey, id.privateKey)
  98. }
  99. case IdentityTypeP384:
  100. if len(id.publicKey) == IdentityTypeP384PublicKeySize && len(id.privateKey) == IdentityTypeP384PrivateKeySize {
  101. return fmt.Sprintf("%.10x:1:%s:%s", uint64(id.address), base32StdLowerCase.EncodeToString(id.publicKey), base32StdLowerCase.EncodeToString(id.privateKey))
  102. }
  103. }
  104. return ""
  105. }
  106. // PublicKeyString returns the address and public key (identity.public contents).
  107. // An empty string is returned if this identity is invalid or not initialized.
  108. func (id *Identity) String() string {
  109. switch id.idtype {
  110. case IdentityTypeC25519:
  111. if len(id.publicKey) == IdentityTypeC25519PublicKeySize {
  112. return fmt.Sprintf("%.10x:0:%x", uint64(id.address), id.publicKey)
  113. }
  114. case IdentityTypeP384:
  115. if len(id.publicKey) == IdentityTypeP384PublicKeySize {
  116. return fmt.Sprintf("%.10x:1:%s", uint64(id.address), base32StdLowerCase.EncodeToString(id.publicKey))
  117. }
  118. }
  119. return ""
  120. }
  121. // MarshalJSON marshals this Identity in its string format (private key is never included)
  122. func (id *Identity) MarshalJSON() ([]byte, error) {
  123. return []byte("\"" + id.String() + "\""), nil
  124. }
  125. // UnmarshalJSON unmarshals this Identity from a string
  126. func (id *Identity) UnmarshalJSON(j []byte) error {
  127. var s string
  128. err := json.Unmarshal(j, &s)
  129. if err != nil {
  130. return err
  131. }
  132. fmt.Println(s)
  133. nid, err := NewIdentityFromString(s)
  134. if err != nil {
  135. return err
  136. }
  137. *id = *nid
  138. return nil
  139. }