v2 / vlib / crypto / blake3 / blake3_test.v
128 lines · 99 sloc · 3.48 KB · 07c796b670d9e498ccb25605af189617f61ec295
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
11import encoding.hex
12import json
13import os
14
15struct TestObject {
16 comment string
17 key string
18 context_string string
19 cases []TestVectors
20}
21
22struct TestVectors {
23 input_len u64
24 hash string
25 keyed_hash string
26 derive_key string
27}
28
29const object_string = os.read_file(os.real_path(os.join_path(os.dir(@FILE), 'testdata',
30 'test_vectors.json'))) or { panic(err) }
31
32const test_object = json.decode(TestObject, object_string) or { panic(err) }
33
34const data_segment = []u8{len: 251, cap: 251, init: u8(index)}
35
36fn test_run_test_vectors() {
37 mut data := []u8{}
38 for i in 0 .. 408 {
39 data << data_segment
40 }
41
42 for case in test_object.cases {
43 extended_length := u64(case.hash.len)
44
45 // test Blake3 hash
46
47 mut hash_d := Digest.new_hash() or {
48 assert false, 'Digest.new_hash error: ${err}'
49 return
50 }
51
52 hash_d.write(data[..int(case.input_len)]) or {
53 assert false, 'hash_d.write error: ${err}'
54 return
55 }
56
57 hash_bytes := hex.decode(case.hash) or {
58 assert false, 'invalid hex string: ${err}'
59 return
60 }
61
62 // test various sizes and see if we can ask for different
63 // sizes without recomputing the hash
64
65 for i in [u64(16), 20, 24, 28, 32, 48, 64, 72, 96] {
66 if hash_bytes.len > i {
67 assert hash_d.checksum(i) == hash_bytes[..int(i)], 'hash failed output length ${i}'
68 }
69 }
70
71 assert hash_d.checksum(u64(hash_bytes.len)) == hash_bytes, 'hash failed output length ${extended_length}'
72
73 // test Blake3 keyed hash
74
75 mut keyed_hash_d := Digest.new_keyed_hash(test_object.key.bytes()) or {
76 assert false, 'Digest.new_keyed_hash error: ${err}'
77 return
78 }
79
80 keyed_hash_d.write(data[..int(case.input_len)]) or {
81 assert false, 'keyed_hash_d.write error: ${err}'
82 return
83 }
84
85 keyed_hash_bytes := hex.decode(case.keyed_hash) or {
86 assert false, 'invalid hex string: ${err}'
87 return
88 }
89
90 // test various sizes and see if we can ask for different
91 // sizes without recomputing the hash
92
93 for i in [u64(16), 20, 24, 28, 32, 48, 64, 72, 96] {
94 if keyed_hash_bytes.len > i {
95 assert keyed_hash_d.checksum(i) == keyed_hash_bytes[..int(i)], 'keyed hash failed output length ${i}'
96 }
97 }
98
99 assert keyed_hash_d.checksum(u64(keyed_hash_bytes.len)) == keyed_hash_bytes, 'keyed hash failed output length ${extended_length}'
100 // test Blake3 derive key hash
101
102 mut derive_key_hash_d := Digest.new_derive_key_hash(test_object.context_string.bytes()) or {
103 assert false, 'Digest.new_derive_key_hash error: ${err}'
104 return
105 }
106
107 derive_key_hash_d.write(data[..int(case.input_len)]) or {
108 assert false, 'derive_key_hash_d.write error: ${err}'
109 return
110 }
111
112 derive_key_hash_bytes := hex.decode(case.derive_key) or {
113 assert false, 'invalid hex string: ${err}'
114 return
115 }
116
117 // test various sizes and see if we can ask for different
118 // sizes without recomputing the hash
119
120 for i in [u64(16), 20, 24, 28, 32, 48, 64, 72, 96] {
121 if derive_key_hash_bytes.len > i {
122 assert derive_key_hash_d.checksum(i) == derive_key_hash_bytes[..int(i)], 'derive key hash failed output length ${i}'
123 }
124 }
125
126 assert derive_key_hash_d.checksum(u64(derive_key_hash_bytes.len)) == derive_key_hash_bytes, 'derive key hash failed output length ${extended_length}'
127 }
128}
129