noise.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package nebula
  2. import (
  3. "crypto/cipher"
  4. "encoding/binary"
  5. "errors"
  6. "github.com/flynn/noise"
  7. )
  8. type endianness interface {
  9. PutUint64(b []byte, v uint64)
  10. }
  11. var noiseEndianness endianness = binary.BigEndian
  12. type NebulaCipherState struct {
  13. c cipher.AEAD
  14. }
  15. func NewNebulaCipherState(s *noise.CipherState) *NebulaCipherState {
  16. x := s.Cipher()
  17. return &NebulaCipherState{c: x.(cipher.AEAD)}
  18. }
  19. // EncryptDanger encrypts and authenticates a given payload.
  20. //
  21. // out is a destination slice to hold the output of the EncryptDanger operation.
  22. // - ad is additional data, which will be authenticated and appended to out, but not encrypted.
  23. // - plaintext is encrypted, authenticated and appended to out.
  24. // - n is a nonce value which must never be re-used with this key.
  25. // - nb is a buffer used for temporary storage in the implementation of this call, which should
  26. // be re-used by callers to minimize garbage collection.
  27. func (s *NebulaCipherState) EncryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error) {
  28. if s != nil {
  29. // TODO: Is this okay now that we have made messageCounter atomic?
  30. // Alternative may be to split the counter space into ranges
  31. //if n <= s.n {
  32. // return nil, errors.New("CRITICAL: a duplicate counter value was used")
  33. //}
  34. //s.n = n
  35. nb[0] = 0
  36. nb[1] = 0
  37. nb[2] = 0
  38. nb[3] = 0
  39. noiseEndianness.PutUint64(nb[4:], n)
  40. out = s.c.Seal(out, nb, plaintext, ad)
  41. //l.Debugf("Encryption: outlen: %d, nonce: %d, ad: %s, plainlen %d", len(out), n, ad, len(plaintext))
  42. return out, nil
  43. } else {
  44. return nil, errors.New("no cipher state available to encrypt")
  45. }
  46. }
  47. func (s *NebulaCipherState) DecryptDanger(out, ad, ciphertext []byte, n uint64, nb []byte) ([]byte, error) {
  48. if s != nil {
  49. nb[0] = 0
  50. nb[1] = 0
  51. nb[2] = 0
  52. nb[3] = 0
  53. noiseEndianness.PutUint64(nb[4:], n)
  54. return s.c.Open(out, nb, ciphertext, ad)
  55. } else {
  56. return []byte{}, nil
  57. }
  58. }
  59. func (s *NebulaCipherState) Overhead() int {
  60. if s != nil {
  61. return s.c.Overhead()
  62. }
  63. return 0
  64. }