gitlab.com/yawning/chacha20.git@v0.0.0-20230427033715-7877545b1b37/chacha20_test.go (about) 1 // Copryright (C) 2019 Yawning Angel 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package chacha20 17 18 import ( 19 "crypto/rand" 20 "crypto/sha512" 21 "math" 22 "strconv" 23 "testing" 24 25 "github.com/stretchr/testify/require" 26 27 "gitlab.com/yawning/chacha20.git/internal/api" 28 ) 29 30 // Test vectors taken from: 31 // https://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-01 32 var draftTestVectors = []struct { 33 name string 34 key []byte 35 iv []byte 36 stream []byte 37 seekOffset uint64 38 }{ 39 { 40 name: "IETF Draft: TC1: All zero key and IV.", 41 key: []byte{ 42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 46 }, 47 iv: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 48 stream: []byte{ 49 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 50 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, 51 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 52 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, 53 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, 54 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, 55 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, 56 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86, 57 0x9f, 0x07, 0xe7, 0xbe, 0x55, 0x51, 0x38, 0x7a, 58 0x98, 0xba, 0x97, 0x7c, 0x73, 0x2d, 0x08, 0x0d, 59 0xcb, 0x0f, 0x29, 0xa0, 0x48, 0xe3, 0x65, 0x69, 60 0x12, 0xc6, 0x53, 0x3e, 0x32, 0xee, 0x7a, 0xed, 61 0x29, 0xb7, 0x21, 0x76, 0x9c, 0xe6, 0x4e, 0x43, 62 0xd5, 0x71, 0x33, 0xb0, 0x74, 0xd8, 0x39, 0xd5, 63 0x31, 0xed, 0x1f, 0x28, 0x51, 0x0a, 0xfb, 0x45, 64 0xac, 0xe1, 0x0a, 0x1f, 0x4b, 0x79, 0x4d, 0x6f, 65 }, 66 }, 67 { 68 name: "IETF Draft: TC2: Single bit in key set. All zero IV.", 69 key: []byte{ 70 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 }, 75 iv: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 76 stream: []byte{ 77 0xc5, 0xd3, 0x0a, 0x7c, 0xe1, 0xec, 0x11, 0x93, 78 0x78, 0xc8, 0x4f, 0x48, 0x7d, 0x77, 0x5a, 0x85, 79 0x42, 0xf1, 0x3e, 0xce, 0x23, 0x8a, 0x94, 0x55, 80 0xe8, 0x22, 0x9e, 0x88, 0x8d, 0xe8, 0x5b, 0xbd, 81 0x29, 0xeb, 0x63, 0xd0, 0xa1, 0x7a, 0x5b, 0x99, 82 0x9b, 0x52, 0xda, 0x22, 0xbe, 0x40, 0x23, 0xeb, 83 0x07, 0x62, 0x0a, 0x54, 0xf6, 0xfa, 0x6a, 0xd8, 84 0x73, 0x7b, 0x71, 0xeb, 0x04, 0x64, 0xda, 0xc0, 85 0x10, 0xf6, 0x56, 0xe6, 0xd1, 0xfd, 0x55, 0x05, 86 0x3e, 0x50, 0xc4, 0x87, 0x5c, 0x99, 0x30, 0xa3, 87 0x3f, 0x6d, 0x02, 0x63, 0xbd, 0x14, 0xdf, 0xd6, 88 0xab, 0x8c, 0x70, 0x52, 0x1c, 0x19, 0x33, 0x8b, 89 0x23, 0x08, 0xb9, 0x5c, 0xf8, 0xd0, 0xbb, 0x7d, 90 0x20, 0x2d, 0x21, 0x02, 0x78, 0x0e, 0xa3, 0x52, 91 0x8f, 0x1c, 0xb4, 0x85, 0x60, 0xf7, 0x6b, 0x20, 92 0xf3, 0x82, 0xb9, 0x42, 0x50, 0x0f, 0xce, 0xac, 93 }, 94 }, 95 { 96 name: "IETF Draft: TC3: Single bit in IV set. All zero key.", 97 key: []byte{ 98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 102 }, 103 iv: []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 104 stream: []byte{ 105 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb, 106 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80, 107 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac, 108 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32, 109 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c, 110 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54, 111 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d, 112 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b, 113 0x53, 0x05, 0xe5, 0xe4, 0x4a, 0xff, 0x19, 0xb2, 114 0x35, 0x93, 0x61, 0x44, 0x67, 0x5e, 0xfb, 0xe4, 115 0x40, 0x9e, 0xb7, 0xe8, 0xe5, 0xf1, 0x43, 0x0f, 116 0x5f, 0x58, 0x36, 0xae, 0xb4, 0x9b, 0xb5, 0x32, 117 0x8b, 0x01, 0x7c, 0x4b, 0x9d, 0xc1, 0x1f, 0x8a, 118 0x03, 0x86, 0x3f, 0xa8, 0x03, 0xdc, 0x71, 0xd5, 119 0x72, 0x6b, 0x2b, 0x6b, 0x31, 0xaa, 0x32, 0x70, 120 0x8a, 0xfe, 0x5a, 0xf1, 0xd6, 0xb6, 0x90, 0x58, 121 }, 122 }, 123 { 124 name: "IETF Draft: TC4: All bits in key and IV are set.", 125 key: []byte{ 126 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 127 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 130 }, 131 iv: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 132 stream: []byte{ 133 0xd9, 0xbf, 0x3f, 0x6b, 0xce, 0x6e, 0xd0, 0xb5, 134 0x42, 0x54, 0x55, 0x77, 0x67, 0xfb, 0x57, 0x44, 135 0x3d, 0xd4, 0x77, 0x89, 0x11, 0xb6, 0x06, 0x05, 136 0x5c, 0x39, 0xcc, 0x25, 0xe6, 0x74, 0xb8, 0x36, 137 0x3f, 0xea, 0xbc, 0x57, 0xfd, 0xe5, 0x4f, 0x79, 138 0x0c, 0x52, 0xc8, 0xae, 0x43, 0x24, 0x0b, 0x79, 139 0xd4, 0x90, 0x42, 0xb7, 0x77, 0xbf, 0xd6, 0xcb, 140 0x80, 0xe9, 0x31, 0x27, 0x0b, 0x7f, 0x50, 0xeb, 141 0x5b, 0xac, 0x2a, 0xcd, 0x86, 0xa8, 0x36, 0xc5, 142 0xdc, 0x98, 0xc1, 0x16, 0xc1, 0x21, 0x7e, 0xc3, 143 0x1d, 0x3a, 0x63, 0xa9, 0x45, 0x13, 0x19, 0xf0, 144 0x97, 0xf3, 0xb4, 0xd6, 0xda, 0xb0, 0x77, 0x87, 145 0x19, 0x47, 0x7d, 0x24, 0xd2, 0x4b, 0x40, 0x3a, 146 0x12, 0x24, 0x1d, 0x7c, 0xca, 0x06, 0x4f, 0x79, 147 0x0f, 0x1d, 0x51, 0xcc, 0xaf, 0xf6, 0xb1, 0x66, 148 0x7d, 0x4b, 0xbc, 0xa1, 0x95, 0x8c, 0x43, 0x06, 149 }, 150 }, 151 { 152 name: "IETF Draft: TC5: Every even bit set in key and IV.", 153 key: []byte{ 154 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 155 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 156 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 157 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 158 }, 159 iv: []byte{0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}, 160 stream: []byte{ 161 0xbe, 0xa9, 0x41, 0x1a, 0xa4, 0x53, 0xc5, 0x43, 162 0x4a, 0x5a, 0xe8, 0xc9, 0x28, 0x62, 0xf5, 0x64, 163 0x39, 0x68, 0x55, 0xa9, 0xea, 0x6e, 0x22, 0xd6, 164 0xd3, 0xb5, 0x0a, 0xe1, 0xb3, 0x66, 0x33, 0x11, 165 0xa4, 0xa3, 0x60, 0x6c, 0x67, 0x1d, 0x60, 0x5c, 166 0xe1, 0x6c, 0x3a, 0xec, 0xe8, 0xe6, 0x1e, 0xa1, 167 0x45, 0xc5, 0x97, 0x75, 0x01, 0x7b, 0xee, 0x2f, 168 0xa6, 0xf8, 0x8a, 0xfc, 0x75, 0x80, 0x69, 0xf7, 169 0xe0, 0xb8, 0xf6, 0x76, 0xe6, 0x44, 0x21, 0x6f, 170 0x4d, 0x2a, 0x34, 0x22, 0xd7, 0xfa, 0x36, 0xc6, 171 0xc4, 0x93, 0x1a, 0xca, 0x95, 0x0e, 0x9d, 0xa4, 172 0x27, 0x88, 0xe6, 0xd0, 0xb6, 0xd1, 0xcd, 0x83, 173 0x8e, 0xf6, 0x52, 0xe9, 0x7b, 0x14, 0x5b, 0x14, 174 0x87, 0x1e, 0xae, 0x6c, 0x68, 0x04, 0xc7, 0x00, 175 0x4d, 0xb5, 0xac, 0x2f, 0xce, 0x4c, 0x68, 0xc7, 176 0x26, 0xd0, 0x04, 0xb1, 0x0f, 0xca, 0xba, 0x86, 177 }, 178 }, 179 { 180 name: "IETF Draft: TC6: Every odd bit set in key and IV.", 181 key: []byte{ 182 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 183 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 184 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 185 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 186 }, 187 iv: []byte{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 188 stream: []byte{ 189 0x9a, 0xa2, 0xa9, 0xf6, 0x56, 0xef, 0xde, 0x5a, 190 0xa7, 0x59, 0x1c, 0x5f, 0xed, 0x4b, 0x35, 0xae, 191 0xa2, 0x89, 0x5d, 0xec, 0x7c, 0xb4, 0x54, 0x3b, 192 0x9e, 0x9f, 0x21, 0xf5, 0xe7, 0xbc, 0xbc, 0xf3, 193 0xc4, 0x3c, 0x74, 0x8a, 0x97, 0x08, 0x88, 0xf8, 194 0x24, 0x83, 0x93, 0xa0, 0x9d, 0x43, 0xe0, 0xb7, 195 0xe1, 0x64, 0xbc, 0x4d, 0x0b, 0x0f, 0xb2, 0x40, 196 0xa2, 0xd7, 0x21, 0x15, 0xc4, 0x80, 0x89, 0x06, 197 0x72, 0x18, 0x44, 0x89, 0x44, 0x05, 0x45, 0xd0, 198 0x21, 0xd9, 0x7e, 0xf6, 0xb6, 0x93, 0xdf, 0xe5, 199 0xb2, 0xc1, 0x32, 0xd4, 0x7e, 0x6f, 0x04, 0x1c, 200 0x90, 0x63, 0x65, 0x1f, 0x96, 0xb6, 0x23, 0xe6, 201 0x2a, 0x11, 0x99, 0x9a, 0x23, 0xb6, 0xf7, 0xc4, 202 0x61, 0xb2, 0x15, 0x30, 0x26, 0xad, 0x5e, 0x86, 203 0x6a, 0x2e, 0x59, 0x7e, 0xd0, 0x7b, 0x84, 0x01, 204 0xde, 0xc6, 0x3a, 0x09, 0x34, 0xc6, 0xb2, 0xa9, 205 }, 206 }, 207 { 208 name: "IETF Draft: TC7: Sequence patterns in key and IV.", 209 key: []byte{ 210 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 211 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 212 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 213 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 214 }, 215 iv: []byte{0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78}, 216 stream: []byte{ 217 0x9f, 0xad, 0xf4, 0x09, 0xc0, 0x08, 0x11, 0xd0, 218 0x04, 0x31, 0xd6, 0x7e, 0xfb, 0xd8, 0x8f, 0xba, 219 0x59, 0x21, 0x8d, 0x5d, 0x67, 0x08, 0xb1, 0xd6, 220 0x85, 0x86, 0x3f, 0xab, 0xbb, 0x0e, 0x96, 0x1e, 221 0xea, 0x48, 0x0f, 0xd6, 0xfb, 0x53, 0x2b, 0xfd, 222 0x49, 0x4b, 0x21, 0x51, 0x01, 0x50, 0x57, 0x42, 223 0x3a, 0xb6, 0x0a, 0x63, 0xfe, 0x4f, 0x55, 0xf7, 224 0xa2, 0x12, 0xe2, 0x16, 0x7c, 0xca, 0xb9, 0x31, 225 0xfb, 0xfd, 0x29, 0xcf, 0x7b, 0xc1, 0xd2, 0x79, 226 0xed, 0xdf, 0x25, 0xdd, 0x31, 0x6b, 0xb8, 0x84, 227 0x3d, 0x6e, 0xde, 0xe0, 0xbd, 0x1e, 0xf1, 0x21, 228 0xd1, 0x2f, 0xa1, 0x7c, 0xbc, 0x2c, 0x57, 0x4c, 229 0xcc, 0xab, 0x5e, 0x27, 0x51, 0x67, 0xb0, 0x8b, 230 0xd6, 0x86, 0xf8, 0xa0, 0x9d, 0xf8, 0x7e, 0xc3, 231 0xff, 0xb3, 0x53, 0x61, 0xb9, 0x4e, 0xbf, 0xa1, 232 0x3f, 0xec, 0x0e, 0x48, 0x89, 0xd1, 0x8d, 0xa5, 233 }, 234 }, 235 { 236 name: "IETF Draft: TC8: key: 'All your base are belong to us!, IV: 'IETF2013'", 237 key: []byte{ 238 0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78, 239 0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35, 240 0x1f, 0x68, 0xed, 0x2e, 0x19, 0x4c, 0x79, 0xfb, 241 0xc6, 0xae, 0xbe, 0xe1, 0xa6, 0x67, 0x97, 0x5d, 242 }, 243 iv: []byte{0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21}, 244 stream: []byte{ 245 0xf6, 0x3a, 0x89, 0xb7, 0x5c, 0x22, 0x71, 0xf9, 246 0x36, 0x88, 0x16, 0x54, 0x2b, 0xa5, 0x2f, 0x06, 247 0xed, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2b, 0x00, 248 0xb5, 0xe8, 0xf8, 0x0a, 0xe9, 0xa4, 0x73, 0xaf, 249 0xc2, 0x5b, 0x21, 0x8f, 0x51, 0x9a, 0xf0, 0xfd, 250 0xd4, 0x06, 0x36, 0x2e, 0x8d, 0x69, 0xde, 0x7f, 251 0x54, 0xc6, 0x04, 0xa6, 0xe0, 0x0f, 0x35, 0x3f, 252 0x11, 0x0f, 0x77, 0x1b, 0xdc, 0xa8, 0xab, 0x92, 253 0xe5, 0xfb, 0xc3, 0x4e, 0x60, 0xa1, 0xd9, 0xa9, 254 0xdb, 0x17, 0x34, 0x5b, 0x0a, 0x40, 0x27, 0x36, 255 0x85, 0x3b, 0xf9, 0x10, 0xb0, 0x60, 0xbd, 0xf1, 256 0xf8, 0x97, 0xb6, 0x29, 0x0f, 0x01, 0xd1, 0x38, 257 0xae, 0x2c, 0x4c, 0x90, 0x22, 0x5b, 0xa9, 0xea, 258 0x14, 0xd5, 0x18, 0xf5, 0x59, 0x29, 0xde, 0xa0, 259 0x98, 0xca, 0x7a, 0x6c, 0xcf, 0xe6, 0x12, 0x27, 260 0x05, 0x3c, 0x84, 0xe4, 0x9a, 0x4a, 0x33, 0x32, 261 }, 262 }, 263 { 264 name: "XChaCha20 Test", 265 key: []byte{ 266 0x54, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70, 267 0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 268 0x68, 0x65, 0x20, 0x70, 0x69, 0x73, 0x74, 0x6f, 269 0x6c, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 270 }, 271 iv: []byte{ 272 0x73, 0x74, 0x6f, 0x70, 0x20, 0x61, 0x20, 0x66, 273 0x69, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x61, 274 0x74, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x62, 0x6f, 275 }, 276 stream: []byte{ 277 0xfa, 0x27, 0xe8, 0x54, 0xba, 0x9f, 0x74, 0xf0, 278 0x7f, 0xa3, 0x85, 0x03, 0x65, 0x1b, 0xc9, 0xbf, 279 0xe8, 0x80, 0xed, 0x2b, 0xf7, 0x20, 0xed, 0xc5, 280 0xb4, 0x82, 0xc9, 0xea, 0x95, 0x32, 0x59, 0x20, 281 0xb9, 0xf5, 0x86, 0x93, 0xf1, 0xf7, 0xa6, 0x67, 282 0x4e, 0xc4, 0xf3, 0xfa, 0x93, 0x14, 0x4d, 0xe2, 283 0xe9, 0x6d, 0x0d, 0x4a, 0xe7, 0x70, 0x32, 0xae, 284 0x88, 0xb7, 0x58, 0x3b, 0xd5, 0x5f, 0x16, 0xa6, 285 0xd5, 0x0e, 0x8d, 0x53, 0x0c, 0x60, 0x8e, 0x41, 286 0x5c, 0xda, 0x0c, 0xe9, 0xc7, 0xde, 0xc6, 0x71, 287 0x9d, 0x8a, 0xe5, 0xcb, 0xde, 0x45, 0x5b, 0x98, 288 0xf6, 0x57, 0xca, 0x9d, 0xd1, 0xa1, 0xe3, 0x5c, 289 0x01, 0xe6, 0x29, 0x38, 0x9e, 0xf5, 0x97, 0x38, 290 0x75, 0x61, 0x0e, 0x71, 0xfc, 0xd1, 0xa1, 0x11, 291 0x29, 0x47, 0x37, 0x6b, 0xac, 0x09, 0xd6, 0xee, 292 0xf7, 0x61, 0x62, 0x24, 0x00, 0x58, 0xac, 0x1d, 293 0xcf, 0x42, 0xef, 0x50, 0xfa, 0x54, 0x14, 0x49, 294 0x31, 0xd2, 0x62, 295 }, 296 }, 297 { 298 name: "RFC 7539 Test Vector (96 bit nonce)", 299 key: []byte{ 300 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 301 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 302 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 303 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 304 }, 305 iv: []byte{ 306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 307 0x00, 0x00, 0x00, 0x00, 308 }, 309 stream: []byte{ 310 0x22, 0x4f, 0x51, 0xf3, 0x40, 0x1b, 0xd9, 0xe1, 311 0x2f, 0xde, 0x27, 0x6f, 0xb8, 0x63, 0x1d, 0xed, 312 0x8c, 0x13, 0x1f, 0x82, 0x3d, 0x2c, 0x06, 0xe2, 313 0x7e, 0x4f, 0xca, 0xec, 0x9e, 0xf3, 0xcf, 0x78, 314 0x8a, 0x3b, 0x0a, 0xa3, 0x72, 0x60, 0x0a, 0x92, 315 0xb5, 0x79, 0x74, 0xcd, 0xed, 0x2b, 0x93, 0x34, 316 0x79, 0x4c, 0xba, 0x40, 0xc6, 0x3e, 0x34, 0xcd, 317 0xea, 0x21, 0x2c, 0x4c, 0xf0, 0x7d, 0x41, 0xb7, 318 0x69, 0xa6, 0x74, 0x9f, 0x3f, 0x63, 0x0f, 0x41, 319 0x22, 0xca, 0xfe, 0x28, 0xec, 0x4d, 0xc4, 0x7e, 320 0x26, 0xd4, 0x34, 0x6d, 0x70, 0xb9, 0x8c, 0x73, 321 0xf3, 0xe9, 0xc5, 0x3a, 0xc4, 0x0c, 0x59, 0x45, 322 0x39, 0x8b, 0x6e, 0xda, 0x1a, 0x83, 0x2c, 0x89, 323 0xc1, 0x67, 0xea, 0xcd, 0x90, 0x1d, 0x7e, 0x2b, 324 0xf3, 0x63, 325 }, 326 seekOffset: 1, 327 }, 328 } 329 330 func TestChaCha20(t *testing.T) { 331 for _, v := range supportedImpls { 332 testWithImpl := func(t *testing.T, impl api.Implementation) { 333 oldImpl := activeImpl 334 defer func() { 335 activeImpl = oldImpl 336 }() 337 338 activeImpl = impl 339 340 t.Run("Basic", doTestBasic) 341 t.Run("TestVectors", doTestVectors) 342 } 343 344 t.Run(v.Name(), func(t *testing.T) { 345 testWithImpl(t, v) 346 }) 347 } 348 } 349 350 func doTestBasic(t *testing.T) { 351 t.Run("RoundTrip", doTestBasicRoundTrip) 352 t.Run("Counter", doTestBasicCounter) 353 t.Run("IETFCounter", doTestBasicIETFCounter) 354 t.Run("Incremental", doTestBasicIncremental) 355 } 356 357 func doTestBasicRoundTrip(t *testing.T) { 358 require := require.New(t) 359 360 var ( 361 key [KeySize]byte 362 nonce [NonceSize]byte 363 ) 364 365 c, err := New(key[:], nonce[:]) 366 require.NoError(err, "New") 367 368 plaintext := []byte("The smallest minority on earth is the individual. Those who deny individual rights cannot claim to be defenders of minorities.") 369 ciphertext := make([]byte, len(plaintext)) 370 c.XORKeyStream(ciphertext, plaintext) 371 372 require.NotEqual(plaintext, ciphertext, "XORKeyStream - output") 373 374 err = c.Seek(0) 375 require.NoError(err, "Seek") 376 c.XORKeyStream(ciphertext, ciphertext) 377 378 require.Equal(plaintext, ciphertext, "XORKeyStream - round trip output") 379 } 380 381 func doTestBasicCounter(t *testing.T) { 382 require := require.New(t) 383 384 var ( 385 key [KeySize]byte 386 nonce [NonceSize]byte 387 388 block, block2 [api.BlockSize]byte 389 ) 390 391 c, err := New(key[:], nonce[:]) 392 require.NoError(err, "New") 393 394 c.KeyStream(block[:]) // Block: 0 395 396 err = c.Seek(math.MaxUint32 + 1) 397 require.NoError(err, "Seek") 398 c.KeyStream(block2[:]) // Block: 0x100000000 399 400 require.NotEqual(block, block2, "KeyStream - 32 bit counter would wrap") 401 } 402 403 func doTestBasicIETFCounter(t *testing.T) { 404 require := require.New(t) 405 406 var ( 407 key [KeySize]byte 408 nonce [INonceSize]byte 409 410 block [api.BlockSize]byte 411 ) 412 413 c, err := New(key[:], nonce[:]) 414 require.NoError(err, "New") 415 416 err = c.Seek(math.MaxUint32 - 1) 417 require.NoError(err, "Seek") 418 c.KeyStream(block[:]) 419 420 require.Panics(func() { 421 c.KeyStream(block[:]) 422 }, "KeyStream - counter would wrap") 423 } 424 425 func doTestBasicIncremental(t *testing.T) { 426 require := require.New(t) 427 428 var ( 429 key [KeySize]byte 430 nonce [NonceSize]byte 431 432 buf [2048]byte 433 434 expectedDigest = []byte{ 435 0xcf, 0xd6, 0xe9, 0x49, 0x22, 0x5b, 0x85, 0x4f, 436 0xe0, 0x49, 0x46, 0x49, 0x1e, 0x69, 0x35, 0xff, 437 0x05, 0xff, 0x98, 0x3d, 0x15, 0x54, 0xbc, 0x88, 438 0x5b, 0xca, 0x0e, 0xc8, 0x08, 0x2d, 0xd5, 0xb8, 439 } 440 ) 441 442 c, err := New(key[:], nonce[:]) 443 require.NoError(err, "New") 444 445 h := sha512.New512_256() 446 for i := 1; i <= 2048; i++ { 447 c.KeyStream(buf[:i]) 448 _, _ = h.Write(buf[:i]) 449 } 450 451 digest := h.Sum(nil) 452 453 require.Equal(expectedDigest, digest, "KeyStream digest matches") 454 } 455 456 func doTestVectors(t *testing.T) { 457 for _, v := range draftTestVectors { 458 t.Run(v.name, func(t *testing.T) { 459 require := require.New(t) 460 c, err := New(v.key, v.iv) 461 require.NoError(err, "New") 462 463 if v.seekOffset != 0 { 464 err = c.Seek(v.seekOffset) 465 require.NoErrorf(err, "Seek(%d)", v.seekOffset) 466 } 467 468 out := make([]byte, len(v.stream)) 469 c.XORKeyStream(out, out) 470 require.EqualValues(v.stream, out, "XORKeyStream") 471 472 // Ensure that KeyStream tramples over dst. 473 _, err = rand.Read(out) 474 require.NoError(err, "rand.Read") 475 476 err = c.Seek(v.seekOffset) 477 require.NoErrorf(err, "Seek(%d) - resetting", v.seekOffset) 478 c.KeyStream(out) 479 require.EqualValues(v.stream, out, "KeyStream") 480 }) 481 } 482 } 483 484 func BenchmarkChaCha20(b *testing.B) { 485 for _, v := range supportedImpls { 486 benchWithImpl := func(b *testing.B, impl api.Implementation) { 487 oldImpl := activeImpl 488 defer func() { 489 activeImpl = oldImpl 490 }() 491 492 activeImpl = impl 493 for _, vv := range []int{ 494 1, 8, 32, 64, 576, 1536, 4096, 1024768, 495 } { 496 b.Run(strconv.Itoa(vv), func(b *testing.B) { 497 doBenchN(b, vv) 498 }) 499 } 500 } 501 502 b.Run(v.Name(), func(b *testing.B) { 503 benchWithImpl(b, v) 504 }) 505 } 506 } 507 508 func doBenchN(b *testing.B, n int) { 509 var ( 510 key [KeySize]byte 511 nonce [NonceSize]byte 512 ) 513 514 s := make([]byte, n) 515 c, err := New(key[:], nonce[:]) 516 if err != nil { 517 b.Fatal(err) 518 } 519 b.SetBytes(int64(n)) 520 521 b.ResetTimer() 522 for i := 0; i < b.N; i++ { 523 c.XORKeyStream(s, s) 524 } 525 }