1
0

chachapoly.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. package noiseutil
  2. import (
  3. "crypto/cipher"
  4. "encoding/binary"
  5. "errors"
  6. "github.com/flynn/noise"
  7. )
  8. // CipherStateChaChaPoly is the data-plane wrapper for the ChaCha20-Poly1305 AEAD cipher.
  9. // ChaCha20-Poly1305 uses little-endian nonce encoding per the Noise spec.
  10. type CipherStateChaChaPoly struct {
  11. c cipher.AEAD
  12. }
  13. // NewCipherStateChaChaPoly extracts the underlying AEAD from the post-handshake noise.CipherState.
  14. // The caller is responsible for ensuring the noise cipher is actually ChaCha20-Poly1305.
  15. func NewCipherStateChaChaPoly(s *noise.CipherState) *CipherStateChaChaPoly {
  16. return &CipherStateChaChaPoly{c: s.Cipher().(cipher.AEAD)}
  17. }
  18. func (s *CipherStateChaChaPoly) EncryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error) {
  19. if s == nil {
  20. return nil, errors.New("no cipher state available to encrypt")
  21. }
  22. if n >= RejectAfterMessages {
  23. return nil, ErrMessageCounterExhausted
  24. }
  25. nb[0] = 0
  26. nb[1] = 0
  27. nb[2] = 0
  28. nb[3] = 0
  29. binary.LittleEndian.PutUint64(nb[4:], n)
  30. return s.c.Seal(out, nb, plaintext, ad), nil
  31. }
  32. func (s *CipherStateChaChaPoly) DecryptDanger(out, ad, ciphertext []byte, n uint64, nb []byte) ([]byte, error) {
  33. if s == nil {
  34. return []byte{}, nil
  35. }
  36. nb[0] = 0
  37. nb[1] = 0
  38. nb[2] = 0
  39. nb[3] = 0
  40. binary.LittleEndian.PutUint64(nb[4:], n)
  41. return s.c.Open(out, nb, ciphertext, ad)
  42. }
  43. func (s *CipherStateChaChaPoly) Overhead() int {
  44. if s == nil {
  45. return 0
  46. }
  47. return s.c.Overhead()
  48. }