diff --git a/go.mod b/go.mod index 96b2f3a..d2d13fe 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( cwtch.im/tapir v0.1.18 git.openprivacy.ca/openprivacy/connectivity v1.1.2 git.openprivacy.ca/openprivacy/libricochet-go v1.0.13 - git.openprivacy.ca/openprivacy/log v1.0.0 + git.openprivacy.ca/openprivacy/log v1.0.1 github.com/c-bata/go-prompt v0.2.3 github.com/golang/protobuf v1.3.5 github.com/google/go-cmp v0.4.0 // indirect diff --git a/go.sum b/go.sum index 3dd7367..2c539c3 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ git.openprivacy.ca/openprivacy/libricochet-go v1.0.13 h1:Z86uL9K47onznY1wP1P/wWf git.openprivacy.ca/openprivacy/libricochet-go v1.0.13/go.mod h1:ZUuX1SOrgV4K18IEcp0hQJNPKszRr2oGb3UeK2iYe5U= git.openprivacy.ca/openprivacy/log v1.0.0 h1:Rvqm1weUdR4AOnJ79b1upHCc9vC/QF1rhSD2Um7sr1Y= git.openprivacy.ca/openprivacy/log v1.0.0/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw= +git.openprivacy.ca/openprivacy/log v1.0.1 h1:NWV5oBTatvlSzUE6wtB+UQCulgyMOtm4BXGd34evMys= +git.openprivacy.ca/openprivacy/log v1.0.1/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw= github.com/c-bata/go-prompt v0.2.3 h1:jjCS+QhG/sULBhAaBdjb2PlMRVaKXQgn+4yzaauvs2s= github.com/c-bata/go-prompt v0.2.3/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca h1:Q2r7AxHdJwWfLtBZwvW621M3sPqxPc6ITv2j1FGsYpw= diff --git a/storage/v1/file_enc.go b/storage/v1/file_enc.go index a4e1870..38cc063 100644 --- a/storage/v1/file_enc.go +++ b/storage/v1/file_enc.go @@ -12,8 +12,8 @@ import ( "path" ) -// createKeySalt derives a key from a password: returns key, salt, err -func createKeySalt(password string) ([32]byte, [128]byte, error) { +// CreateKeySalt derives a key and salt from a password: returns key, salt, err +func CreateKeySalt(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) @@ -26,7 +26,8 @@ func createKeySalt(password string) ([32]byte, [128]byte, error) { return dkr, salt, nil } -func createKey(password string, salt []byte) [32]byte { +// CreateKey derives a key from a password and salt +func CreateKey(password string, salt []byte) [32]byte { dk := pbkdf2.Key([]byte(password), salt, 4096, 32, sha3.New512) var dkr [32]byte @@ -34,8 +35,8 @@ func createKey(password string, salt []byte) [32]byte { return dkr } -//encryptFileData encrypts the cwtchPeer via the specified key. -func encryptFileData(data []byte, key [32]byte) ([]byte, error) { +//EncryptFileData encrypts the data with the supplied key +func EncryptFileData(data []byte, key [32]byte) ([]byte, error) { var nonce [24]byte if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil { @@ -47,8 +48,8 @@ func encryptFileData(data []byte, key [32]byte) ([]byte, error) { return encrypted, nil } -//decryptFile decrypts the passed ciphertext into a cwtchPeer via the specified key. -func decryptFile(ciphertext []byte, key [32]byte) ([]byte, error) { +//DecryptFile decrypts the passed ciphertext with the supplied 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) @@ -58,11 +59,11 @@ func decryptFile(ciphertext []byte, key [32]byte) ([]byte, error) { return nil, errors.New("Failed to decrypt") } -// load instantiates a cwtchPeer from the file store -func readEncryptedFile(directory, filename string, key [32]byte) ([]byte, error) { +// ReadEncryptedFile reads data from an encrypted file in directory with key +func ReadEncryptedFile(directory, filename string, key [32]byte) ([]byte, error) { encryptedbytes, err := ioutil.ReadFile(path.Join(directory, filename)) if err == nil { - data, err := decryptFile(encryptedbytes, key) + data, err := DecryptFile(encryptedbytes, key) if err == nil { return data, nil } diff --git a/storage/v1/file_store.go b/storage/v1/file_store.go index 5145db3..4351f7e 100644 --- a/storage/v1/file_store.go +++ b/storage/v1/file_store.go @@ -33,7 +33,7 @@ func NewFileStore(directory string, filename string, key [32]byte) FileStore { // write serializes a cwtchPeer to a file func (fps *fileStore) Write(data []byte) error { - encryptedbytes, err := encryptFileData(data, fps.key) + encryptedbytes, err := EncryptFileData(data, fps.key) if err != nil { return err } @@ -43,7 +43,7 @@ func (fps *fileStore) Write(data []byte) error { } func (fps *fileStore) Read() ([]byte, error) { - return readEncryptedFile(fps.directory, fps.filename, fps.key) + return ReadEncryptedFile(fps.directory, fps.filename, fps.key) } func (fps *fileStore) Delete() { diff --git a/storage/v1/profile_store.go b/storage/v1/profile_store.go index d329aa0..cfae079 100644 --- a/storage/v1/profile_store.go +++ b/storage/v1/profile_store.go @@ -32,7 +32,7 @@ type ProfileStoreV1 struct { } func initV1Directory(directory, password string) ([32]byte, [128]byte, error) { - key, salt, err := createKeySalt(password) + key, salt, err := CreateKeySalt(password) if err != nil { log.Errorf("Could not create key for profile store from password: %v\n", err) return [32]byte{}, [128]byte{}, err @@ -91,7 +91,7 @@ func LoadProfileWriterStore(eventManager event.Manager, directory, password stri return nil, err } - key := createKey(password, salt) + key := CreateKey(password, salt) ps := &ProfileStoreV1{fs: NewFileStore(directory, profileFilename, key), key: key, directory: directory, profile: nil, eventManager: eventManager, streamStores: map[string]StreamStore{}, writer: true} copy(ps.salt[:], salt) @@ -179,14 +179,14 @@ func (ps *ProfileStoreV1) GetStatusMessages() []*event.Event { // ChangePassword restores all data under a new password's encryption func (ps *ProfileStoreV1) ChangePassword(oldpass, newpass, eventID string) { - oldkey := createKey(oldpass, ps.salt[:]) + oldkey := CreateKey(oldpass, ps.salt[:]) if oldkey != ps.key { ps.eventManager.Publish(event.NewEventList(event.ChangePasswordError, event.Error, "Supplied current password does not match", event.EventID, eventID)) return } - newkey := createKey(newpass, ps.salt[:]) + newkey := CreateKey(newpass, ps.salt[:]) newStreamStores := map[string]StreamStore{} idToNewLocalID := map[string]string{} diff --git a/storage/v1/stream_store.go b/storage/v1/stream_store.go index e964146..14d82bd 100644 --- a/storage/v1/stream_store.go +++ b/storage/v1/stream_store.go @@ -57,7 +57,7 @@ func (ss *streamStore) initBuffer() { func (ss *streamStore) initBufferFromStorage() error { filename := fmt.Sprintf("%s.%d", ss.filenameBase, 0) - bytes, _ := readEncryptedFile(ss.storeDirectory, filename, ss.key) + bytes, _ := ReadEncryptedFile(ss.storeDirectory, filename, ss.key) msgs := []model.Message{} err := json.Unmarshal([]byte(bytes), &msgs) @@ -83,7 +83,7 @@ func (ss *streamStore) updateFile() error { } // ENCRYPT - encryptedMsgs, err := encryptFileData(msgs, ss.key) + encryptedMsgs, err := EncryptFileData(msgs, ss.key) if err != nil { log.Errorf("Failed to encrypt messages: %v\n", err) return err @@ -118,7 +118,7 @@ func (ss *streamStore) Read() (messages []model.Message) { for i := fileStorePartitions - 1; i >= 0; i-- { filename := fmt.Sprintf("%s.%d", ss.filenameBase, i) - bytes, err := readEncryptedFile(ss.storeDirectory, filename, ss.key) + bytes, err := ReadEncryptedFile(ss.storeDirectory, filename, ss.key) if err != nil { continue } diff --git a/storage/v1/stream_store_test.go b/storage/v1/stream_store_test.go index b2f73b9..cb596ea 100644 --- a/storage/v1/stream_store_test.go +++ b/storage/v1/stream_store_test.go @@ -15,7 +15,7 @@ func TestStreamStoreWriteRead(t *testing.T) { os.Remove(".test.json") os.RemoveAll(testingDir) os.Mkdir(testingDir, 0777) - key, _, _ := createKeySalt(password) + key, _, _ := CreateKeySalt(password) ss1 := NewStreamStore(testingDir, filenameBase, key) m := model.Message{Message: line1} ss1.Write(m) @@ -34,7 +34,7 @@ func TestStreamStoreWriteReadRotate(t *testing.T) { os.Remove(".test.json") os.RemoveAll(testingDir) os.Mkdir(testingDir, 0777) - key, _, _ := createKeySalt(password) + key, _, _ := CreateKeySalt(password) ss1 := NewStreamStore(testingDir, filenameBase, key) m := model.Message{Message: line1} for i := 0; i < 400; i++ {