Skip to content
Snippets Groups Projects
Commit 2ee0156a authored by Josh Brooks's avatar Josh Brooks
Browse files

Fix issue in design for mnemonic

parent 18f59545
No related branches found
No related tags found
2 merge requests!23Release,!19Implement mnemonic in client
...@@ -12,17 +12,17 @@ import ( ...@@ -12,17 +12,17 @@ import (
"gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/crypto/fastRNG"
"gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/csprng"
xxMnemonic "gitlab.com/xx_network/crypto/mnemonic" xxMnemonic "gitlab.com/xx_network/crypto/mnemonic"
"golang.org/x/crypto/salsa20" "gitlab.com/xx_network/primitives/utils"
"golang.org/x/crypto/chacha20poly1305"
) )
const ( const mnemonicFile = "/.recovery"
nonceSize = 8
)
// StoreSecretWithMnemonic creates a mnemonic and uses it to encrypt the secret. // StoreSecretWithMnemonic creates a mnemonic and uses it to encrypt the secret.
// This encrypted data saved in storage. // This encrypted data saved in storage.
func (c *Client) StoreSecretWithMnemonic(secret []byte) (string, error) { func StoreSecretWithMnemonic(secret []byte, path string) (string, error) {
rng := c.rng.GetStream() // Use fastRNG for RNG ops (AES fortuna based RNG using system RNG)
rng := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG).GetStream()
// Create a mnemonic // Create a mnemonic
mnemonic, err := xxMnemonic.GenerateMnemonic(rng, 32) mnemonic, err := xxMnemonic.GenerateMnemonic(rng, 32)
...@@ -30,19 +30,21 @@ func (c *Client) StoreSecretWithMnemonic(secret []byte) (string, error) { ...@@ -30,19 +30,21 @@ func (c *Client) StoreSecretWithMnemonic(secret []byte) (string, error) {
return "", errors.Errorf("Failed to generate mnemonic: %v", err) return "", errors.Errorf("Failed to generate mnemonic: %v", err)
} }
decodedMnemonic, err := xxMnemonic.DecodeMnemonic(mnemonic)
if err != nil {
return "", errors.Errorf("Failed to decode mnemonic: %v", err)
}
// Encrypt secret with mnemonic as key // Encrypt secret with mnemonic as key
ciphertext, nonce, err := encryptWithMnemonic(mnemonic, secret, rng) ciphertext, err := encryptWithMnemonic(secret, decodedMnemonic, rng)
if err != nil { if err != nil {
return "", errors.Errorf("Failed to encrypt secret with mnemonic: %v", err) return "", errors.Errorf("Failed to encrypt secret with mnemonic: %v", err)
} }
// Concatenate ciphertext with nonce for storage // Save encrypted secret to file
data := marshalMnemonicInformation(nonce, ciphertext) err = utils.WriteFileDef(path+mnemonicFile, ciphertext)
// Save data to storage
err = c.storage.SaveMnemonicInformation(data)
if err != nil { if err != nil {
return "", errors.Errorf("Failed to store mnemonic information: %v", err) return "", errors.Errorf("Failed to save mnemonic information to file")
} }
return mnemonic, nil return mnemonic, nil
...@@ -50,64 +52,58 @@ func (c *Client) StoreSecretWithMnemonic(secret []byte) (string, error) { ...@@ -50,64 +52,58 @@ func (c *Client) StoreSecretWithMnemonic(secret []byte) (string, error) {
// LoadSecretWithMnemonic loads the encrypted secret from storage and decrypts // LoadSecretWithMnemonic loads the encrypted secret from storage and decrypts
// the secret using the given mnemonic. // the secret using the given mnemonic.
func (c *Client) LoadSecretWithMnemonic(mnemonic string) (secret []byte, err error) { func LoadSecretWithMnemonic(mnemonic, path string) (secret []byte, err error) {
data, err := c.storage.LoadMnemonicInformation() data, err := utils.ReadFile(path + mnemonicFile)
if err != nil { if err != nil {
return nil, errors.Errorf("Failed to load mnemonic information: %v", err) return nil, errors.Errorf("Failed to load mnemonic information: %v", err)
} }
nonce, ciphertext := unmarshalMnemonicInformation(data) decodedMnemonic, err := xxMnemonic.DecodeMnemonic(mnemonic)
if err != nil {
return nil, errors.Errorf("Failed to decode mnemonic: %v", err)
}
secret = decryptWithMnemonic(nonce, ciphertext, mnemonic) secret, err = decryptWithMnemonic(data, decodedMnemonic)
if err != nil {
return nil, errors.Errorf("Failed to decrypt secret: %v", err)
}
return secret, nil return secret, nil
} }
// encryptWithMnemonic is a helper function which encrypts the given secret // encryptWithMnemonic is a helper function which encrypts the given secret
// using the mnemonic as the key. // using the mnemonic as the key.
func encryptWithMnemonic(mnemonic string, secret []byte, func encryptWithMnemonic(data, decodedMnemonic []byte,
rng *fastRNG.Stream) (ciphertext, nonce []byte, err error) { rng csprng.Source) (ciphertext []byte, error error) {
chaCipher, err := chacha20poly1305.NewX(decodedMnemonic[:])
// Place the key into a 32 byte array for salsa 20 if err != nil {
var keyArray [32]byte return nil, errors.Errorf("Failed to initalize encryption algorithm: %v", err)
copy(keyArray[:], mnemonic) }
// Generate the nonce // Generate the nonce
nonce, err = csprng.Generate(nonceSize, rng) nonce := make([]byte, chaCipher.NonceSize())
nonce, err = csprng.Generate(chaCipher.NonceSize(), rng)
if err != nil { if err != nil {
return nil, nil, errors.Errorf("Failed to generate nonce for encryption: %v", err) return nil, errors.Errorf("Failed to generate nonce: %v", err)
} }
// Encrypt the secret ciphertext = chaCipher.Seal(nonce, nonce, data, nil)
ciphertext = make([]byte, len(secret)) return ciphertext, nil
salsa20.XORKeyStream(ciphertext, secret, nonce, &keyArray)
return ciphertext, nonce, nil
} }
// decryptWithMnemonic is a helper function which decrypts the secret // decryptWithMnemonic is a helper function which decrypts the secret
// from storage, using the mnemonic as the key. // from storage, using the mnemonic as the key.
func decryptWithMnemonic(nonce, ciphertext []byte, mnemonic string) (secret []byte) { func decryptWithMnemonic(data, decodedMnemonic []byte) ([]byte, error) {
// Place the key into a 32 byte array for salsa 20 chaCipher, err := chacha20poly1305.NewX(decodedMnemonic[:])
var keyArray [32]byte if err != nil {
copy(keyArray[:], mnemonic) return nil, errors.Errorf("Failed to initalize encryption algorithm: %v", err)
}
// Decrypt the secret
secret = make([]byte, len(ciphertext))
salsa20.XORKeyStream(secret, ciphertext, nonce, &keyArray)
return secret
}
// marshalMnemonicInformation is a helper function which concatenates the nonce
// and ciphertext.
func marshalMnemonicInformation(nonce, ciphertext []byte) []byte {
return append(nonce, ciphertext...)
}
// unmarshalMnemonicInformation is a helper function which separates the nonceLen := chaCipher.NonceSize()
// concatenated data containing the nonce and ciphertext of the mnemonic nonce, ciphertext := data[:nonceLen], data[nonceLen:]
// handling. This is the inverse of marshalMnemonicInformation. plaintext, err := chaCipher.Open(nil, nonce, ciphertext, nil)
func unmarshalMnemonicInformation(data []byte) (nonce, ciphertext []byte) { if err != nil {
return data[:nonceSize], data[nonceSize:] return nil, errors.Wrap(err, "Cannot decrypt with password!")
}
return plaintext, nil
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment