From a93b71c576a2aa265fda9f4d4da620d32342d308 Mon Sep 17 00:00:00 2001 From: Florian Lenz Date: Tue, 17 Apr 2018 15:19:39 +0200 Subject: [PATCH 1/4] [key_store] added GetMnemonic() --- keyStore/keyStore.go | 5 +++++ keyStore/keyStore_test.go | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/keyStore/keyStore.go b/keyStore/keyStore.go index 5d554eb..4dfc696 100644 --- a/keyStore/keyStore.go +++ b/keyStore/keyStore.go @@ -87,6 +87,11 @@ func (ks KeyStore) validate() error { return nil } +//Get mnemonic +func (ks KeyStore) GetMnemonic() string { + return ks.mnemonic +} + //Marshal key store func (ks KeyStore) Marshal() ([]byte, error) { diff --git a/keyStore/keyStore_test.go b/keyStore/keyStore_test.go index 4e0d99d..de0206e 100644 --- a/keyStore/keyStore_test.go +++ b/keyStore/keyStore_test.go @@ -138,3 +138,13 @@ func TestNewKeyStoreFactory(t *testing.T) { require.Equal(t, ks.version, uint8(1)) } + +func TestGetMnemonic(t *testing.T) { + + ks := KeyStore{ + mnemonic: "abandon amount liar amount expire adjust cage candy arch gather drum buyer", + } + + require.Equal(t, "abandon amount liar amount expire adjust cage candy arch gather drum buyer", ks.GetMnemonic()) + +} From 5177422427bfaea3b8ae23e7251261ed463e596d Mon Sep 17 00:00:00 2001 From: Florian Lenz Date: Tue, 17 Apr 2018 18:00:41 +0200 Subject: [PATCH 2/4] [key_manager] added open with mnemonic --- keyManager/keyManager.go | 74 +++++++++++++++++++++++++++++------ keyManager/keyManager_test.go | 39 +++++++++++++++++- panthalassa.go | 2 +- 3 files changed, 102 insertions(+), 13 deletions(-) diff --git a/keyManager/keyManager.go b/keyManager/keyManager.go index 574c25b..47e2ad2 100644 --- a/keyManager/keyManager.go +++ b/keyManager/keyManager.go @@ -1,6 +1,7 @@ package keyManager import ( + "encoding/json" "errors" crypto "github.com/Bit-Nation/panthalassa/crypto" ks "github.com/Bit-Nation/panthalassa/keyStore" @@ -8,32 +9,64 @@ import ( type KeyManager struct { keyStore *ks.KeyStore + account accountKeyStore } -//Open an encrypted key store file -func Open(encryptedKeyStore, pw string) (*KeyManager, error) { +type accountKeyStore struct { + Password string `json:"password"` + EncryptedKeyStore string `json:"encrypted_key_store"` + Version uint8 `json:"version"` +} + +//Open encrypted keystore with password +func OpenWithPassword(encryptedAccount, pw string) (*KeyManager, error) { + + //unmarshal encrypted account + var acc accountKeyStore + if err := json.Unmarshal([]byte(encryptedAccount), &acc); err != nil { + return &KeyManager{}, err + } //Decrypt key store - jsonKeyStore, err := crypto.DecryptScryptCipherText(pw, encryptedKeyStore) + jsonKeyStore, err := crypto.DecryptScryptCipherText(pw, acc.EncryptedKeyStore) if err != nil { - return &KeyManager{}, nil + return &KeyManager{}, err } - //transform json key store string to KeyStore + //unmarshal key store keyStore, err := ks.FromJson(jsonKeyStore) - if err != nil { - return &KeyManager{}, nil + return &KeyManager{}, err } - // return &KeyManager{ keyStore: keyStore, + account: acc, }, nil } -//Export the key store +//Open account with mnemonic. +//This should only be used as a backup +func OpenWithMnemonic(account, mnemonic string) (*KeyManager, error) { + + //unmarshal encrypted account + var acc accountKeyStore + if err := json.Unmarshal([]byte(account), &acc); err != nil { + return &KeyManager{}, err + } + + //decrypt password with mnemonic + pw, err := crypto.DecryptScryptCipherText(mnemonic, acc.Password) + if err != nil { + return &KeyManager{}, err + } + + return OpenWithPassword(account, pw) + +} + +//Export the account func (km KeyManager) Export(pw, pwConfirm string) (string, error) { //Exit if password's are not equal @@ -41,11 +74,30 @@ func (km KeyManager) Export(pw, pwConfirm string) (string, error) { return "", errors.New("password miss match") } - keyStoreJson, err := km.keyStore.Marshal() + //Marshal the keystore + keyStore, err := km.keyStore.Marshal() if err != nil { return "", err } - return crypto.NewScryptCipherText(pw, string(keyStoreJson)) + + //encrypt key store with password + encryptedKeyStore, err := crypto.NewScryptCipherText(pw, string(keyStore)) + if err != nil { + return "", err + } + + //encrypt password with mnemonic + encryptedPassword, err := crypto.NewScryptCipherText(km.keyStore.GetMnemonic(), pw) + + //Marshal account + acc, err := json.Marshal(accountKeyStore{ + Password: encryptedPassword, + EncryptedKeyStore: encryptedKeyStore, + Version: 1, + }) + + return string(acc), err + } //Get ethereum private key diff --git a/keyManager/keyManager_test.go b/keyManager/keyManager_test.go index effe87a..5a905ec 100644 --- a/keyManager/keyManager_test.go +++ b/keyManager/keyManager_test.go @@ -6,6 +6,17 @@ import ( "testing" ) +//Test the Create from function +func TestCreateFromKeyStore(t *testing.T) { + //create keyStore + ks, err := keyStore.NewKeyStoreFactory() + require.Nil(t, err) + + km := CreateFromKeyStore(ks) + + require.Equal(t, km.keyStore, ks) +} + func TestExportFunction(t *testing.T) { //create key storage @@ -22,11 +33,37 @@ func TestExportFunction(t *testing.T) { require.Nil(t, err) //Decrypt the exported encrypted key storage - km, err = Open(cipherText, "my_password") + km, err = OpenWithPassword(cipherText, "my_password") + require.Nil(t, err) + + jsonKs, err := km.keyStore.Marshal() + require.Nil(t, err) + + require.Equal(t, jsonKeyStore, string(jsonKs)) +} + +func TestOpenWithMnemonic(t *testing.T) { + + //create key storage + jsonKeyStore := `{"mnemonic":"abandon amount liar amount expire adjust cage candy arch gather drum buyer","keys":{"eth_private_key":"dedbc9eb2b7eea18727f4b2e2d440b93e597cb283f00a3245943481785944d75"},"version":1}` + ks, err := keyStore.FromJson(jsonKeyStore) + require.Nil(t, err) + + //create key manager + km := CreateFromKeyStore(ks) + + //Export the key storage via the key manager + //The export should be encrypted + cipherText, err := km.Export("my_password", "my_password") + require.Nil(t, err) + + //Decrypt the exported encrypted key storage + km, err = OpenWithMnemonic(cipherText, "abandon amount liar amount expire adjust cage candy arch gather drum buyer") require.Nil(t, err) jsonKs, err := km.keyStore.Marshal() require.Nil(t, err) require.Equal(t, jsonKeyStore, string(jsonKs)) + } diff --git a/panthalassa.go b/panthalassa.go index 8520a7c..7b13f46 100644 --- a/panthalassa.go +++ b/panthalassa.go @@ -23,7 +23,7 @@ func (p *Panthalassa) Stop() error { //Create an new instance of panthalassa func NewPanthalassa(keyStore, pw string) (*Panthalassa, error) { - km, err := keyManager.Open(keyStore, pw) + km, err := keyManager.OpenWithPassword(keyStore, pw) if err != nil { return &Panthalassa{}, nil } From 3386f7e722ec8eff73fefa1123d487b18b1398ed Mon Sep 17 00:00:00 2001 From: Florian Lenz Date: Tue, 17 Apr 2018 18:08:29 +0200 Subject: [PATCH 3/4] [kay_manager] changed variable name --- keyManager/keyManager.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/keyManager/keyManager.go b/keyManager/keyManager.go index 47e2ad2..e636474 100644 --- a/keyManager/keyManager.go +++ b/keyManager/keyManager.go @@ -48,11 +48,11 @@ func OpenWithPassword(encryptedAccount, pw string) (*KeyManager, error) { //Open account with mnemonic. //This should only be used as a backup -func OpenWithMnemonic(account, mnemonic string) (*KeyManager, error) { +func OpenWithMnemonic(encryptedAccount, mnemonic string) (*KeyManager, error) { //unmarshal encrypted account var acc accountKeyStore - if err := json.Unmarshal([]byte(account), &acc); err != nil { + if err := json.Unmarshal([]byte(encryptedAccount), &acc); err != nil { return &KeyManager{}, err } @@ -62,7 +62,7 @@ func OpenWithMnemonic(account, mnemonic string) (*KeyManager, error) { return &KeyManager{}, err } - return OpenWithPassword(account, pw) + return OpenWithPassword(encryptedAccount, pw) } From c95149a2597b17a1f6fb1a8ef9a0de4e8e1f7d4a Mon Sep 17 00:00:00 2001 From: Florian Lenz Date: Tue, 17 Apr 2018 18:41:24 +0200 Subject: [PATCH 4/4] [key_store] added utils to get account key's from mnemonic --- keyStore/keyStore.go | 10 ++++++++-- panthalassa.go | 9 +++++++-- utils.go | 11 +++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/keyStore/keyStore.go b/keyStore/keyStore.go index 4dfc696..bb98133 100644 --- a/keyStore/keyStore.go +++ b/keyStore/keyStore.go @@ -140,7 +140,13 @@ func NewKeyStoreFactory() (*KeyStore, error) { return &KeyStore{}, err } - k, err := bip32.NewMasterKey(bip39.NewSeed(mn, "coins")) + return NewFromMnemonic(mn) +} + +//Create new keyStore from mnemonic +func NewFromMnemonic(mnemonic string) (*KeyStore, error) { + + k, err := bip32.NewMasterKey(bip39.NewSeed(mnemonic, "coins")) if err != nil { return &KeyStore{}, err } @@ -152,7 +158,7 @@ func NewKeyStoreFactory() (*KeyStore, error) { } ks := KeyStore{ - mnemonic: mn, + mnemonic: mnemonic, keys: map[string]string{ "eth_private_key": hex.EncodeToString(ethKey.Key), }, diff --git a/panthalassa.go b/panthalassa.go index 7b13f46..2cdb021 100644 --- a/panthalassa.go +++ b/panthalassa.go @@ -20,10 +20,15 @@ func (p *Panthalassa) Stop() error { return nil } +//Export account with the given password +func (p *Panthalassa) Export(pw, pwConfirm string) (string, error) { + return p.km.Export(pw, pwConfirm) +} + //Create an new instance of panthalassa -func NewPanthalassa(keyStore, pw string) (*Panthalassa, error) { +func NewPanthalassa(encryptedAccount, pw string) (*Panthalassa, error) { - km, err := keyManager.OpenWithPassword(keyStore, pw) + km, err := keyManager.OpenWithPassword(encryptedAccount, pw) if err != nil { return &Panthalassa{}, nil } diff --git a/utils.go b/utils.go index 15560ce..91dc08d 100644 --- a/utils.go +++ b/utils.go @@ -38,3 +38,14 @@ func NewAccountKeys(pw, pwConfirm string) (string, error) { km := keyManager.CreateFromKeyStore(ks) return km.Export(pw, pwConfirm) } + +//Create new account store from mnemonic +//This can e.g. be used in case you need to recover your account +func NewAccountKeysFromMnemonic(mnemonic, pw, pwConfirm string) (string, error) { + ks, err := keyStore.NewFromMnemonic(mnemonic) + if err != nil { + return "", err + } + km := keyManager.CreateFromKeyStore(ks) + return km.Export(pw, pwConfirm) +}