mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
303 lines
9.9 KiB
V
303 lines
9.9 KiB
V
// Copyright (c) 2023 Kim Shrier. All rights reserved.
|
|
// Use of this source code is governed by an MIT license
|
|
// that can be found in the LICENSE file.
|
|
// Package blake3 implements the Blake3 cryptographic hash
|
|
// as described in:
|
|
// https://github.com/BLAKE3-team/BLAKE3-specs/blob/master/blake3.pdf
|
|
// Version 20211102173700
|
|
|
|
module blake3
|
|
|
|
// build input strings of various lengths
|
|
const fua = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
const bua = 'ZYXWVUTSRQPONMLKJIHGFEDCBA'
|
|
|
|
const fla = 'abcdefghijklmnopqrstuvwxyz'
|
|
const bla = 'zyxwvutsrqponmlkjihgfedcba'
|
|
|
|
const fnr = '0123456789'
|
|
const bnr = '9876543210'
|
|
|
|
const ll = fua + ' ' + fla + ' ' + fnr + ' ' + bnr + ' ' + bla + ' ' + bua
|
|
|
|
const lb = ll + '\n' + ll + '\n' + ll + '\n' + ll + '\n' + ll + '\n' + ll + '\n' + ll + '\n' + ll
|
|
|
|
struct TestInput {
|
|
input_string string
|
|
key_words []u32
|
|
chunk_number u64
|
|
flags u32
|
|
}
|
|
|
|
struct TestCase {
|
|
input TestInput // inputs to the chunk's process_input method
|
|
results Chunk // the resulting chunk
|
|
words []u32 // the final output state as 32-bit words
|
|
}
|
|
|
|
// Chunk structures after processing varying amounts of input
|
|
//
|
|
// The expected values were derived from instrumenting the C reference
|
|
// implementation and dumping the appropriate values from their variables
|
|
// when processing the same input as the test case.
|
|
const test_cases = [
|
|
// chunk 0 with 0 bytes input
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: ''
|
|
key_words: iv
|
|
chunk_number: 0
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 0
|
|
chaining_value: iv.clone()
|
|
block_words: [u32(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
flags: 0x0b
|
|
}
|
|
words: [u32(0xb94913af), 0xa6a1f9f5, 0xea4d40a0, 0x49c9dc36, 0xc925cb9b, 0xb712c1ad,
|
|
0xca939acc, 0x62321fe4, 0xe7030fe0, 0x6bf29ab6, 0x9ff0aa7f, 0x503033cd, 0xe0df8d33,
|
|
0x86ccb885, 0x208ba99c, 0x3a24086c]
|
|
},
|
|
// chunk 0 with 1 byte input
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: 'A'
|
|
key_words: iv
|
|
chunk_number: 0
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 0
|
|
chaining_value: iv.clone()
|
|
block_words: [u32(0x00000041), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
flags: 0x0b
|
|
}
|
|
words: [u32(0xfa4b6832), 0x4dc8c028, 0x1105216f, 0xfc0eceaa, 0x88c77151, 0x89ba4891,
|
|
0xa25a8d20, 0x98fa0597, 0x4c0088e3, 0xafa7cbb8, 0xc586c5f7, 0x66dbef0e, 0x8c91d56a,
|
|
0xa0b3daff, 0xe919be05, 0x997a1ce7]
|
|
},
|
|
// chunk 0 with 3 bytes input
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: 'abc'
|
|
key_words: iv
|
|
chunk_number: 0
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 0
|
|
chaining_value: iv.clone()
|
|
block_words: [u32(0x00636261), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
flags: 0x0b
|
|
}
|
|
words: [u32(0xacb33764), 0x33514638, 0x753bb6ff, 0xb58d3a27, 0x4658c548, 0x03db795d,
|
|
0x6c9c35fd, 0x859dbdd5, 0xae50b21f, 0xd0f59373, 0x5db61328, 0x490d1a52, 0x9ca09b2d,
|
|
0x4c7fcef7, 0xf200d9ff, 0x0bbf7433]
|
|
},
|
|
// chunk 0 with 63 bytes input
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: ll[..63]
|
|
key_words: iv
|
|
chunk_number: 0
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 0
|
|
chaining_value: iv.clone()
|
|
block_words: [u32(0x44434241), 0x48474645, 0x4c4b4a49, 0x504f4e4d, 0x54535251,
|
|
0x58575655, 0x61205a59, 0x65646362, 0x69686766, 0x6d6c6b6a, 0x71706f6e, 0x75747372,
|
|
0x79787776, 0x3130207a, 0x35343332, 0x00383736]
|
|
flags: 0x0b
|
|
}
|
|
words: [u32(0x39c41fc6), 0x2dd7c57b, 0xb8b16421, 0x360cbedb, 0x462d5672, 0x56713bb5,
|
|
0x15132543, 0x7a92c4ba, 0x15c4ac13, 0x2354f573, 0xdc14f100, 0x35be07e8, 0xf98b17b9,
|
|
0x573f38f8, 0xc8d2fbf4, 0xc06588e5]
|
|
},
|
|
// chunk 0 with 64 bytes input
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: ll[..64]
|
|
key_words: iv
|
|
chunk_number: 0
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 0
|
|
chaining_value: iv.clone()
|
|
block_words: [u32(0x44434241), 0x48474645, 0x4c4b4a49, 0x504f4e4d, 0x54535251,
|
|
0x58575655, 0x61205a59, 0x65646362, 0x69686766, 0x6d6c6b6a, 0x71706f6e, 0x75747372,
|
|
0x79787776, 0x3130207a, 0x35343332, 0x39383736]
|
|
flags: 0x0b
|
|
}
|
|
words: [u32(0x6010817a), 0x21deb495, 0x0826485b, 0x6f895da5, 0x9363242a, 0x176b60a9,
|
|
0x383215a7, 0x2b95570f, 0x57fe7082, 0x45b13a10, 0x007af189, 0x4b5e7ec7, 0x9574b5d8,
|
|
0x109362a0, 0x282d14c2, 0x3a134380]
|
|
},
|
|
// chunk 0 with 65 bytes input
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: ll[..65]
|
|
key_words: iv
|
|
chunk_number: 0
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 0
|
|
chaining_value: [u32(0xbb99f549), 0x3b4b2903, 0x436d199e, 0x6eea5980, 0x82ebb968,
|
|
0x33cc3c4a, 0x90f4944b, 0x9480e10a]
|
|
block_words: [u32(0x00000020), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
flags: 0x0a
|
|
}
|
|
words: [u32(0xb06cf0f5), 0xd6f8f23d, 0x0f06389e, 0x20dec0a4, 0x69a20569, 0xdbbb4453,
|
|
0x09f0bb52, 0xe22c6707, 0x6b530f62, 0x9ac8bfbd, 0xc0aa57b0, 0xdb30223c, 0xd6e52c79,
|
|
0x42d84d38, 0xcfb4105f, 0xb42f1bd3]
|
|
},
|
|
// chunk 0 with 127 bytes input
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: ll[..127]
|
|
key_words: iv
|
|
chunk_number: 0
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 0
|
|
chaining_value: [u32(0xbb99f549), 0x3b4b2903, 0x436d199e, 0x6eea5980, 0x82ebb968,
|
|
0x33cc3c4a, 0x90f4944b, 0x9480e10a]
|
|
block_words: [u32(0x37383920), 0x33343536, 0x20303132, 0x7778797a, 0x73747576,
|
|
0x6f707172, 0x6b6c6d6e, 0x6768696a, 0x63646566, 0x5a206162, 0x56575859, 0x52535455,
|
|
0x4e4f5051, 0x4a4b4c4d, 0x46474849, 0x00434445]
|
|
flags: 0x0a
|
|
}
|
|
words: [u32(0x589a304d), 0x49f8a607, 0x55a03867, 0xe4fec410, 0x1a6bb2f6, 0x11dfecb3,
|
|
0xf9989552, 0xb2d18382, 0x9fc6329a, 0xcc93199f, 0x5431cfc5, 0x1f5bddc6, 0x1d039fc5,
|
|
0x09af900e, 0x55ce0ba2, 0x9707b1e6]
|
|
},
|
|
// chunk 0 with 128 bytes input
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: ll[..128]
|
|
key_words: iv
|
|
chunk_number: 0
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 0
|
|
chaining_value: [u32(0xbb99f549), 0x3b4b2903, 0x436d199e, 0x6eea5980, 0x82ebb968,
|
|
0x33cc3c4a, 0x90f4944b, 0x9480e10a]
|
|
block_words: [u32(0x37383920), 0x33343536, 0x20303132, 0x7778797a, 0x73747576,
|
|
0x6f707172, 0x6b6c6d6e, 0x6768696a, 0x63646566, 0x5a206162, 0x56575859, 0x52535455,
|
|
0x4e4f5051, 0x4a4b4c4d, 0x46474849, 0x42434445]
|
|
flags: 0x0a
|
|
}
|
|
words: [u32(0xd0d12158), 0x8802f9a4, 0x5bd125fb, 0xf2751b9d, 0x8fb2a4d2, 0x27744bfa,
|
|
0x6ea287b1, 0xae9cfdb2, 0x8e0c2651, 0xeb2cfa50, 0x84654cbf, 0xb97b6f7b, 0xd2d737a2,
|
|
0x46eaad72, 0x4d0235f0, 0xcaf8abb7]
|
|
},
|
|
// chunk 0 with 129 bytes input
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: ll[..129]
|
|
key_words: iv
|
|
chunk_number: 0
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 0
|
|
chaining_value: [u32(0xccf04979), 0x9cbf983e, 0x9e274997, 0xb88c707b, 0x482b00d8,
|
|
0x7aedc034, 0x1efdc297, 0x4de9f7c5]
|
|
block_words: [u32(0x00000041), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
flags: 0x0a
|
|
}
|
|
words: [u32(0xa896b53e), 0x1a64b264, 0xb08c7ea7, 0x09990e6d, 0x30470999, 0x762e9f2c,
|
|
0xb6c7bf5f, 0x64fd723a, 0x6cb02e2f, 0xa3849bf2, 0xede8ea18, 0x14c88505, 0xfbf2ad67,
|
|
0x6bc0a779, 0x8e731b77, 0x643a82c6]
|
|
},
|
|
// chunk 0 with 1023 bytes input
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: lb[..1023]
|
|
key_words: iv
|
|
chunk_number: 0
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 0
|
|
chaining_value: [u32(0x78fd494b), 0xcd7eeddd, 0x0cb98e9b, 0x7a6a754e, 0x38ff2d32,
|
|
0x88c4ca4c, 0xbc7baf18, 0xf7684da9]
|
|
block_words: [u32(0x207a7978), 0x33323130, 0x37363534, 0x39203938, 0x35363738,
|
|
0x31323334, 0x797a2030, 0x75767778, 0x71727374, 0x6d6e6f70, 0x696a6b6c, 0x65666768,
|
|
0x61626364, 0x58595a20, 0x54555657, 0x00515253]
|
|
flags: 0x0a
|
|
}
|
|
words: [u32(0x96bcc611), 0x8ccfc351, 0x89ec78f7, 0x2f748832, 0xf75ee10a, 0xc739f876,
|
|
0x6adddebb, 0xe28853ab, 0x6983883d, 0x1ca0378d, 0x11f4296c, 0x6638ad9a, 0x0c639f8a,
|
|
0xebf03d1f, 0x2c0e3844, 0x0989b826]
|
|
},
|
|
// chunk 0 with 1024 bytes input
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: lb[..1024]
|
|
key_words: iv
|
|
chunk_number: 0
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 0
|
|
chaining_value: [u32(0x78fd494b), 0xcd7eeddd, 0x0cb98e9b, 0x7a6a754e, 0x38ff2d32,
|
|
0x88c4ca4c, 0xbc7baf18, 0xf7684da9]
|
|
block_words: [u32(0x207a7978), 0x33323130, 0x37363534, 0x39203938, 0x35363738,
|
|
0x31323334, 0x797a2030, 0x75767778, 0x71727374, 0x6d6e6f70, 0x696a6b6c, 0x65666768,
|
|
0x61626364, 0x58595a20, 0x54555657, 0x50515253]
|
|
flags: 0x0a
|
|
}
|
|
words: [u32(0x50dbfcc6), 0x7dd05a7f, 0xa641cc37, 0x11721a4e, 0x6f33eea2, 0x834877a1,
|
|
0x1cb36c9c, 0xf8d78dce, 0xb7539a0e, 0x7c7b57f4, 0xeef982da, 0x82c6c442, 0x8a451e9b,
|
|
0xb9cc8414, 0xdef7ad58, 0x65ecfb6b]
|
|
},
|
|
// chunk 1 with 1 byte input
|
|
// this is what the second chunk of input sees
|
|
// after the first 1024 bytes have been consumed
|
|
TestCase{
|
|
input: TestInput{
|
|
input_string: 'O'
|
|
key_words: iv
|
|
chunk_number: 1
|
|
flags: 0
|
|
}
|
|
results: Chunk{
|
|
chunk_number: 1
|
|
chaining_value: iv.clone()
|
|
block_words: [u32(0x0000004f), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
flags: 0x0b
|
|
}
|
|
words: [u32(0xfd795319), 0x4448fd94, 0xa8054dbb, 0x526517ad, 0x7e8e2e4c, 0xf54cf835,
|
|
0xb498c9a7, 0x341396fa, 0x753298b2, 0xd721328c, 0x4013c5d6, 0xaf64d891, 0x77893790,
|
|
0xe486143b, 0x13764172, 0x0cae81d0]
|
|
},
|
|
]
|
|
|
|
fn test_various_test_cases() {
|
|
for test_case in test_cases {
|
|
mut chunk := Chunk{}
|
|
input := test_case.input
|
|
chunk.process_input(input.input_string.bytes(), input.key_words, input.chunk_number,
|
|
input.flags, true)
|
|
|
|
results := test_case.results
|
|
assert chunk.chunk_number == results.chunk_number
|
|
|
|
for i, value in chunk.chaining_value {
|
|
assert value == results.chaining_value[i], 'i: ${i}, left: ${value:08x} right: ${results.chaining_value[i]:08x}'
|
|
}
|
|
|
|
for i in 0 .. 16 {
|
|
assert chunk.block_words[i] == results.block_words[i], 'i: ${i}, left: ${chunk.block_words[i]:08x} right: ${results.block_words[i]}'
|
|
}
|
|
|
|
assert chunk.flags == results.flags
|
|
}
|
|
}
|