aead.go 3.2 KB

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