chacha20poly1305_test.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // Copyright 2016 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package chacha20poly1305
  5. import (
  6. "bytes"
  7. "crypto/cipher"
  8. cr "crypto/rand"
  9. "encoding/hex"
  10. mr "math/rand"
  11. "strconv"
  12. "testing"
  13. )
  14. func TestVectors(t *testing.T) {
  15. for i, test := range chacha20Poly1305Tests {
  16. key, _ := hex.DecodeString(test.key)
  17. nonce, _ := hex.DecodeString(test.nonce)
  18. ad, _ := hex.DecodeString(test.aad)
  19. plaintext, _ := hex.DecodeString(test.plaintext)
  20. var (
  21. aead cipher.AEAD
  22. err error
  23. )
  24. switch len(nonce) {
  25. case NonceSize:
  26. aead, err = New(key)
  27. case NonceSizeX:
  28. aead, err = NewX(key)
  29. default:
  30. t.Fatalf("#%d: wrong nonce length: %d", i, len(nonce))
  31. }
  32. if err != nil {
  33. t.Fatal(err)
  34. }
  35. ct := aead.Seal(nil, nonce, plaintext, ad)
  36. if ctHex := hex.EncodeToString(ct); ctHex != test.out {
  37. t.Errorf("#%d: got %s, want %s", i, ctHex, test.out)
  38. continue
  39. }
  40. plaintext2, err := aead.Open(nil, nonce, ct, ad)
  41. if err != nil {
  42. t.Errorf("#%d: Open failed", i)
  43. continue
  44. }
  45. if !bytes.Equal(plaintext, plaintext2) {
  46. t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext)
  47. continue
  48. }
  49. if len(ad) > 0 {
  50. alterAdIdx := mr.Intn(len(ad))
  51. ad[alterAdIdx] ^= 0x80
  52. if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
  53. t.Errorf("#%d: Open was successful after altering additional data", i)
  54. }
  55. ad[alterAdIdx] ^= 0x80
  56. }
  57. alterNonceIdx := mr.Intn(aead.NonceSize())
  58. nonce[alterNonceIdx] ^= 0x80
  59. if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
  60. t.Errorf("#%d: Open was successful after altering nonce", i)
  61. }
  62. nonce[alterNonceIdx] ^= 0x80
  63. alterCtIdx := mr.Intn(len(ct))
  64. ct[alterCtIdx] ^= 0x80
  65. if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
  66. t.Errorf("#%d: Open was successful after altering ciphertext", i)
  67. }
  68. ct[alterCtIdx] ^= 0x80
  69. }
  70. }
  71. func TestRandom(t *testing.T) {
  72. // Some random tests to verify Open(Seal) == Plaintext
  73. f := func(t *testing.T, nonceSize int) {
  74. for i := 0; i < 256; i++ {
  75. var nonce = make([]byte, nonceSize)
  76. var key [32]byte
  77. al := mr.Intn(128)
  78. pl := mr.Intn(16384)
  79. ad := make([]byte, al)
  80. plaintext := make([]byte, pl)
  81. cr.Read(key[:])
  82. cr.Read(nonce[:])
  83. cr.Read(ad)
  84. cr.Read(plaintext)
  85. var (
  86. aead cipher.AEAD
  87. err error
  88. )
  89. switch len(nonce) {
  90. case NonceSize:
  91. aead, err = New(key[:])
  92. case NonceSizeX:
  93. aead, err = NewX(key[:])
  94. default:
  95. t.Fatalf("#%d: wrong nonce length: %d", i, len(nonce))
  96. }
  97. if err != nil {
  98. t.Fatal(err)
  99. }
  100. ct := aead.Seal(nil, nonce[:], plaintext, ad)
  101. plaintext2, err := aead.Open(nil, nonce[:], ct, ad)
  102. if err != nil {
  103. t.Errorf("Random #%d: Open failed", i)
  104. continue
  105. }
  106. if !bytes.Equal(plaintext, plaintext2) {
  107. t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext)
  108. continue
  109. }
  110. if len(ad) > 0 {
  111. alterAdIdx := mr.Intn(len(ad))
  112. ad[alterAdIdx] ^= 0x80
  113. if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
  114. t.Errorf("Random #%d: Open was successful after altering additional data", i)
  115. }
  116. ad[alterAdIdx] ^= 0x80
  117. }
  118. alterNonceIdx := mr.Intn(aead.NonceSize())
  119. nonce[alterNonceIdx] ^= 0x80
  120. if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
  121. t.Errorf("Random #%d: Open was successful after altering nonce", i)
  122. }
  123. nonce[alterNonceIdx] ^= 0x80
  124. alterCtIdx := mr.Intn(len(ct))
  125. ct[alterCtIdx] ^= 0x80
  126. if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
  127. t.Errorf("Random #%d: Open was successful after altering ciphertext", i)
  128. }
  129. ct[alterCtIdx] ^= 0x80
  130. }
  131. }
  132. t.Run("Standard", func(t *testing.T) { f(t, NonceSize) })
  133. t.Run("X", func(t *testing.T) { f(t, NonceSizeX) })
  134. }
  135. func benchamarkChaCha20Poly1305Seal(b *testing.B, buf []byte, nonceSize int) {
  136. b.ReportAllocs()
  137. b.SetBytes(int64(len(buf)))
  138. var key [32]byte
  139. var nonce = make([]byte, nonceSize)
  140. var ad [13]byte
  141. var out []byte
  142. var aead cipher.AEAD
  143. switch len(nonce) {
  144. case NonceSize:
  145. aead, _ = New(key[:])
  146. case NonceSizeX:
  147. aead, _ = NewX(key[:])
  148. }
  149. b.ResetTimer()
  150. for i := 0; i < b.N; i++ {
  151. out = aead.Seal(out[:0], nonce[:], buf[:], ad[:])
  152. }
  153. }
  154. func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte, nonceSize int) {
  155. b.ReportAllocs()
  156. b.SetBytes(int64(len(buf)))
  157. var key [32]byte
  158. var nonce = make([]byte, nonceSize)
  159. var ad [13]byte
  160. var ct []byte
  161. var out []byte
  162. var aead cipher.AEAD
  163. switch len(nonce) {
  164. case NonceSize:
  165. aead, _ = New(key[:])
  166. case NonceSizeX:
  167. aead, _ = NewX(key[:])
  168. }
  169. ct = aead.Seal(ct[:0], nonce[:], buf[:], ad[:])
  170. b.ResetTimer()
  171. for i := 0; i < b.N; i++ {
  172. out, _ = aead.Open(out[:0], nonce[:], ct[:], ad[:])
  173. }
  174. }
  175. func BenchmarkChacha20Poly1305(b *testing.B) {
  176. for _, length := range []int{64, 1350, 8 * 1024} {
  177. b.Run("Open-"+strconv.Itoa(length), func(b *testing.B) {
  178. benchamarkChaCha20Poly1305Open(b, make([]byte, length), NonceSize)
  179. })
  180. b.Run("Seal-"+strconv.Itoa(length), func(b *testing.B) {
  181. benchamarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSize)
  182. })
  183. b.Run("Open-"+strconv.Itoa(length)+"-X", func(b *testing.B) {
  184. benchamarkChaCha20Poly1305Open(b, make([]byte, length), NonceSizeX)
  185. })
  186. b.Run("Seal-"+strconv.Itoa(length)+"-X", func(b *testing.B) {
  187. benchamarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSizeX)
  188. })
  189. }
  190. }