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 }