You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.5 KiB

  1. package cryptostore
  2. import keys "github.com/tendermint/go-crypto/keys"
  3. // Manager combines encyption and storage implementation to provide
  4. // a full-featured key manager
  5. type Manager struct {
  6. es encryptedStorage
  7. }
  8. func New(coder Encoder, store keys.Storage) Manager {
  9. return Manager{
  10. es: encryptedStorage{
  11. coder: coder,
  12. store: store,
  13. },
  14. }
  15. }
  16. // exists just to make sure we fulfill the Signer interface
  17. func (s Manager) assertSigner() keys.Signer {
  18. return s
  19. }
  20. // exists just to make sure we fulfill the Manager interface
  21. func (s Manager) assertKeyManager() keys.Manager {
  22. return s
  23. }
  24. // Create adds a new key to the storage engine, returning error if
  25. // another key already stored under this name
  26. //
  27. // algo must be a supported go-crypto algorithm:
  28. //
  29. func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error) {
  30. gen, err := getGenerator(algo)
  31. if err != nil {
  32. return keys.Info{}, "", err
  33. }
  34. key := gen.Generate()
  35. err = s.es.Put(name, passphrase, key)
  36. // TODO
  37. return info(name, key), "", err
  38. }
  39. func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error) {
  40. // TODO
  41. return keys.Info{}, nil
  42. }
  43. // List loads the keys from the storage and enforces alphabetical order
  44. func (s Manager) List() (keys.Infos, error) {
  45. res, err := s.es.List()
  46. res.Sort()
  47. return res, err
  48. }
  49. // Get returns the public information about one key
  50. func (s Manager) Get(name string) (keys.Info, error) {
  51. _, info, err := s.es.store.Get(name)
  52. return info, err
  53. }
  54. // Sign will modify the Signable in order to attach a valid signature with
  55. // this public key
  56. //
  57. // If no key for this name, or the passphrase doesn't match, returns an error
  58. func (s Manager) Sign(name, passphrase string, tx keys.Signable) error {
  59. key, _, err := s.es.Get(name, passphrase)
  60. if err != nil {
  61. return err
  62. }
  63. sig := key.Sign(tx.SignBytes())
  64. pubkey := key.PubKey()
  65. return tx.Sign(pubkey, sig)
  66. }
  67. // Export decodes the private key with the current password, encodes
  68. // it with a secure one-time password and generates a sequence that can be
  69. // Imported by another Manager
  70. //
  71. // This is designed to copy from one device to another, or provide backups
  72. // during version updates.
  73. func (s Manager) Export(name, oldpass, transferpass string) ([]byte, error) {
  74. key, _, err := s.es.Get(name, oldpass)
  75. if err != nil {
  76. return nil, err
  77. }
  78. res, err := s.es.coder.Encrypt(key, transferpass)
  79. return res, err
  80. }
  81. // Import accepts bytes generated by Export along with the same transferpass
  82. // If they are valid, it stores the password under the given name with the
  83. // new passphrase.
  84. func (s Manager) Import(name, newpass, transferpass string, data []byte) error {
  85. key, err := s.es.coder.Decrypt(data, transferpass)
  86. if err != nil {
  87. return err
  88. }
  89. return s.es.Put(name, newpass, key)
  90. }
  91. // Delete removes key forever, but we must present the
  92. // proper passphrase before deleting it (for security)
  93. func (s Manager) Delete(name, passphrase string) error {
  94. // verify we have the proper password before deleting
  95. _, _, err := s.es.Get(name, passphrase)
  96. if err != nil {
  97. return err
  98. }
  99. return s.es.Delete(name)
  100. }
  101. // Update changes the passphrase with which a already stored key is encoded.
  102. //
  103. // oldpass must be the current passphrase used for encoding, newpass will be
  104. // the only valid passphrase from this time forward
  105. func (s Manager) Update(name, oldpass, newpass string) error {
  106. key, _, err := s.es.Get(name, oldpass)
  107. if err != nil {
  108. return err
  109. }
  110. // we must delete first, as Putting over an existing name returns an error
  111. s.Delete(name, oldpass)
  112. return s.es.Put(name, newpass, key)
  113. }