You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

173 lines
4.6 KiB

  1. // Copyright 2017 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 auth
  5. import (
  6. "bytes"
  7. rand "crypto/rand"
  8. mrand "math/rand"
  9. "testing"
  10. )
  11. // Test cases are from RFC 4231, and match those present in the tests directory
  12. // of the download here: https://nacl.cr.yp.to/install.html
  13. var testCases = []struct {
  14. key [32]byte
  15. msg []byte
  16. out [32]byte
  17. }{
  18. {
  19. key: [32]byte{
  20. 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
  21. 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
  22. 0x0b, 0x0b, 0x0b, 0x0b,
  23. },
  24. msg: []byte("Hi There"),
  25. out: [32]byte{
  26. 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
  27. 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
  28. 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
  29. 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
  30. },
  31. },
  32. {
  33. key: [32]byte{'J', 'e', 'f', 'e'},
  34. msg: []byte("what do ya want for nothing?"),
  35. out: [32]byte{
  36. 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
  37. 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
  38. 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
  39. 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
  40. },
  41. },
  42. {
  43. key: [32]byte{
  44. 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
  45. 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
  46. 0xaa, 0xaa, 0xaa, 0xaa,
  47. },
  48. msg: []byte{ // 50 bytes of 0xdd
  49. 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
  50. 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
  51. 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
  52. 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
  53. 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
  54. 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
  55. 0xdd, 0xdd,
  56. },
  57. out: [32]byte{
  58. 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84,
  59. 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9,
  60. 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36,
  61. 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39,
  62. },
  63. },
  64. {
  65. key: [32]byte{
  66. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  67. 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
  68. 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
  69. 0x19,
  70. },
  71. msg: []byte{
  72. 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
  73. 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
  74. 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
  75. 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
  76. 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
  77. 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
  78. 0xcd, 0xcd,
  79. },
  80. out: [32]byte{
  81. 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69,
  82. 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7,
  83. 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d,
  84. 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb,
  85. },
  86. },
  87. }
  88. func TestSum(t *testing.T) {
  89. for i, test := range testCases {
  90. tag := Sum(test.msg, &test.key)
  91. if !bytes.Equal(tag[:], test.out[:]) {
  92. t.Errorf("#%d: Sum: got\n%x\nwant\n%x", i, tag, test.out)
  93. }
  94. }
  95. }
  96. func TestVerify(t *testing.T) {
  97. wrongMsg := []byte("unknown msg")
  98. for i, test := range testCases {
  99. if !Verify(test.out[:], test.msg, &test.key) {
  100. t.Errorf("#%d: Verify(%x, %q, %x) failed", i, test.out, test.msg, test.key)
  101. }
  102. if Verify(test.out[:], wrongMsg, &test.key) {
  103. t.Errorf("#%d: Verify(%x, %q, %x) unexpectedly passed", i, test.out, wrongMsg, test.key)
  104. }
  105. }
  106. }
  107. func TestStress(t *testing.T) {
  108. if testing.Short() {
  109. t.Skip("exhaustiveness test")
  110. }
  111. var key [32]byte
  112. msg := make([]byte, 10000)
  113. prng := mrand.New(mrand.NewSource(0))
  114. // copied from tests/auth5.c in nacl
  115. for i := 0; i < 10000; i++ {
  116. if _, err := rand.Read(key[:]); err != nil {
  117. t.Fatal(err)
  118. }
  119. if _, err := rand.Read(msg[:i]); err != nil {
  120. t.Fatal(err)
  121. }
  122. tag := Sum(msg[:i], &key)
  123. if !Verify(tag[:], msg[:i], &key) {
  124. t.Errorf("#%d: unexpected failure from Verify", i)
  125. }
  126. if i > 0 {
  127. msgIndex := prng.Intn(i)
  128. oldMsgByte := msg[msgIndex]
  129. msg[msgIndex] += byte(1 + prng.Intn(255))
  130. if Verify(tag[:], msg[:i], &key) {
  131. t.Errorf("#%d: unexpected success from Verify after corrupting message", i)
  132. }
  133. msg[msgIndex] = oldMsgByte
  134. tag[prng.Intn(len(tag))] += byte(1 + prng.Intn(255))
  135. if Verify(tag[:], msg[:i], &key) {
  136. t.Errorf("#%d: unexpected success from Verify after corrupting authenticator", i)
  137. }
  138. }
  139. }
  140. }
  141. func BenchmarkAuth(b *testing.B) {
  142. var key [32]byte
  143. if _, err := rand.Read(key[:]); err != nil {
  144. b.Fatal(err)
  145. }
  146. buf := make([]byte, 1024)
  147. if _, err := rand.Read(buf[:]); err != nil {
  148. b.Fatal(err)
  149. }
  150. b.SetBytes(int64(len(buf)))
  151. b.ReportAllocs()
  152. b.ResetTimer()
  153. for i := 0; i < b.N; i++ {
  154. tag := Sum(buf, &key)
  155. if Verify(tag[:], buf, &key) == false {
  156. b.Fatal("unexpected failure from Verify")
  157. }
  158. }
  159. }