2019-01-14 20:09:25 +00:00
|
|
|
package storage
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/rand"
|
2019-01-29 20:56:59 +00:00
|
|
|
"errors"
|
2019-01-14 20:09:25 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
2019-01-29 20:56:59 +00:00
|
|
|
"golang.org/x/crypto/nacl/secretbox"
|
2019-01-14 20:09:25 +00:00
|
|
|
"golang.org/x/crypto/pbkdf2"
|
|
|
|
"golang.org/x/crypto/sha3"
|
|
|
|
"io"
|
2019-01-29 20:56:59 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"path"
|
2019-01-14 20:09:25 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// createKey derives a key from a password
|
|
|
|
func createKey(password string) ([32]byte, [128]byte, error) {
|
|
|
|
var salt [128]byte
|
|
|
|
if _, err := io.ReadFull(rand.Reader, salt[:]); err != nil {
|
|
|
|
log.Errorf("Cannot read from random: %v\n", err)
|
|
|
|
return [32]byte{}, salt, err
|
|
|
|
}
|
|
|
|
dk := pbkdf2.Key([]byte(password), salt[:], 4096, 32, sha3.New512)
|
|
|
|
|
|
|
|
var dkr [32]byte
|
|
|
|
copy(dkr[:], dk)
|
|
|
|
return dkr, salt, nil
|
|
|
|
}
|
2019-01-29 20:56:59 +00:00
|
|
|
|
|
|
|
//encryptFileData encrypts the cwtchPeer via the specified key.
|
|
|
|
func encryptFileData(data []byte, key [32]byte) ([]byte, error) {
|
|
|
|
var nonce [24]byte
|
|
|
|
|
|
|
|
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
|
|
|
|
log.Errorf("Cannot read from random: %v\n", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
encrypted := secretbox.Seal(nonce[:], data, &nonce, &key)
|
|
|
|
return encrypted, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
//decryptFile decrypts the passed ciphertext into a cwtchPeer via the specified key.
|
|
|
|
func decryptFile(ciphertext []byte, key [32]byte) ([]byte, error) {
|
|
|
|
var decryptNonce [24]byte
|
|
|
|
copy(decryptNonce[:], ciphertext[:24])
|
|
|
|
decrypted, ok := secretbox.Open(nil, ciphertext[24:], &decryptNonce, &key)
|
|
|
|
if ok {
|
|
|
|
return decrypted, nil
|
|
|
|
}
|
|
|
|
return nil, errors.New("Failed to decrypt")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load instantiates a cwtchPeer from the file store
|
|
|
|
func readEncryptedFile(directory, filename, password string) ([]byte, error) {
|
|
|
|
encryptedbytes, err := ioutil.ReadFile(path.Join(directory, filename))
|
2019-02-03 01:18:33 +00:00
|
|
|
if err == nil && len(encryptedbytes) > 128 {
|
2019-01-29 20:56:59 +00:00
|
|
|
var dkr [32]byte
|
|
|
|
//Separate the salt from the encrypted bytes, then generate the derived key
|
|
|
|
salt, encryptedbytes := encryptedbytes[0:128], encryptedbytes[128:]
|
|
|
|
dk := pbkdf2.Key([]byte(password), salt, 4096, 32, sha3.New512)
|
|
|
|
copy(dkr[:], dk)
|
|
|
|
|
|
|
|
data, err := decryptFile(encryptedbytes, dkr)
|
|
|
|
if err == nil {
|
|
|
|
return data, nil
|
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|