v / vlib / crypto / blake3 / blake3_chunk_test.v
302 lines · 288 sloc · 9.91 KB · 3954e05455422cfc2ff384c8ac2a22a375c1dab6
Raw
1// Copyright (c) 2023 Kim Shrier. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4// Package blake3 implements the Blake3 cryptographic hash
5// as described in:
6// https://github.com/BLAKE3-team/BLAKE3-specs/blob/master/blake3.pdf
7// Version 20211102173700
8
9module blake3
10
11// build input strings of various lengths
12const fua = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
13const bua = 'ZYXWVUTSRQPONMLKJIHGFEDCBA'
14
15const fla = 'abcdefghijklmnopqrstuvwxyz'
16const bla = 'zyxwvutsrqponmlkjihgfedcba'
17
18const fnr = '0123456789'
19const bnr = '9876543210'
20
21const ll = fua + ' ' + fla + ' ' + fnr + ' ' + bnr + ' ' + bla + ' ' + bua
22
23const lb = ll + '\n' + ll + '\n' + ll + '\n' + ll + '\n' + ll + '\n' + ll + '\n' + ll + '\n' + ll
24
25struct TestInput {
26 input_string string
27 key_words []u32
28 chunk_number u64
29 flags u32
30}
31
32struct TestCase {
33 input TestInput // inputs to the chunk's process_input method
34 results Chunk // the resulting chunk
35 words []u32 // the final output state as 32-bit words
36}
37
38// Chunk structures after processing varying amounts of input
39//
40// The expected values were derived from instrumenting the C reference
41// implementation and dumping the appropriate values from their variables
42// when processing the same input as the test case.
43const test_cases = [
44 // chunk 0 with 0 bytes input
45 TestCase{
46 input: TestInput{
47 input_string: ''
48 key_words: iv
49 chunk_number: 0
50 flags: 0
51 }
52 results: Chunk{
53 chunk_number: 0
54 chaining_value: iv.clone()
55 block_words: [u32(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
56 flags: 0x0b
57 }
58 words: [u32(0xb94913af), 0xa6a1f9f5, 0xea4d40a0, 0x49c9dc36, 0xc925cb9b, 0xb712c1ad,
59 0xca939acc, 0x62321fe4, 0xe7030fe0, 0x6bf29ab6, 0x9ff0aa7f, 0x503033cd, 0xe0df8d33,
60 0x86ccb885, 0x208ba99c, 0x3a24086c]
61 },
62 // chunk 0 with 1 byte input
63 TestCase{
64 input: TestInput{
65 input_string: 'A'
66 key_words: iv
67 chunk_number: 0
68 flags: 0
69 }
70 results: Chunk{
71 chunk_number: 0
72 chaining_value: iv.clone()
73 block_words: [u32(0x00000041), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
74 flags: 0x0b
75 }
76 words: [u32(0xfa4b6832), 0x4dc8c028, 0x1105216f, 0xfc0eceaa, 0x88c77151, 0x89ba4891,
77 0xa25a8d20, 0x98fa0597, 0x4c0088e3, 0xafa7cbb8, 0xc586c5f7, 0x66dbef0e, 0x8c91d56a,
78 0xa0b3daff, 0xe919be05, 0x997a1ce7]
79 },
80 // chunk 0 with 3 bytes input
81 TestCase{
82 input: TestInput{
83 input_string: 'abc'
84 key_words: iv
85 chunk_number: 0
86 flags: 0
87 }
88 results: Chunk{
89 chunk_number: 0
90 chaining_value: iv.clone()
91 block_words: [u32(0x00636261), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
92 flags: 0x0b
93 }
94 words: [u32(0xacb33764), 0x33514638, 0x753bb6ff, 0xb58d3a27, 0x4658c548, 0x03db795d,
95 0x6c9c35fd, 0x859dbdd5, 0xae50b21f, 0xd0f59373, 0x5db61328, 0x490d1a52, 0x9ca09b2d,
96 0x4c7fcef7, 0xf200d9ff, 0x0bbf7433]
97 },
98 // chunk 0 with 63 bytes input
99 TestCase{
100 input: TestInput{
101 input_string: ll[..63]
102 key_words: iv
103 chunk_number: 0
104 flags: 0
105 }
106 results: Chunk{
107 chunk_number: 0
108 chaining_value: iv.clone()
109 block_words: [u32(0x44434241), 0x48474645, 0x4c4b4a49, 0x504f4e4d, 0x54535251,
110 0x58575655, 0x61205a59, 0x65646362, 0x69686766, 0x6d6c6b6a, 0x71706f6e, 0x75747372,
111 0x79787776, 0x3130207a, 0x35343332, 0x00383736]
112 flags: 0x0b
113 }
114 words: [u32(0x39c41fc6), 0x2dd7c57b, 0xb8b16421, 0x360cbedb, 0x462d5672, 0x56713bb5,
115 0x15132543, 0x7a92c4ba, 0x15c4ac13, 0x2354f573, 0xdc14f100, 0x35be07e8, 0xf98b17b9,
116 0x573f38f8, 0xc8d2fbf4, 0xc06588e5]
117 },
118 // chunk 0 with 64 bytes input
119 TestCase{
120 input: TestInput{
121 input_string: ll[..64]
122 key_words: iv
123 chunk_number: 0
124 flags: 0
125 }
126 results: Chunk{
127 chunk_number: 0
128 chaining_value: iv.clone()
129 block_words: [u32(0x44434241), 0x48474645, 0x4c4b4a49, 0x504f4e4d, 0x54535251,
130 0x58575655, 0x61205a59, 0x65646362, 0x69686766, 0x6d6c6b6a, 0x71706f6e, 0x75747372,
131 0x79787776, 0x3130207a, 0x35343332, 0x39383736]
132 flags: 0x0b
133 }
134 words: [u32(0x6010817a), 0x21deb495, 0x0826485b, 0x6f895da5, 0x9363242a, 0x176b60a9,
135 0x383215a7, 0x2b95570f, 0x57fe7082, 0x45b13a10, 0x007af189, 0x4b5e7ec7, 0x9574b5d8,
136 0x109362a0, 0x282d14c2, 0x3a134380]
137 },
138 // chunk 0 with 65 bytes input
139 TestCase{
140 input: TestInput{
141 input_string: ll[..65]
142 key_words: iv
143 chunk_number: 0
144 flags: 0
145 }
146 results: Chunk{
147 chunk_number: 0
148 chaining_value: [u32(0xbb99f549), 0x3b4b2903, 0x436d199e, 0x6eea5980, 0x82ebb968,
149 0x33cc3c4a, 0x90f4944b, 0x9480e10a]
150 block_words: [u32(0x00000020), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
151 flags: 0x0a
152 }
153 words: [u32(0xb06cf0f5), 0xd6f8f23d, 0x0f06389e, 0x20dec0a4, 0x69a20569, 0xdbbb4453,
154 0x09f0bb52, 0xe22c6707, 0x6b530f62, 0x9ac8bfbd, 0xc0aa57b0, 0xdb30223c, 0xd6e52c79,
155 0x42d84d38, 0xcfb4105f, 0xb42f1bd3]
156 },
157 // chunk 0 with 127 bytes input
158 TestCase{
159 input: TestInput{
160 input_string: ll[..127]
161 key_words: iv
162 chunk_number: 0
163 flags: 0
164 }
165 results: Chunk{
166 chunk_number: 0
167 chaining_value: [u32(0xbb99f549), 0x3b4b2903, 0x436d199e, 0x6eea5980, 0x82ebb968,
168 0x33cc3c4a, 0x90f4944b, 0x9480e10a]
169 block_words: [u32(0x37383920), 0x33343536, 0x20303132, 0x7778797a, 0x73747576,
170 0x6f707172, 0x6b6c6d6e, 0x6768696a, 0x63646566, 0x5a206162, 0x56575859, 0x52535455,
171 0x4e4f5051, 0x4a4b4c4d, 0x46474849, 0x00434445]
172 flags: 0x0a
173 }
174 words: [u32(0x589a304d), 0x49f8a607, 0x55a03867, 0xe4fec410, 0x1a6bb2f6, 0x11dfecb3,
175 0xf9989552, 0xb2d18382, 0x9fc6329a, 0xcc93199f, 0x5431cfc5, 0x1f5bddc6, 0x1d039fc5,
176 0x09af900e, 0x55ce0ba2, 0x9707b1e6]
177 },
178 // chunk 0 with 128 bytes input
179 TestCase{
180 input: TestInput{
181 input_string: ll[..128]
182 key_words: iv
183 chunk_number: 0
184 flags: 0
185 }
186 results: Chunk{
187 chunk_number: 0
188 chaining_value: [u32(0xbb99f549), 0x3b4b2903, 0x436d199e, 0x6eea5980, 0x82ebb968,
189 0x33cc3c4a, 0x90f4944b, 0x9480e10a]
190 block_words: [u32(0x37383920), 0x33343536, 0x20303132, 0x7778797a, 0x73747576,
191 0x6f707172, 0x6b6c6d6e, 0x6768696a, 0x63646566, 0x5a206162, 0x56575859, 0x52535455,
192 0x4e4f5051, 0x4a4b4c4d, 0x46474849, 0x42434445]
193 flags: 0x0a
194 }
195 words: [u32(0xd0d12158), 0x8802f9a4, 0x5bd125fb, 0xf2751b9d, 0x8fb2a4d2, 0x27744bfa,
196 0x6ea287b1, 0xae9cfdb2, 0x8e0c2651, 0xeb2cfa50, 0x84654cbf, 0xb97b6f7b, 0xd2d737a2,
197 0x46eaad72, 0x4d0235f0, 0xcaf8abb7]
198 },
199 // chunk 0 with 129 bytes input
200 TestCase{
201 input: TestInput{
202 input_string: ll[..129]
203 key_words: iv
204 chunk_number: 0
205 flags: 0
206 }
207 results: Chunk{
208 chunk_number: 0
209 chaining_value: [u32(0xccf04979), 0x9cbf983e, 0x9e274997, 0xb88c707b, 0x482b00d8,
210 0x7aedc034, 0x1efdc297, 0x4de9f7c5]
211 block_words: [u32(0x00000041), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
212 flags: 0x0a
213 }
214 words: [u32(0xa896b53e), 0x1a64b264, 0xb08c7ea7, 0x09990e6d, 0x30470999, 0x762e9f2c,
215 0xb6c7bf5f, 0x64fd723a, 0x6cb02e2f, 0xa3849bf2, 0xede8ea18, 0x14c88505, 0xfbf2ad67,
216 0x6bc0a779, 0x8e731b77, 0x643a82c6]
217 },
218 // chunk 0 with 1023 bytes input
219 TestCase{
220 input: TestInput{
221 input_string: lb[..1023]
222 key_words: iv
223 chunk_number: 0
224 flags: 0
225 }
226 results: Chunk{
227 chunk_number: 0
228 chaining_value: [u32(0x78fd494b), 0xcd7eeddd, 0x0cb98e9b, 0x7a6a754e, 0x38ff2d32,
229 0x88c4ca4c, 0xbc7baf18, 0xf7684da9]
230 block_words: [u32(0x207a7978), 0x33323130, 0x37363534, 0x39203938, 0x35363738,
231 0x31323334, 0x797a2030, 0x75767778, 0x71727374, 0x6d6e6f70, 0x696a6b6c, 0x65666768,
232 0x61626364, 0x58595a20, 0x54555657, 0x00515253]
233 flags: 0x0a
234 }
235 words: [u32(0x96bcc611), 0x8ccfc351, 0x89ec78f7, 0x2f748832, 0xf75ee10a, 0xc739f876,
236 0x6adddebb, 0xe28853ab, 0x6983883d, 0x1ca0378d, 0x11f4296c, 0x6638ad9a, 0x0c639f8a,
237 0xebf03d1f, 0x2c0e3844, 0x0989b826]
238 },
239 // chunk 0 with 1024 bytes input
240 TestCase{
241 input: TestInput{
242 input_string: lb[..1024]
243 key_words: iv
244 chunk_number: 0
245 flags: 0
246 }
247 results: Chunk{
248 chunk_number: 0
249 chaining_value: [u32(0x78fd494b), 0xcd7eeddd, 0x0cb98e9b, 0x7a6a754e, 0x38ff2d32,
250 0x88c4ca4c, 0xbc7baf18, 0xf7684da9]
251 block_words: [u32(0x207a7978), 0x33323130, 0x37363534, 0x39203938, 0x35363738,
252 0x31323334, 0x797a2030, 0x75767778, 0x71727374, 0x6d6e6f70, 0x696a6b6c, 0x65666768,
253 0x61626364, 0x58595a20, 0x54555657, 0x50515253]
254 flags: 0x0a
255 }
256 words: [u32(0x50dbfcc6), 0x7dd05a7f, 0xa641cc37, 0x11721a4e, 0x6f33eea2, 0x834877a1,
257 0x1cb36c9c, 0xf8d78dce, 0xb7539a0e, 0x7c7b57f4, 0xeef982da, 0x82c6c442, 0x8a451e9b,
258 0xb9cc8414, 0xdef7ad58, 0x65ecfb6b]
259 },
260 // chunk 1 with 1 byte input
261 // this is what the second chunk of input sees
262 // after the first 1024 bytes have been consumed
263 TestCase{
264 input: TestInput{
265 input_string: 'O'
266 key_words: iv
267 chunk_number: 1
268 flags: 0
269 }
270 results: Chunk{
271 chunk_number: 1
272 chaining_value: iv.clone()
273 block_words: [u32(0x0000004f), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
274 flags: 0x0b
275 }
276 words: [u32(0xfd795319), 0x4448fd94, 0xa8054dbb, 0x526517ad, 0x7e8e2e4c, 0xf54cf835,
277 0xb498c9a7, 0x341396fa, 0x753298b2, 0xd721328c, 0x4013c5d6, 0xaf64d891, 0x77893790,
278 0xe486143b, 0x13764172, 0x0cae81d0]
279 },
280]
281
282fn test_various_test_cases() {
283 for test_case in test_cases {
284 mut chunk := Chunk{}
285 input := test_case.input
286 chunk.process_input(input.input_string.bytes(), input.key_words, input.chunk_number,
287 input.flags, true)
288
289 results := test_case.results
290 assert chunk.chunk_number == results.chunk_number
291
292 for i, value in chunk.chaining_value {
293 assert value == results.chaining_value[i], 'i: ${i}, left: ${value:08x} right: ${results.chaining_value[i]:08x}'
294 }
295
296 for i in 0 .. 16 {
297 assert chunk.block_words[i] == results.block_words[i], 'i: ${i}, left: ${chunk.block_words[i]:08x} right: ${results.block_words[i]}'
298 }
299
300 assert chunk.flags == results.flags
301 }
302}
303