noise.go 2.5 KB

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