api.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // api.go - External interface
  2. //
  3. // To the extent possible under law, Yawning Angel has waived all copyright
  4. // and related or neighboring rights to the software, 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 norx implements the NORX Authenticated Encryption Algorithm,
  8. // specifically the NORX64-4-1 and NORX64-6-1 variants, as recommended by the
  9. // designers for software implementations on modern 64-bit CPUs.
  10. //
  11. // This implementation is derived from the Public Domain reference
  12. // implementation by Jean-Philippe Aumasson, Philipp Jovanovic, and Samuel
  13. // Neves.
  14. //
  15. // Warning:
  16. // NORX is a rather new authenticated encryption algorithm. The authors are
  17. // confident that it is secure but nevertheless NORX should be considered
  18. // experimental. Therefore, do not use it in your applications!
  19. package norx
  20. import (
  21. "crypto/cipher"
  22. "errors"
  23. )
  24. var (
  25. // ErrInvalidKeySize is the error thrown via a panic when a key is an
  26. // invalid size.
  27. ErrInvalidKeySize = errors.New("norx: invalid key size")
  28. // ErrInvalidNonceSize is the error thrown via a panic when a nonce is
  29. // an invalid size.
  30. ErrInvalidNonceSize = errors.New("norx: invalid nonce size")
  31. // ErrOpen is the error returned when the message authentication fails
  32. // during an Open call.
  33. ErrOpen = errors.New("norx: message authentication failed")
  34. )
  35. // AEAD is a parameterized and keyed NORX instance, in the spirit of
  36. // crypto/cipher.AEAD.
  37. type AEAD struct {
  38. key []byte
  39. rounds int
  40. }
  41. // NonceSize returns the size of the nonce that must be passed to Seal and
  42. // Open.
  43. func (ae *AEAD) NonceSize() int {
  44. return NonceSize
  45. }
  46. // Overhead returns the maximum difference between the lengths of a plaintext
  47. // and its ciphertext.
  48. func (ae *AEAD) Overhead() int {
  49. return TagSize
  50. }
  51. // Seal encrypts and authenticates plaintext, authenticates the optional
  52. // header and footer (additional data) and, appends the result to dst,
  53. // returning the updated slice. The nonce must be NonceSize() bytes long and
  54. // unique for all time, for a given key.
  55. //
  56. // The plaintext and dst must overlap exactly or not at all. To reuse
  57. // plaintext's storage for the encrypted output, use plaintext[:0] as dst.
  58. func (ae *AEAD) Seal(dst, nonce, plaintext, header, footer []byte) []byte {
  59. if len(nonce) != NonceSize {
  60. panic(ErrInvalidNonceSize)
  61. }
  62. dst = aeadEncrypt(ae.rounds, dst, header, plaintext, footer, nonce, ae.key)
  63. return dst
  64. }
  65. // Open decrypts and authenticates ciphertext, authenticates the optonal
  66. // header and footer (additional data) and, if successful, appends the
  67. // resulting plaintext to dst, returning the updated slice. The nonce must
  68. // be NonceSize() bytes long and both it and the additional data must match the
  69. // value passed to Seal.
  70. //
  71. // The ciphertext and dst must overlap exactly or not at all. To reuse
  72. // ciphertext's storage for the decrypted output, use ciphertext[:0] as dst.
  73. //
  74. // Even if the function fails, the contents of dst, up to its capacity,
  75. // may be overwritten.
  76. func (ae *AEAD) Open(dst, nonce, ciphertext, header, footer []byte) ([]byte, error) {
  77. var err error
  78. var ok bool
  79. if len(nonce) != NonceSize {
  80. panic(ErrInvalidNonceSize)
  81. }
  82. dst, ok = aeadDecrypt(ae.rounds, dst, header, ciphertext, footer, nonce, ae.key)
  83. if !ok {
  84. err = ErrOpen
  85. }
  86. return dst, err
  87. }
  88. // Reset securely purges stored sensitive data from the AEAD instance.
  89. func (ae *AEAD) Reset() {
  90. burnBytes(ae.key)
  91. }
  92. // ToRuntime converts an AEAD instance to a crypto/cipher.AEAD instance.
  93. //
  94. // The interfaces are distinct as NORX supports both a header and footer as
  95. // additional data, while the runtime interface only has a singular additonal
  96. // data parameter. The resulting cipher.AEAD instance will use the header
  97. // for additional data if provided, ignoring the footer.
  98. func (ae *AEAD) ToRuntime() cipher.AEAD {
  99. return &goAEAD{ae}
  100. }
  101. type goAEAD struct {
  102. aead *AEAD
  103. }
  104. func (ae *goAEAD) NonceSize() int {
  105. return ae.aead.NonceSize()
  106. }
  107. func (ae *goAEAD) Overhead() int {
  108. return ae.aead.Overhead()
  109. }
  110. func (ae *goAEAD) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
  111. return ae.aead.Seal(dst, nonce, plaintext, additionalData, nil)
  112. }
  113. func (ae *goAEAD) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
  114. return ae.aead.Open(dst, nonce, ciphertext, additionalData, nil)
  115. }
  116. // New6441 returns a new keyed NORX64-4-1 instance.
  117. func New6441(key []byte) *AEAD {
  118. return newAEAD(key, 4)
  119. }
  120. // New6461 returns a new keyed NORX64-6-1 instance.
  121. func New6461(key []byte) *AEAD {
  122. return newAEAD(key, 6)
  123. }
  124. func newAEAD(key []byte, rounds int) *AEAD {
  125. if len(key) != KeySize {
  126. panic(ErrInvalidKeySize)
  127. }
  128. return &AEAD{
  129. key: append([]byte{}, key...),
  130. rounds: rounds,
  131. }
  132. }