encrypt.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Package encrypter is suitable for encrypting messages you would like to securely share between two points.
  2. // Useful for providing end to end encryption (E2EE). It uses Box (NaCl) for encrypting the messages.
  3. // tldr is it uses Elliptic Curves (Curve25519) for the keys, XSalsa20 and Poly1305 for encryption.
  4. // You can read more here https://godoc.org/golang.org/x/crypto/nacl/box.
  5. //
  6. // msg := []byte("super safe message.")
  7. // alice, err := NewEncrypter("alice_priv_key.pem", "alice_pub_key.pem")
  8. // if err != nil {
  9. // log.Fatal(err)
  10. // }
  11. //
  12. // bob, err := NewEncrypter("bob_priv_key.pem", "bob_pub_key.pem")
  13. // if err != nil {
  14. // log.Fatal(err)
  15. // }
  16. // encrypted, err := alice.Encrypt(msg, bob.PublicKey())
  17. // if err != nil {
  18. // log.Fatal(err)
  19. // }
  20. //
  21. // data, err := bob.Decrypt(encrypted, alice.PublicKey())
  22. // if err != nil {
  23. // log.Fatal(err)
  24. // }
  25. // fmt.Println(string(data))
  26. package token
  27. import (
  28. "bytes"
  29. "crypto/rand"
  30. "encoding/base64"
  31. "encoding/pem"
  32. "errors"
  33. "io"
  34. "os"
  35. "golang.org/x/crypto/nacl/box"
  36. )
  37. // Encrypter represents a keypair value with auxiliary functions to make
  38. // doing encryption and decryption easier
  39. type Encrypter struct {
  40. privateKey *[32]byte
  41. publicKey *[32]byte
  42. }
  43. // NewEncrypter returns a new encrypter with initialized keypair
  44. func NewEncrypter(privateKey, publicKey string) (*Encrypter, error) {
  45. e := &Encrypter{}
  46. pubKey, key, err := e.fetchOrGenerateKeys(privateKey, publicKey)
  47. if err != nil {
  48. return nil, err
  49. }
  50. e.privateKey, e.publicKey = key, pubKey
  51. return e, nil
  52. }
  53. // PublicKey returns a base64 encoded public key. Useful for transport (like in HTTP requests)
  54. func (e *Encrypter) PublicKey() string {
  55. return base64.URLEncoding.EncodeToString(e.publicKey[:])
  56. }
  57. // Decrypt data that was encrypted using our publicKey. It will use our privateKey and the sender's publicKey to decrypt
  58. // data is an encrypted buffer of data, mostly like from the Encrypt function. Messages contain the nonce data on the front
  59. // of the message.
  60. // senderPublicKey is a base64 encoded version of the sender's public key (most likely from the PublicKey function).
  61. // The return value is the decrypted buffer or an error.
  62. func (e *Encrypter) Decrypt(data []byte, senderPublicKey string) ([]byte, error) {
  63. var decryptNonce [24]byte
  64. copy(decryptNonce[:], data[:24]) // we pull the nonce from the front of the actual message.
  65. pubKey, err := e.decodePublicKey(senderPublicKey)
  66. if err != nil {
  67. return nil, err
  68. }
  69. decrypted, ok := box.Open(nil, data[24:], &decryptNonce, pubKey, e.privateKey)
  70. if !ok {
  71. return nil, errors.New("failed to decrypt message")
  72. }
  73. return decrypted, nil
  74. }
  75. // Encrypt data using our privateKey and the recipient publicKey
  76. // data is a buffer of data that we would like to encrypt. Messages will have the nonce added to front
  77. // as they have to unique for each message shared.
  78. // recipientPublicKey is a base64 encoded version of the sender's public key (most likely from the PublicKey function).
  79. // The return value is the encrypted buffer or an error.
  80. func (e *Encrypter) Encrypt(data []byte, recipientPublicKey string) ([]byte, error) {
  81. var nonce [24]byte
  82. if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
  83. return nil, err
  84. }
  85. pubKey, err := e.decodePublicKey(recipientPublicKey)
  86. if err != nil {
  87. return nil, err
  88. }
  89. // This encrypts msg and adds the nonce to the front of the message, since the nonce has to be
  90. // the same for encrypting and decrypting
  91. return box.Seal(nonce[:], data, &nonce, pubKey, e.privateKey), nil
  92. }
  93. // WriteKeys keys will take the currently initialized keypair and write them to provided filenames
  94. func (e *Encrypter) WriteKeys(privateKey, publicKey string) error {
  95. if err := e.writeKey(e.privateKey[:], "BOX PRIVATE KEY", privateKey); err != nil {
  96. return err
  97. }
  98. return e.writeKey(e.publicKey[:], "PUBLIC KEY", publicKey)
  99. }
  100. // fetchOrGenerateKeys will either load or create a keypair if it doesn't exist
  101. func (e *Encrypter) fetchOrGenerateKeys(privateKey, publicKey string) (*[32]byte, *[32]byte, error) {
  102. key, err := e.fetchKey(privateKey)
  103. if os.IsNotExist(err) {
  104. return box.GenerateKey(rand.Reader)
  105. } else if err != nil {
  106. return nil, nil, err
  107. }
  108. pub, err := e.fetchKey(publicKey)
  109. if os.IsNotExist(err) {
  110. return box.GenerateKey(rand.Reader)
  111. } else if err != nil {
  112. return nil, nil, err
  113. }
  114. return pub, key, nil
  115. }
  116. // writeKey will write a key to disk in DER format (it's a standard pem key)
  117. func (e *Encrypter) writeKey(key []byte, pemType, filename string) error {
  118. data := pem.EncodeToMemory(&pem.Block{
  119. Type: pemType,
  120. Bytes: key,
  121. })
  122. f, err := os.Create(filename)
  123. if err != nil {
  124. return err
  125. }
  126. _, err = f.Write(data)
  127. if err != nil {
  128. return err
  129. }
  130. return nil
  131. }
  132. // fetchKey will load a a DER formatted key from disk
  133. func (e *Encrypter) fetchKey(filename string) (*[32]byte, error) {
  134. f, err := os.Open(filename)
  135. if err != nil {
  136. return nil, err
  137. }
  138. buf := new(bytes.Buffer)
  139. io.Copy(buf, f)
  140. p, _ := pem.Decode(buf.Bytes())
  141. if p == nil {
  142. return nil, errors.New("Failed to decode key")
  143. }
  144. var newKey [32]byte
  145. copy(newKey[:], p.Bytes)
  146. return &newKey, nil
  147. }
  148. // decodePublicKey will base64 decode the provided key to the box representation
  149. func (e *Encrypter) decodePublicKey(key string) (*[32]byte, error) {
  150. pub, err := base64.URLEncoding.DecodeString(key)
  151. if err != nil {
  152. return nil, err
  153. }
  154. var newKey [32]byte
  155. copy(newKey[:], pub)
  156. return &newKey, nil
  157. }