From 87badb090ff941c5359b4017705f67976e8c3ca2 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 21:58:02 -0400 Subject: [PATCH 1/4] Revert "Parameterize and lower bcrypt cost" This reverts commit dfc4cdd2d71513e4a9922d679c74f36357c4c862. --- keys/cryptostore/encoder.go | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go index 99241f1b7..31f49c3f7 100644 --- a/keys/cryptostore/encoder.go +++ b/keys/cryptostore/encoder.go @@ -7,20 +7,6 @@ import ( "github.com/tendermint/go-crypto/bcrypt" ) -const ( - // BcryptCost is as parameter to increase the resistance of the - // encoded keys to brute force password guessing - // - // Jae: 14 is good today (2016) - // - // Ethan: loading the key (at each signing) takes a second on my desktop, - // this is hard for laptops and deadly for mobile. You can raise it again, - // but for now, I will make this usable - // - // TODO: review value - BCryptCost = 12 -) - var ( // SecretBox uses the algorithm from NaCL to store secrets securely SecretBox Encoder = secretbox{} @@ -44,7 +30,7 @@ func (e secretbox) Encrypt(privKey crypto.PrivKey, passphrase string) (saltBytes } saltBytes = crypto.CRandBytes(16) - key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), BCryptCost) + key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) if err != nil { return nil, nil, errors.Wrap(err, "Couldn't generate bcrypt key from passphrase.") } @@ -58,7 +44,7 @@ func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) // NOTE: Some keys weren't encrypted with a passphrase and hence we have the conditional if passphrase != "" { var key []byte - key, err = bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), BCryptCost) + key, err = bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) if err != nil { return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") } From 64056182206e90f16833c1a270414cf82c1856d6 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 22:02:44 -0400 Subject: [PATCH 2/4] Revert "Upgrade keys to use bcrypt with salts (#38)" This reverts commit 8e7f0e7701f92206679ad093d013b9b162427631. --- keys/cryptostore/enc_storage.go | 8 +- keys/cryptostore/encoder.go | 60 ++++++-------- keys/cryptostore/encoder_test.go | 22 +++--- keys/cryptostore/generator.go | 1 - keys/cryptostore/holder.go | 18 ++--- keys/cryptostore/holder_test.go | 10 +-- keys/cryptostore/storage_test.go | 2 +- keys/storage/filestorage/main.go | 108 ++++++-------------------- keys/storage/filestorage/main_test.go | 13 ++-- keys/storage/memstorage/main.go | 12 ++- keys/storage/memstorage/main_test.go | 13 ++-- 11 files changed, 94 insertions(+), 173 deletions(-) diff --git a/keys/cryptostore/enc_storage.go b/keys/cryptostore/enc_storage.go index e0c7e59a3..daeb220b5 100644 --- a/keys/cryptostore/enc_storage.go +++ b/keys/cryptostore/enc_storage.go @@ -12,21 +12,21 @@ type encryptedStorage struct { } func (es encryptedStorage) Put(name, pass string, key crypto.PrivKey) error { - saltBytes, encBytes, err := es.coder.Encrypt(key, pass) + secret, err := es.coder.Encrypt(key, pass) if err != nil { return err } ki := info(name, key) - return es.store.Put(name, saltBytes, encBytes, ki) + return es.store.Put(name, secret, ki) } func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.Info, error) { - saltBytes, encBytes, info, err := es.store.Get(name) + secret, info, err := es.store.Get(name) if err != nil { return crypto.PrivKey{}, info, err } - key, err := es.coder.Decrypt(saltBytes, encBytes, pass) + key, err := es.coder.Decrypt(secret, pass) return key, info, err } diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go index 31f49c3f7..31cbc2e54 100644 --- a/keys/cryptostore/encoder.go +++ b/keys/cryptostore/encoder.go @@ -2,9 +2,7 @@ package cryptostore import ( "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/go-crypto/bcrypt" ) var ( @@ -18,55 +16,45 @@ var ( // // This should use a well-designed symetric encryption algorithm type Encoder interface { - Encrypt(privKey crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte, err error) - Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) + Encrypt(key crypto.PrivKey, pass string) ([]byte, error) + Decrypt(data []byte, pass string) (crypto.PrivKey, error) } -type secretbox struct{} +func secret(passphrase string) []byte { + // TODO: Sha256(Bcrypt(passphrase)) + return crypto.Sha256([]byte(passphrase)) +} -func (e secretbox) Encrypt(privKey crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte, err error) { - if passphrase == "" { - return nil, privKey.Bytes(), nil - } +type secretbox struct{} - saltBytes = crypto.CRandBytes(16) - key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) - if err != nil { - return nil, nil, errors.Wrap(err, "Couldn't generate bcrypt key from passphrase.") +func (e secretbox) Encrypt(key crypto.PrivKey, pass string) ([]byte, error) { + if pass == "" { + return key.Bytes(), nil } - key = crypto.Sha256(key) // Get 32 bytes - privKeyBytes := privKey.Bytes() - return saltBytes, crypto.EncryptSymmetric(privKeyBytes, key), nil + s := secret(pass) + cipher := crypto.EncryptSymmetric(key.Bytes(), s) + return cipher, nil } -func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) { - privKeyBytes := encBytes - // NOTE: Some keys weren't encrypted with a passphrase and hence we have the conditional - if passphrase != "" { - var key []byte - key, err = bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) +func (e secretbox) Decrypt(data []byte, pass string) (key crypto.PrivKey, err error) { + private := data + if pass != "" { + s := secret(pass) + private, err = crypto.DecryptSymmetric(data, s) if err != nil { return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") } - key = crypto.Sha256(key) // Get 32 bytes - privKeyBytes, err = crypto.DecryptSymmetric(encBytes, key) - if err != nil { - return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") - } - } - privKey, err = crypto.PrivKeyFromBytes(privKeyBytes) - if err != nil { - return crypto.PrivKey{}, errors.Wrap(err, "Private Key") } - return privKey, nil + key, err = crypto.PrivKeyFromBytes(private) + return key, errors.Wrap(err, "Invalid Passphrase") } type noop struct{} -func (n noop) Encrypt(key crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte, err error) { - return []byte{}, key.Bytes(), nil +func (n noop) Encrypt(key crypto.PrivKey, pass string) ([]byte, error) { + return key.Bytes(), nil } -func (n noop) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) { - return crypto.PrivKeyFromBytes(encBytes) +func (n noop) Decrypt(data []byte, pass string) (crypto.PrivKey, error) { + return crypto.PrivKeyFromBytes(data) } diff --git a/keys/cryptostore/encoder_test.go b/keys/cryptostore/encoder_test.go index 614286a19..9a0757b73 100644 --- a/keys/cryptostore/encoder_test.go +++ b/keys/cryptostore/encoder_test.go @@ -20,22 +20,22 @@ func TestNoopEncoder(t *testing.T) { key2, err := cryptostore.GenSecp256k1.Generate(cmn.RandBytes(16)) require.NoError(err) - _, b, err := noop.Encrypt(key, "encode") + b, err := noop.Encrypt(key, "encode") require.Nil(err) assert.NotEmpty(b) - _, b2, err := noop.Encrypt(key2, "encode") + b2, err := noop.Encrypt(key2, "encode") require.Nil(err) assert.NotEmpty(b2) assert.NotEqual(b, b2) // note the decode with a different password works - not secure! - pk, err := noop.Decrypt(nil, b, "decode") + pk, err := noop.Decrypt(b, "decode") require.Nil(err) require.NotNil(pk) assert.Equal(key, pk) - pk2, err := noop.Decrypt(nil, b2, "kggugougp") + pk2, err := noop.Decrypt(b2, "kggugougp") require.Nil(err) require.NotNil(pk2) assert.Equal(key2, pk2) @@ -49,17 +49,17 @@ func TestSecretBox(t *testing.T) { require.NoError(err) pass := "some-special-secret" - s, b, err := enc.Encrypt(key, pass) + b, err := enc.Encrypt(key, pass) require.Nil(err) assert.NotEmpty(b) // decoding with a different pass is an error - pk, err := enc.Decrypt(s, b, "decode") + pk, err := enc.Decrypt(b, "decode") require.NotNil(err) require.True(pk.Empty()) // but decoding with the same passphrase gets us our key - pk, err = enc.Decrypt(s, b, pass) + pk, err = enc.Decrypt(b, pass) require.Nil(err) assert.Equal(key, pk) } @@ -84,11 +84,11 @@ func TestSecretBoxNoPass(t *testing.T) { } for i, tc := range cases { - s, b, err := enc.Encrypt(key, tc.encode) + b, err := enc.Encrypt(key, tc.encode) require.Nil(err, "%d: %+v", i, err) assert.NotEmpty(b, "%d", i) - pk, err := enc.Decrypt(s, b, tc.decode) + pk, err := enc.Decrypt(b, tc.decode) if tc.valid { require.Nil(err, "%d: %+v", i, err) assert.Equal(key, pk, "%d", i) @@ -99,7 +99,7 @@ func TestSecretBoxNoPass(t *testing.T) { // now let's make sure raw bytes also work... b := key.Bytes() - pk, rerr := enc.Decrypt(nil, b, "") - require.NoError(rerr) + pk, err := enc.Decrypt(b, "") + require.Nil(err, "%+v", err) assert.Equal(key, pk) } diff --git a/keys/cryptostore/generator.go b/keys/cryptostore/generator.go index 65cc8e58b..81277eda9 100644 --- a/keys/cryptostore/generator.go +++ b/keys/cryptostore/generator.go @@ -2,7 +2,6 @@ package cryptostore import ( "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-crypto/nano" ) diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index 923190c1b..7e89dda38 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -95,7 +95,7 @@ func (s Manager) List() (keys.Infos, error) { // Get returns the public information about one key func (s Manager) Get(name string) (keys.Info, error) { - _, _, info, err := s.es.store.Get(name) + _, info, err := s.es.store.Get(name) return info, err } @@ -119,23 +119,21 @@ func (s Manager) Sign(name, passphrase string, tx keys.Signable) error { // // This is designed to copy from one device to another, or provide backups // during version updates. -// TODO: How to handle Export with salt? -func (s Manager) Export(name, oldpass, transferpass string) (salt, data []byte, err error) { +func (s Manager) Export(name, oldpass, transferpass string) ([]byte, error) { key, _, err := s.es.Get(name, oldpass) if err != nil { - return nil, nil, err + return nil, err } - salt, data, err = s.es.coder.Encrypt(key, transferpass) - return salt, data, err + res, err := s.es.coder.Encrypt(key, transferpass) + return res, err } // Import accepts bytes generated by Export along with the same transferpass -// If they are valid, it stores the key under the given name with the +// If they are valid, it stores the password under the given name with the // new passphrase. -// TODO: How to handle Import with salt? -func (s Manager) Import(name, newpass, transferpass string, salt, data []byte) error { - key, err := s.es.coder.Decrypt(salt, data, transferpass) +func (s Manager) Import(name, newpass, transferpass string, data []byte) error { + key, err := s.es.coder.Decrypt(data, transferpass) if err != nil { return err } diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 3709cc55d..a9056f0de 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -232,7 +232,7 @@ func TestImportUnencrypted(t *testing.T) { pass := "top-secret" // import raw bytes - err = cstore.Import(name, pass, "", nil, key.Bytes()) + err = cstore.Import(name, pass, "", key.Bytes()) require.Nil(err, "%+v", err) // make sure the address matches @@ -273,15 +273,15 @@ func TestAdvancedKeyManagement(t *testing.T) { assertPassword(assert, cstore, n1, p2, p1) // exporting requires the proper name and passphrase - _, _, err = cstore.Export(n2, p2, pt) + _, err = cstore.Export(n2, p2, pt) assert.NotNil(err) - _, _, err = cstore.Export(n1, p1, pt) + _, err = cstore.Export(n1, p1, pt) assert.NotNil(err) - salt, exported, err := cstore.Export(n1, p2, pt) + exported, err := cstore.Export(n1, p2, pt) require.Nil(err, "%+v", err) // import fails on bad transfer pass - err = cstore.Import(n2, p3, p2, salt, exported) + err = cstore.Import(n2, p3, p2, exported) assert.NotNil(err) } diff --git a/keys/cryptostore/storage_test.go b/keys/cryptostore/storage_test.go index 23931c294..6d475fdc9 100644 --- a/keys/cryptostore/storage_test.go +++ b/keys/cryptostore/storage_test.go @@ -5,9 +5,9 @@ import ( "github.com/stretchr/testify/assert" + crypto "github.com/tendermint/go-crypto" cmn "github.com/tendermint/tmlibs/common" - crypto "github.com/tendermint/go-crypto" keys "github.com/tendermint/go-crypto/keys" ) diff --git a/keys/storage/filestorage/main.go b/keys/storage/filestorage/main.go index 2bd4dcc1f..1f9702995 100644 --- a/keys/storage/filestorage/main.go +++ b/keys/storage/filestorage/main.go @@ -6,7 +6,6 @@ like standard ssh key storage. package filestorage import ( - "encoding/hex" "fmt" "io/ioutil" "os" @@ -14,13 +13,11 @@ import ( "strings" "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" keys "github.com/tendermint/go-crypto/keys" ) const ( - // BlockType is the type of block. BlockType = "Tendermint Light Client" // PrivExt is the extension for private keys. @@ -33,7 +30,6 @@ const ( dirPerm = os.FileMode(0700) ) -// FileStore is a file-based key storage with tight permissions. type FileStore struct { keyDir string } @@ -44,11 +40,9 @@ type FileStore struct { // be created if it doesn't exist already. func New(dir string) FileStore { err := os.MkdirAll(dir, dirPerm) - if err != nil { panic(err) } - return FileStore{dir} } @@ -57,7 +51,7 @@ var _ keys.Storage = FileStore{} // Put creates two files, one with the public info as json, the other // with the (encoded) private key as gpg ascii-armor style -func (s FileStore) Put(name string, salt, key []byte, info keys.Info) error { +func (s FileStore) Put(name string, key []byte, info keys.Info) error { pub, priv := s.nameToPaths(name) // write public info @@ -67,22 +61,22 @@ func (s FileStore) Put(name string, salt, key []byte, info keys.Info) error { } // write private info - return write(priv, name, salt, key) + return write(priv, name, key) } // Get loads the info and (encoded) private key from the directory // It uses `name` to generate the filename, and returns an error if the // files don't exist or are in the incorrect format -func (s FileStore) Get(name string) (salt []byte, key []byte, info keys.Info, err error) { +func (s FileStore) Get(name string) ([]byte, keys.Info, error) { pub, priv := s.nameToPaths(name) - info, err = readInfo(pub) + info, err := readInfo(pub) if err != nil { - return nil, nil, info, err + return nil, info, err } - salt, key, _, err = read(priv) - return salt, key, info.Format(), err + key, _, err := read(priv) + return key, info.Format(), err } // List parses the key directory for public info and returns a list of @@ -121,117 +115,63 @@ func (s FileStore) List() (keys.Infos, error) { func (s FileStore) Delete(name string) error { pub, priv := s.nameToPaths(name) err := os.Remove(priv) - if err != nil { return errors.Wrap(err, "Deleting Private Key") } - err = os.Remove(pub) - return errors.Wrap(err, "Deleting Public Key") } func (s FileStore) nameToPaths(name string) (pub, priv string) { privName := fmt.Sprintf("%s.%s", name, PrivExt) pubName := fmt.Sprintf("%s.%s", name, PubExt) - return path.Join(s.keyDir, pubName), path.Join(s.keyDir, privName) } -func readInfo(path string) (info keys.Info, err error) { - f, err := os.Open(path) - if err != nil { - return info, errors.Wrap(err, "Reading data") - } - defer f.Close() - - d, err := ioutil.ReadAll(f) - if err != nil { - return info, errors.Wrap(err, "Reading data") - } +func writeInfo(path string, info keys.Info) error { + return write(path, info.Name, info.PubKey.Bytes()) +} - block, headers, key, err := crypto.DecodeArmor(string(d)) +func readInfo(path string) (info keys.Info, err error) { + var data []byte + data, info.Name, err = read(path) if err != nil { - return info, errors.Wrap(err, "Invalid Armor") + return } - - if block != BlockType { - return info, errors.Errorf("Unknown key type: %s", block) - } - - pk, _ := crypto.PubKeyFromBytes(key) - info.Name = headers["name"] + pk, err := crypto.PubKeyFromBytes(data) info.PubKey = pk - - return info, nil + return } -func read(path string) (salt, key []byte, name string, err error) { +func read(path string) ([]byte, string, error) { f, err := os.Open(path) if err != nil { - return nil, nil, "", errors.Wrap(err, "Reading data") + return nil, "", errors.Wrap(err, "Reading data") } defer f.Close() d, err := ioutil.ReadAll(f) if err != nil { - return nil, nil, "", errors.Wrap(err, "Reading data") + return nil, "", errors.Wrap(err, "Reading data") } - block, headers, key, err := crypto.DecodeArmor(string(d)) if err != nil { - return nil, nil, "", errors.Wrap(err, "Invalid Armor") + return nil, "", errors.Wrap(err, "Invalid Armor") } - if block != BlockType { - return nil, nil, "", errors.Errorf("Unknown key type: %s", block) - } - - if headers["kdf"] != "bcrypt" { - return nil, nil, "", errors.Errorf("Unrecognized KDF type: %v", headers["kdf"]) + return nil, "", errors.Errorf("Unknown key type: %s", block) } - - if headers["salt"] == "" { - return nil, nil, "", errors.Errorf("Missing salt bytes") - } - - salt, err = hex.DecodeString(headers["salt"]) - if err != nil { - return nil, nil, "", errors.Errorf("Error decoding salt: %v", err.Error()) - } - - return salt, key, headers["name"], nil + return key, headers["name"], nil } -func writeInfo(path string, info keys.Info) error { +func write(path, name string, key []byte) error { f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, keyPerm) if err != nil { return errors.Wrap(err, "Writing data") } defer f.Close() - - headers := map[string]string{"name": info.Name} - text := crypto.EncodeArmor(BlockType, headers, info.PubKey.Bytes()) - _, err = f.WriteString(text) - - return errors.Wrap(err, "Writing data") -} - -func write(path, name string, salt, key []byte) error { - f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, keyPerm) - if err != nil { - return errors.Wrap(err, "Writing data") - } - defer f.Close() - - headers := map[string]string{ - "name": name, - "kdf": "bcrypt", - "salt": fmt.Sprintf("%X", salt), - } - + headers := map[string]string{"name": name} text := crypto.EncodeArmor(BlockType, headers, key) _, err = f.WriteString(text) - return errors.Wrap(err, "Writing data") } diff --git a/keys/storage/filestorage/main_test.go b/keys/storage/filestorage/main_test.go index bed46ab1f..28c950c2c 100644 --- a/keys/storage/filestorage/main_test.go +++ b/keys/storage/filestorage/main_test.go @@ -22,7 +22,6 @@ func TestBasicCRUD(t *testing.T) { name := "bar" key := []byte("secret-key-here") - salt := []byte("salt-here") pubkey := crypto.GenPrivKeyEd25519().PubKey() info := keys.Info{ Name: name, @@ -30,7 +29,7 @@ func TestBasicCRUD(t *testing.T) { } // No data: Get and Delete return nothing - _, _, _, err = store.Get(name) + _, _, err = store.Get(name) assert.NotNil(err) err = store.Delete(name) assert.NotNil(err) @@ -40,14 +39,14 @@ func TestBasicCRUD(t *testing.T) { assert.Empty(l) // Putting the key in the store must work - err = store.Put(name, salt, key, info) + err = store.Put(name, key, info) assert.Nil(err) // But a second time is a failure - err = store.Put(name, salt, key, info) + err = store.Put(name, key, info) assert.NotNil(err) // Now, we can get and list properly - _, k, i, err := store.Get(name) + k, i, err := store.Get(name) require.Nil(err, "%+v", err) assert.Equal(key, k) assert.Equal(info.Name, i.Name) @@ -59,7 +58,7 @@ func TestBasicCRUD(t *testing.T) { assert.Equal(i, l[0]) // querying a non-existent key fails - _, _, _, err = store.Get("badname") + _, _, err = store.Get("badname") assert.NotNil(err) // We can only delete once @@ -69,7 +68,7 @@ func TestBasicCRUD(t *testing.T) { assert.NotNil(err) // and then Get and List don't work - _, _, _, err = store.Get(name) + _, _, err = store.Get(name) assert.NotNil(err) // List returns empty list l, err = store.List() diff --git a/keys/storage/memstorage/main.go b/keys/storage/memstorage/main.go index 516aa40b8..a988fe0ff 100644 --- a/keys/storage/memstorage/main.go +++ b/keys/storage/memstorage/main.go @@ -7,13 +7,11 @@ package memstorage import ( "github.com/pkg/errors" - keys "github.com/tendermint/go-crypto/keys" ) type data struct { info keys.Info - salt []byte key []byte } @@ -29,22 +27,22 @@ var _ keys.Storage = MemStore{} // Put adds the given key, returns an error if it another key // is already stored under this name -func (s MemStore) Put(name string, salt, key []byte, info keys.Info) error { +func (s MemStore) Put(name string, key []byte, info keys.Info) error { if _, ok := s[name]; ok { return errors.Errorf("Key named '%s' already exists", name) } - s[name] = data{info, salt, key} + s[name] = data{info, key} return nil } // Get returns the key stored under the name, or returns an error if not present -func (s MemStore) Get(name string) (salt, key []byte, info keys.Info, err error) { +func (s MemStore) Get(name string) ([]byte, keys.Info, error) { + var err error d, ok := s[name] if !ok { err = errors.Errorf("Key named '%s' doesn't exist", name) } - - return d.salt, d.key, d.info.Format(), err + return d.key, d.info.Format(), err } // List returns the public info of all keys in the MemStore in unsorted order diff --git a/keys/storage/memstorage/main_test.go b/keys/storage/memstorage/main_test.go index 01975df58..feccb387f 100644 --- a/keys/storage/memstorage/main_test.go +++ b/keys/storage/memstorage/main_test.go @@ -14,7 +14,6 @@ func TestBasicCRUD(t *testing.T) { name := "foo" key := []byte("secret-key-here") - salt := []byte("salt-here") pubkey := crypto.GenPrivKeyEd25519().PubKey() info := keys.Info{ Name: name, @@ -22,7 +21,7 @@ func TestBasicCRUD(t *testing.T) { } // No data: Get and Delete return nothing - _, _, _, err := store.Get(name) + _, _, err := store.Get(name) assert.NotNil(err) err = store.Delete(name) assert.NotNil(err) @@ -32,14 +31,14 @@ func TestBasicCRUD(t *testing.T) { assert.Empty(l) // Putting the key in the store must work - err = store.Put(name, salt, key, info) + err = store.Put(name, key, info) assert.Nil(err) // But a second time is a failure - err = store.Put(name, salt, key, info) + err = store.Put(name, key, info) assert.NotNil(err) // Now, we can get and list properly - _, k, i, err := store.Get(name) + k, i, err := store.Get(name) assert.Nil(err) assert.Equal(key, k) assert.Equal(info.Name, i.Name) @@ -51,7 +50,7 @@ func TestBasicCRUD(t *testing.T) { assert.Equal(i, l[0]) // querying a non-existent key fails - _, _, _, err = store.Get("badname") + _, _, err = store.Get("badname") assert.NotNil(err) // We can only delete once @@ -61,7 +60,7 @@ func TestBasicCRUD(t *testing.T) { assert.NotNil(err) // and then Get and List don't work - _, _, _, err = store.Get(name) + _, _, err = store.Get(name) assert.NotNil(err) // List returns empty list l, err = store.List() From 377d3c7e1122a882a760d005aca8be498ba628aa Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 22:04:22 -0400 Subject: [PATCH 3/4] fix from revert --- keys/types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keys/types.go b/keys/types.go index 008a6f7ae..b3d3a374a 100644 --- a/keys/types.go +++ b/keys/types.go @@ -12,8 +12,8 @@ import ( // Storage has many implementation, based on security and sharing requirements // like disk-backed, mem-backed, vault, db, etc. type Storage interface { - Put(name string, salt []byte, key []byte, info Info) error - Get(name string) (salt []byte, key []byte, info Info, err error) + Put(name string, key []byte, info Info) error + Get(name string) (key []byte, info Info, err error) List() (Infos, error) Delete(name string) error } From d2b1a7096e72bbac6ef0256d7e92edd3c00f61b7 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 22:05:44 -0400 Subject: [PATCH 4/4] changelog --- CHANGELOG.md | 10 ++++++++++ version.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64dc9998b..af0539300 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.4.1 (October 27, 2017) + +This release removes support for bcrypt as it was merged too soon without an upgrade plan +for existing keys. + +REVERTS THE FOLLOWING COMMITS: + +- Parameterize and lower bcrypt cost - dfc4cdd2d71513e4a9922d679c74f36357c4c862 +- Upgrade keys to use bcrypt with salts (#38) - 8e7f0e7701f92206679ad093d013b9b162427631 + ## 0.4.0 (October 27, 2017) BREAKING CHANGES: diff --git a/version.go b/version.go index 585d7e0d7..c39dd627c 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.4.0" +const Version = "0.4.1"