github.com/slackhq/nebula@v1.9.0/noise.go (about)

     1  package nebula
     2  
     3  import (
     4  	"crypto/cipher"
     5  	"encoding/binary"
     6  	"errors"
     7  
     8  	"github.com/flynn/noise"
     9  )
    10  
    11  type endianness interface {
    12  	PutUint64(b []byte, v uint64)
    13  }
    14  
    15  var noiseEndianness endianness = binary.BigEndian
    16  
    17  type NebulaCipherState struct {
    18  	c noise.Cipher
    19  	//k [32]byte
    20  	//n uint64
    21  }
    22  
    23  func NewNebulaCipherState(s *noise.CipherState) *NebulaCipherState {
    24  	return &NebulaCipherState{c: s.Cipher()}
    25  
    26  }
    27  
    28  // EncryptDanger encrypts and authenticates a given payload.
    29  //
    30  // out is a destination slice to hold the output of the EncryptDanger operation.
    31  // - ad is additional data, which will be authenticated and appended to out, but not encrypted.
    32  // - plaintext is encrypted, authenticated and appended to out.
    33  // - n is a nonce value which must never be re-used with this key.
    34  // - nb is a buffer used for temporary storage in the implementation of this call, which should
    35  // be re-used by callers to minimize garbage collection.
    36  func (s *NebulaCipherState) EncryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error) {
    37  	if s != nil {
    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  	} else {
    53  		return nil, errors.New("no cipher state available to encrypt")
    54  	}
    55  }
    56  
    57  func (s *NebulaCipherState) DecryptDanger(out, ad, ciphertext []byte, n uint64, nb []byte) ([]byte, error) {
    58  	if s != nil {
    59  		nb[0] = 0
    60  		nb[1] = 0
    61  		nb[2] = 0
    62  		nb[3] = 0
    63  		noiseEndianness.PutUint64(nb[4:], n)
    64  		return s.c.(cipher.AEAD).Open(out, nb, ciphertext, ad)
    65  	} else {
    66  		return []byte{}, nil
    67  	}
    68  }
    69  
    70  func (s *NebulaCipherState) Overhead() int {
    71  	if s != nil {
    72  		return s.c.(cipher.AEAD).Overhead()
    73  	}
    74  	return 0
    75  }