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