OSDN Git Service

wallet: prevent restore duplicate key (#1561)
authoryahtoo <yahtoo.ma@gmail.com>
Thu, 14 Feb 2019 04:05:12 +0000 (12:05 +0800)
committerPaladz <yzhu101@uottawa.ca>
Thu, 14 Feb 2019 04:05:12 +0000 (12:05 +0800)
* wallet: prevent restore duplicate key

* Fix review bug

blockchain/pseudohsm/image.go
blockchain/pseudohsm/image_test.go [new file with mode: 0644]
blockchain/pseudohsm/pseudohsm.go

index 7a13a72..3053601 100644 (file)
@@ -2,9 +2,14 @@
 package pseudohsm
 
 import (
+       "encoding/hex"
        "encoding/json"
        "io/ioutil"
        "path/filepath"
+
+       log "github.com/sirupsen/logrus"
+
+       "github.com/bytom/crypto/ed25519/chainkd"
 )
 
 // KeyImage is the struct for hold export key data
@@ -38,6 +43,22 @@ func (h *HSM) Restore(image *KeyImage) error {
        defer h.cacheMu.Unlock()
 
        for _, xKey := range image.XKeys {
+               data, err := hex.DecodeString(xKey.XPub)
+               if err != nil {
+                       return ErrXPubFormat
+               }
+
+               var xPub chainkd.XPub
+               copy(xPub[:], data)
+               if h.cache.hasKey(xPub) {
+                       log.WithFields(log.Fields{
+                               "alias": xKey.Alias,
+                               "id":    xKey.ID,
+                               "xPub":  xKey.XPub,
+                       }).Warning("skip restore key due to already existed")
+                       continue
+               }
+
                if ok := h.cache.hasAlias(xKey.Alias); ok {
                        return ErrDuplicateKeyAlias
                }
@@ -52,7 +73,8 @@ func (h *HSM) Restore(image *KeyImage) error {
                if err := writeKeyFile(file, rawKey); err != nil {
                        return err
                }
+
+               h.cache.reload()
        }
-       h.cache.maybeReload()
        return nil
 }
diff --git a/blockchain/pseudohsm/image_test.go b/blockchain/pseudohsm/image_test.go
new file mode 100644 (file)
index 0000000..88dd7d8
--- /dev/null
@@ -0,0 +1,81 @@
+package pseudohsm
+
+import (
+       "encoding/hex"
+       "encoding/json"
+       "io/ioutil"
+       "os"
+       "testing"
+
+       "github.com/bytom/crypto/ed25519/chainkd"
+)
+
+func TestRestore(t *testing.T) {
+       dirPath, err := ioutil.TempDir(".", "")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer os.RemoveAll(dirPath)
+
+       hsm, err := New(dirPath)
+       if err != nil {
+               t.Fatal("create hsm err:", err)
+       }
+
+       testCases := []struct {
+               image    string
+               wantErr  error
+               wantKeys []string
+       }{
+               {
+                       image:    "{\"xkeys\":[{\"alias\":\"test4\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"45650919af7c61d907d8681ae8a3f8d0\"},\"ciphertext\":\"0d073355814763f3c4d0c049668d362a419af56ff193a1e65f1e867babaf3b8c9e91e539918314e7b78532216093f8bc2dd7712af579f7ff2b95ef0ecb8562a0\",\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"d6a5ff1f5ba2d678db428cb2d387a8130f0223c9fe271dfdf02a3edca4608b30\"},\"mac\":\"889920bee3829a8b3aaccb8c6e8aa5f9dda7f986d72efa25c5777c88c1a86c17\"},\"id\":\"868047f4-6613-4abb-902a-4b2a288cd8c7\",\"type\":\"bytom_kd\",\"version\":1,\"xpub\":\"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb6\"}]}",
+                       wantErr:  nil,
+                       wantKeys: []string{"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb6"},
+               },
+               {
+                       image:    "{\"xkeys\":[{\"alias\":\"test4\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"45650919af7c61d907d8681ae8a3f8d0\"},\"ciphertext\":\"0d073355814763f3c4d0c049668d362a419af56ff193a1e65f1e867babaf3b8c9e91e539918314e7b78532216093f8bc2dd7712af579f7ff2b95ef0ecb8562a0\",\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"d6a5ff1f5ba2d678db428cb2d387a8130f0223c9fe271dfdf02a3edca4608b30\"},\"mac\":\"889920bee3829a8b3aaccb8c6e8aa5f9dda7f986d72efa25c5777c88c1a86c17\"},\"id\":\"868047f4-6613-4abb-902a-4b2a288cd8c7\",\"type\":\"bytom_kd\",\"version\":1,\"xpub\":\"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb6\"},{\"alias\":\"test4\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"45650919af7c61d907d8681ae8a3f8d0\"},\"ciphertext\":\"0d073355814763f3c4d0c049668d362a419af56ff193a1e65f1e867babaf3b8c9e91e539918314e7b78532216093f8bc2dd7712af579f7ff2b95ef0ecb8562a0\",\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"d6a5ff1f5ba2d678db428cb2d387a8130f0223c9fe271dfdf02a3edca4608b30\"},\"mac\":\"889920bee3829a8b3aaccb8c6e8aa5f9dda7f986d72efa25c5777c88c1a86c17\"},\"id\":\"868047f4-6613-4abb-902a-4b2a288cd8c7\",\"type\":\"bytom_kd\",\"version\":1,\"xpub\":\"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb6\"}]}",
+                       wantErr:  nil,
+                       wantKeys: []string{"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb6"},
+               },
+               {
+                       image:    "{\"xkeys\":[{\"alias\":\"test4\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"45650919af7c61d907d8681ae8a3f8d0\"},\"ciphertext\":\"0d073355814763f3c4d0c049668d362a419af56ff193a1e65f1e867babaf3b8c9e91e539918314e7b78532216093f8bc2dd7712af579f7ff2b95ef0ecb8562a0\",\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"d6a5ff1f5ba2d678db428cb2d387a8130f0223c9fe271dfdf02a3edca4608b30\"},\"mac\":\"889920bee3829a8b3aaccb8c6e8aa5f9dda7f986d72efa25c5777c88c1a86c17\"},\"id\":\"868047f4-6613-4abb-902a-4b2a288cd8c7\",\"type\":\"bytom_kd\",\"version\":1,\"xpub\":\"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb\"}]}",
+                       wantErr:  ErrXPubFormat,
+                       wantKeys: []string{"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb6"},
+               },
+               {
+                       image:    "{\"xkeys\":[{\"alias\":\"test4\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"45650919af7c61d907d8681ae8a3f8d0\"},\"ciphertext\":\"0d073355814763f3c4d0c049668d362a419af56ff193a1e65f1e867babaf3b8c9e91e539918314e7b78532216093f8bc2dd7712af579f7ff2b95ef0ecb8562a0\",\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"d6a5ff1f5ba2d678db428cb2d387a8130f0223c9fe271dfdf02a3edca4608b30\"},\"mac\":\"889920bee3829a8b3aaccb8c6e8aa5f9dda7f986d72efa25c5777c88c1a86c17\"},\"id\":\"868047f4-6613-4abb-902a-4b2a288cd8c7\",\"type\":\"bytom_kd\",\"version\":1,\"xpub\":\"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb5\"}]}",
+                       wantErr:  ErrDuplicateKeyAlias,
+                       wantKeys: []string{"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb6"},
+               },
+               {
+                       image:    "{\"xkeys\":[{\"alias\":\"test4\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"45650919af7c61d907d8681ae8a3f8d0\"},\"ciphertext\":\"0d073355814763f3c4d0c049668d362a419af56ff193a1e65f1e867babaf3b8c9e91e539918314e7b78532216093f8bc2dd7712af579f7ff2b95ef0ecb8562a0\",\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"d6a5ff1f5ba2d678db428cb2d387a8130f0223c9fe271dfdf02a3edca4608b30\"},\"mac\":\"889920bee3829a8b3aaccb8c6e8aa5f9dda7f986d72efa25c5777c88c1a86c17\"},\"id\":\"868047f4-6613-4abb-902a-4b2a288cd8c7\",\"type\":\"bytom_kd\",\"version\":1,\"xpub\":\"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb6\"},{\"alias\":\"test5\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"45650919af7c61d907d8681ae8a3f8d0\"},\"ciphertext\":\"0d073355814763f3c4d0c049668d362a419af56ff193a1e65f1e867babaf3b8c9e91e539918314e7b78532216093f8bc2dd7712af579f7ff2b95ef0ecb8562a0\",\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"d6a5ff1f5ba2d678db428cb2d387a8130f0223c9fe271dfdf02a3edca4608b30\"},\"mac\":\"889920bee3829a8b3aaccb8c6e8aa5f9dda7f986d72efa25c5777c88c1a86c17\"},\"id\":\"868047f4-6613-4abb-902a-4b2a288cd8c7\",\"type\":\"bytom_kd\",\"version\":1,\"xpub\":\"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb7\"}]}",
+                       wantErr:  nil,
+                       wantKeys: []string{"a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb6", "a57f2ac07c69a71ec2ec7432c573c8b0680f3b6e4bb3c30baaf845b2685840b133dbe260c332640904f0a523421cf911084e98dd18204e88271fbc1c35f18fb7"},
+               },
+       }
+
+       for _, test := range testCases {
+               keyImage := &KeyImage{}
+               if err := json.Unmarshal([]byte(test.image), keyImage); err != nil {
+                       t.Fatal("unmarshal json error:", err)
+               }
+
+               if err := hsm.Restore(keyImage); err != test.wantErr {
+                       t.Errorf("error mismatch: have %v, want %v", err, test.wantErr)
+               }
+
+               if len(hsm.cache.keys()) != len(test.wantKeys) {
+                       t.Errorf("error key num: have %v, want %v", len(hsm.cache.keys()), len(test.wantKeys))
+               }
+
+               for _, key := range test.wantKeys {
+                       var xPub chainkd.XPub
+                       data, _ := hex.DecodeString(key)
+                       copy(xPub[:], data)
+
+                       if !hsm.cache.hasKey(xPub) {
+                               t.Errorf("error restore key: can't find key %v", key)
+                       }
+               }
+       }
+}
index efb050f..5c13844 100644 (file)
@@ -20,6 +20,7 @@ import (
 // pre-define errors for supporting bytom errorFormatter
 var (
        ErrDuplicateKeyAlias = errors.New("duplicate key alias")
+       ErrXPubFormat        = errors.New("xpub format error")
        ErrLoadKey           = errors.New("key not found or wrong password ")
        ErrDecrypt           = errors.New("could not decrypt key with given passphrase")
        ErrMnemonicLength    = errors.New("mnemonic length error")