mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
signer: prevent possibility swap KV-entries in aes_gcm storage, fixes #17635
This commit is contained in:
parent
517c4fc2b0
commit
321de9d86c
2 changed files with 60 additions and 8 deletions
|
|
@ -63,7 +63,7 @@ func (s *AESEncryptedStorage) Put(key, value string) {
|
||||||
log.Warn("Failed to read encrypted storage", "err", err, "file", s.filename)
|
log.Warn("Failed to read encrypted storage", "err", err, "file", s.filename)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ciphertext, iv, err := encrypt(s.key, []byte(value))
|
ciphertext, iv, err := encrypt(s.key, []byte(value), []byte(key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("Failed to encrypt entry", "err", err)
|
log.Warn("Failed to encrypt entry", "err", err)
|
||||||
return
|
return
|
||||||
|
|
@ -90,7 +90,7 @@ func (s *AESEncryptedStorage) Get(key string) string {
|
||||||
log.Warn("Key does not exist", "key", key)
|
log.Warn("Key does not exist", "key", key)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
entry, err := decrypt(s.key, encrypted.Iv, encrypted.CipherText)
|
entry, err := decrypt(s.key, encrypted.Iv, encrypted.CipherText, []byte(key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("Failed to decrypt key", "key", key)
|
log.Warn("Failed to decrypt key", "key", key)
|
||||||
return ""
|
return ""
|
||||||
|
|
@ -129,7 +129,10 @@ func (s *AESEncryptedStorage) writeEncryptedStorage(creds map[string]storedCrede
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encrypt(key []byte, plaintext []byte) ([]byte, []byte, error) {
|
// encrypt encrypts plaingtext with the given key, with additionaldata
|
||||||
|
// The 'additionalData' is used to place the (plaintext) KV-store key into the V,
|
||||||
|
// to prevent the possibility to alter a K, or swap two entries in the KV store with eachother.
|
||||||
|
func encrypt(key []byte, plaintext []byte, additionalData []byte) ([]byte, []byte, error) {
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|
@ -142,11 +145,11 @@ func encrypt(key []byte, plaintext []byte) ([]byte, []byte, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil)
|
ciphertext := aesgcm.Seal(nil, nonce, plaintext, additionalData)
|
||||||
return ciphertext, nonce, nil
|
return ciphertext, nonce, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decrypt(key []byte, nonce []byte, ciphertext []byte) ([]byte, error) {
|
func decrypt(key []byte, nonce []byte, ciphertext []byte, additionalData []byte) ([]byte, error) {
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -155,7 +158,7 @@ func decrypt(key []byte, nonce []byte, ciphertext []byte) ([]byte, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
|
plaintext, err := aesgcm.Open(nil, nonce, ciphertext, additionalData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -33,13 +34,13 @@ func TestEncryption(t *testing.T) {
|
||||||
key := []byte("AES256Key-32Characters1234567890")
|
key := []byte("AES256Key-32Characters1234567890")
|
||||||
plaintext := []byte("exampleplaintext")
|
plaintext := []byte("exampleplaintext")
|
||||||
|
|
||||||
c, iv, err := encrypt(key, plaintext)
|
c, iv, err := encrypt(key, plaintext, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Ciphertext %x, nonce %x\n", c, iv)
|
fmt.Printf("Ciphertext %x, nonce %x\n", c, iv)
|
||||||
|
|
||||||
p, err := decrypt(key, iv, c)
|
p, err := decrypt(key, iv, c, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -113,3 +114,51 @@ func TestEnd2End(t *testing.T) {
|
||||||
t.Errorf("Expected bazonk->foobar, got '%v'", v)
|
t.Errorf("Expected bazonk->foobar, got '%v'", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSwappedKeys(t *testing.T) {
|
||||||
|
// It should not be possible to swap the keys/values, so that
|
||||||
|
// K1:V1, K2:V2 can be swapped into K1:V2, K2:V1
|
||||||
|
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(3), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true))))
|
||||||
|
|
||||||
|
d, err := ioutil.TempDir("", "eth-encrypted-storage-test")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s1 := &AESEncryptedStorage{
|
||||||
|
filename: fmt.Sprintf("%v/vault.json", d),
|
||||||
|
key: []byte("AES256Key-32Characters1234567890"),
|
||||||
|
}
|
||||||
|
s1.Put("k1", "v1")
|
||||||
|
s1.Put("k2", "v2")
|
||||||
|
// Now make a modified copy
|
||||||
|
|
||||||
|
creds := make(map[string]storedCredential)
|
||||||
|
raw, err := ioutil.ReadFile(s1.filename)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err = json.Unmarshal(raw, &creds); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
swap := func() {
|
||||||
|
// Turn it into K1:V2, K2:V2
|
||||||
|
v1, v2 := creds["k1"], creds["k2"]
|
||||||
|
creds["k2"], creds["k1"] = v1, v2
|
||||||
|
raw, err = json.Marshal(creds)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err = ioutil.WriteFile(s1.filename, raw, 0600); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
swap()
|
||||||
|
if v := s1.Get("k1"); v != "" {
|
||||||
|
t.Errorf("swapped value should return empty")
|
||||||
|
}
|
||||||
|
swap()
|
||||||
|
if v := s1.Get("k1"); v != "v1" {
|
||||||
|
t.Errorf("double-swapped value should work fine")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue