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.

73 lines
1.9KB

  1. package v1
  2. import (
  3. "crypto/rand"
  4. "errors"
  5. "git.openprivacy.ca/openprivacy/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. // createKeySalt derives a key from a password: returns key, salt, err
  14. func createKeySalt(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. func createKey(password string, salt []byte) [32]byte {
  26. dk := pbkdf2.Key([]byte(password), salt, 4096, 32, sha3.New512)
  27. var dkr [32]byte
  28. copy(dkr[:], dk)
  29. return dkr
  30. }
  31. //encryptFileData encrypts the cwtchPeer via the specified key.
  32. func encryptFileData(data []byte, key [32]byte) ([]byte, error) {
  33. var nonce [24]byte
  34. if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
  35. log.Errorf("Cannot read from random: %v\n", err)
  36. return nil, err
  37. }
  38. encrypted := secretbox.Seal(nonce[:], data, &nonce, &key)
  39. return encrypted, nil
  40. }
  41. //decryptFile decrypts the passed ciphertext into a cwtchPeer via the specified key.
  42. func decryptFile(ciphertext []byte, key [32]byte) ([]byte, error) {
  43. var decryptNonce [24]byte
  44. copy(decryptNonce[:], ciphertext[:24])
  45. decrypted, ok := secretbox.Open(nil, ciphertext[24:], &decryptNonce, &key)
  46. if ok {
  47. return decrypted, nil
  48. }
  49. return nil, errors.New("Failed to decrypt")
  50. }
  51. // load instantiates a cwtchPeer from the file store
  52. func readEncryptedFile(directory, filename string, key [32]byte) ([]byte, error) {
  53. encryptedbytes, err := ioutil.ReadFile(path.Join(directory, filename))
  54. if err == nil {
  55. data, err := decryptFile(encryptedbytes, key)
  56. if err == nil {
  57. return data, nil
  58. }
  59. return nil, err
  60. }
  61. return nil, err
  62. }