github.com/mad-day/Yawning-crypto@v0.0.0-20190711051033-5a5f8cca32ec/aez/aead.go (about)

     1  // aead.go - crypto/cipher.AEAD wrapper
     2  //
     3  // To the extent possible under law, Yawning Angel has waived all copyright
     4  // and related or neighboring rights to aez, using the Creative
     5  // Commons "CC0" public domain dedication. See LICENSE or
     6  // <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
     7  
     8  package aez
     9  
    10  import (
    11  	"crypto/cipher"
    12  	"errors"
    13  )
    14  
    15  var errOpen = errors.New("aez: Message authentication failed")
    16  
    17  const (
    18  	aeadNonceSize = 16
    19  	aeadOverhead  = 16
    20  )
    21  
    22  // AeadAEZ is AEZ wrapped in the crypto/cipher.AEAD interface.  It expects
    23  // a 16 byte nonce, and uses a 16 byte tag, per the recommended defaults in
    24  // the specification.
    25  //
    26  // The AEZ primitive itself supports a vector of authenticated data, variable
    27  // length nonces, and variable length authentication tags.  Users who require
    28  // such functionality should investigate the one-shot Encrypt/Decrypt calls
    29  // instead.
    30  type AeadAEZ struct {
    31  	key [extractedKeySize]byte
    32  }
    33  
    34  // NonceSize returns the size of the nonce that must be passed to Seal
    35  // and Open.
    36  func (a *AeadAEZ) NonceSize() int {
    37  	return aeadNonceSize
    38  }
    39  
    40  // Overhead returns the maximum difference between the lengths of a
    41  // plaintext and its ciphertext.
    42  func (a *AeadAEZ) Overhead() int {
    43  	return aeadOverhead
    44  }
    45  
    46  // Reset clears the sensitive keying material from the datastructure such
    47  // that it will no longer be in memory.
    48  func (a *AeadAEZ) Reset() {
    49  	memwipe(a.key[:])
    50  }
    51  
    52  // Seal encrypts and authenticates plaintext, authenticates the
    53  // additional data and appends the result to dst, returning the updated
    54  // slice.  The nonce must be NonceSize() bytes long.
    55  //
    56  // The nonce additionally should be unique for all time, for a given key,
    57  // however the AEZ primitive does provide nonce-reuse misuse-resistance,
    58  // see the paper for more details (MRAE).
    59  func (a *AeadAEZ) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
    60  	if len(nonce) != aeadNonceSize {
    61  		panic("aez: incorrect nonce length given to AEZ")
    62  	}
    63  
    64  	var ad [][]byte
    65  	if additionalData != nil {
    66  		ad = append(ad, additionalData)
    67  	}
    68  	// WARNING: The AEAD interface expects plaintext/dst overlap to be allowed.
    69  	c := Encrypt(a.key[:], nonce, ad, aeadOverhead, plaintext, nil)
    70  	dst = append(dst, c...)
    71  
    72  	return dst
    73  }
    74  
    75  // Open decrypts and authenticates ciphertext, authenticates the
    76  // additional data and, if successful, appends the resulting plaintext
    77  // to dst, returning the updated slice. The nonce must be NonceSize()
    78  // bytes long and both it and the additional data must match the
    79  // value passed to Seal.
    80  func (a *AeadAEZ) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
    81  	if len(nonce) != aeadNonceSize {
    82  		panic("aez: incorrect nonce length given to AEZ")
    83  	}
    84  
    85  	var ad [][]byte
    86  	if additionalData != nil {
    87  		ad = append(ad, additionalData)
    88  	}
    89  	// WARNING: The AEAD interface expects ciphertext/dst overlap to be allowed.
    90  	d, ok := Decrypt(a.key[:], nonce, ad, aeadOverhead, ciphertext, nil)
    91  	if !ok {
    92  		return nil, errOpen
    93  	}
    94  	dst = append(dst, d...)
    95  
    96  	return dst, nil
    97  }
    98  
    99  // New returns AEZ wrapped in a new cipher.AEAD instance, with the recommended
   100  // nonce and tag lengths.
   101  func New(key []byte) (cipher.AEAD, error) {
   102  	if len(key) == 0 {
   103  		return nil, errors.New("aez: Invalid key size")
   104  	}
   105  	a := new(AeadAEZ)
   106  	extract(key, &a.key)
   107  	return a, nil
   108  }