noise.go 2.0 KB

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