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.

125 lines
3.4 KiB

  1. package cryptostore
  2. import keys "github.com/tendermint/go-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, 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. return info(name, key), err
  37. }
  38. // List loads the keys from the storage and enforces alphabetical order
  39. func (s Manager) List() (keys.Infos, error) {
  40. res, err := s.es.List()
  41. res.Sort()
  42. return res, err
  43. }
  44. // Get returns the public information about one key
  45. func (s Manager) Get(name string) (keys.Info, error) {
  46. _, info, err := s.es.store.Get(name)
  47. return info, err
  48. }
  49. // Sign will modify the Signable in order to attach a valid signature with
  50. // this public key
  51. //
  52. // If no key for this name, or the passphrase doesn't match, returns an error
  53. func (s Manager) Sign(name, passphrase string, tx keys.Signable) error {
  54. key, _, err := s.es.Get(name, passphrase)
  55. if err != nil {
  56. return err
  57. }
  58. sig := key.Sign(tx.SignBytes())
  59. pubkey := key.PubKey()
  60. return tx.Sign(pubkey, sig)
  61. }
  62. // Export decodes the private key with the current password, encodes
  63. // it with a secure one-time password and generates a sequence that can be
  64. // Imported by another Manager
  65. //
  66. // This is designed to copy from one device to another, or provide backups
  67. // during version updates.
  68. func (s Manager) Export(name, oldpass, transferpass string) ([]byte, error) {
  69. key, _, err := s.es.Get(name, oldpass)
  70. if err != nil {
  71. return nil, err
  72. }
  73. res, err := s.es.coder.Encrypt(key, transferpass)
  74. return res, err
  75. }
  76. // Import accepts bytes generated by Export along with the same transferpass
  77. // If they are valid, it stores the password under the given name with the
  78. // new passphrase.
  79. func (s Manager) Import(name, newpass, transferpass string, data []byte) error {
  80. key, err := s.es.coder.Decrypt(data, transferpass)
  81. if err != nil {
  82. return err
  83. }
  84. return s.es.Put(name, newpass, key)
  85. }
  86. // Delete removes key forever, but we must present the
  87. // proper passphrase before deleting it (for security)
  88. func (s Manager) Delete(name, passphrase string) error {
  89. // verify we have the proper password before deleting
  90. _, _, err := s.es.Get(name, passphrase)
  91. if err != nil {
  92. return err
  93. }
  94. return s.es.Delete(name)
  95. }
  96. // Update changes the passphrase with which a already stored key is encoded.
  97. //
  98. // oldpass must be the current passphrase used for encoding, newpass will be
  99. // the only valid passphrase from this time forward
  100. func (s Manager) Update(name, oldpass, newpass string) error {
  101. key, _, err := s.es.Get(name, oldpass)
  102. if err != nil {
  103. return err
  104. }
  105. // we must delete first, as Putting over an existing name returns an error
  106. s.Delete(name, oldpass)
  107. return s.es.Put(name, newpass, key)
  108. }