Official cwtch.im peer and server implementations. https://cwtch.im
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

file_enc.go 2.0KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package storage
  2. import (
  3. "crypto/rand"
  4. "errors"
  5. "git.openprivacy.ca/openprivacy/libricochet-go/log"
  6. "golang.org/x/crypto/nacl/secretbox"
  7. "golang.org/x/crypto/pbkdf2"
  8. "golang.org/x/crypto/sha3"
  9. "io"
  10. "io/ioutil"
  11. "path"
  12. )
  13. // createKey derives a key from a password
  14. func createKey(password string) ([32]byte, [128]byte, error) {
  15. var salt [128]byte
  16. if _, err := io.ReadFull(rand.Reader, salt[:]); err != nil {
  17. log.Errorf("Cannot read from random: %v\n", err)
  18. return [32]byte{}, salt, err
  19. }
  20. dk := pbkdf2.Key([]byte(password), salt[:], 4096, 32, sha3.New512)
  21. var dkr [32]byte
  22. copy(dkr[:], dk)
  23. return dkr, salt, nil
  24. }
  25. //encryptFileData encrypts the cwtchPeer via the specified key.
  26. func encryptFileData(data []byte, key [32]byte) ([]byte, error) {
  27. var nonce [24]byte
  28. if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
  29. log.Errorf("Cannot read from random: %v\n", err)
  30. return nil, err
  31. }
  32. encrypted := secretbox.Seal(nonce[:], data, &nonce, &key)
  33. return encrypted, nil
  34. }
  35. //decryptFile decrypts the passed ciphertext into a cwtchPeer via the specified key.
  36. func decryptFile(ciphertext []byte, key [32]byte) ([]byte, error) {
  37. var decryptNonce [24]byte
  38. copy(decryptNonce[:], ciphertext[:24])
  39. decrypted, ok := secretbox.Open(nil, ciphertext[24:], &decryptNonce, &key)
  40. if ok {
  41. return decrypted, nil
  42. }
  43. return nil, errors.New("Failed to decrypt")
  44. }
  45. // Load instantiates a cwtchPeer from the file store
  46. func readEncryptedFile(directory, filename, password string) ([]byte, error) {
  47. encryptedbytes, err := ioutil.ReadFile(path.Join(directory, filename))
  48. if err == nil && len(encryptedbytes) > 128 {
  49. var dkr [32]byte
  50. //Separate the salt from the encrypted bytes, then generate the derived key
  51. salt, encryptedbytes := encryptedbytes[0:128], encryptedbytes[128:]
  52. dk := pbkdf2.Key([]byte(password), salt, 4096, 32, sha3.New512)
  53. copy(dkr[:], dk)
  54. data, err := decryptFile(encryptedbytes, dkr)
  55. if err == nil {
  56. return data, nil
  57. }
  58. return nil, err
  59. }
  60. return nil, err
  61. }