diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2022-02-22 20:34:50 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-02-22 20:34:50 +0100 |
| commit | fd627dc13b69a24dce366f5234f06300a5ad0bf4 (patch) | |
| tree | 1b878538a993a4ac8e8f0a18f0d7cc60aedecde0 | |
| parent | ea34f321ed07e782811f32bdc2ec2125f71577cd (diff) | |
| parent | 70e8d97ee1028aa491286195dfa75f7fc49d4133 (diff) | |
Merge pull request #1535 from zhibog/add-siphash
Added SipHash + tests and fixed remaining semicolons in vendor/botan
| -rw-r--r-- | core/crypto/siphash/siphash.odin | 336 | ||||
| -rw-r--r-- | tests/core/crypto/test_core_crypto.odin | 43 | ||||
| -rw-r--r-- | tests/vendor/botan/test_vendor_botan.odin | 43 | ||||
| -rw-r--r-- | vendor/botan/bindings/botan.odin | 4 | ||||
| -rw-r--r-- | vendor/botan/blake2b/blake2b.odin | 2 | ||||
| -rw-r--r-- | vendor/botan/gost/gost.odin | 2 | ||||
| -rw-r--r-- | vendor/botan/keccak/keccak.odin | 2 | ||||
| -rw-r--r-- | vendor/botan/md4/md4.odin | 2 | ||||
| -rw-r--r-- | vendor/botan/md5/md5.odin | 2 | ||||
| -rw-r--r-- | vendor/botan/ripemd/ripemd.odin | 2 | ||||
| -rw-r--r-- | vendor/botan/sha1/sha1.odin | 2 | ||||
| -rw-r--r-- | vendor/botan/sha2/sha2.odin | 8 | ||||
| -rw-r--r-- | vendor/botan/sha3/sha3.odin | 8 | ||||
| -rw-r--r-- | vendor/botan/shake/shake.odin | 4 | ||||
| -rw-r--r-- | vendor/botan/siphash/siphash.odin | 253 | ||||
| -rw-r--r-- | vendor/botan/skein512/skein512.odin | 6 | ||||
| -rw-r--r-- | vendor/botan/sm3/sm3.odin | 2 | ||||
| -rw-r--r-- | vendor/botan/streebog/streebog.odin | 4 | ||||
| -rw-r--r-- | vendor/botan/tiger/tiger.odin | 6 | ||||
| -rw-r--r-- | vendor/botan/whirlpool/whirlpool.odin | 2 |
20 files changed, 706 insertions, 27 deletions
diff --git a/core/crypto/siphash/siphash.odin b/core/crypto/siphash/siphash.odin new file mode 100644 index 000000000..63576551c --- /dev/null +++ b/core/crypto/siphash/siphash.odin @@ -0,0 +1,336 @@ +package siphash + +/* + Copyright 2022 zhibog + Made available under the BSD-3 license. + + List of contributors: + zhibog: Initial implementation. + + Implementation of the SipHash hashing algorithm, as defined at <https://github.com/veorq/SipHash> and <https://www.aumasson.jp/siphash/siphash.pdf> + + Use the specific procedures for a certain setup. The generic procdedures will default to Siphash 2-4 +*/ + +import "core:crypto" +import "core:crypto/util" +import "core:mem" + +/* + High level API +*/ + +KEY_SIZE :: 16 +DIGEST_SIZE :: 8 + +// sum_string_1_3 will hash the given message with the key and return +// the computed hash as a u64 +sum_string_1_3 :: proc(msg, key: string) -> u64 { + return sum_bytes_1_3(transmute([]byte)(msg), transmute([]byte)(key)) +} + +// sum_bytes_1_3 will hash the given message with the key and return +// the computed hash as a u64 +sum_bytes_1_3 :: proc (msg, key: []byte) -> u64 { + ctx: Context + hash: u64 + init(&ctx, key, 1, 3) + update(&ctx, msg) + final(&ctx, &hash) + return hash +} + +// sum_string_to_buffer_1_3 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_string_to_buffer_1_3 :: proc(msg, key: string, dst: []byte) { + sum_bytes_to_buffer_1_3(transmute([]byte)(msg), transmute([]byte)(key), dst) +} + +// sum_bytes_to_buffer_1_3 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_bytes_to_buffer_1_3 :: proc(msg, key, dst: []byte) { + assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8") + hash := sum_bytes_1_3(msg, key) + _collect_output(dst[:], hash) +} + +sum_1_3 :: proc { + sum_string_1_3, + sum_bytes_1_3, + sum_string_to_buffer_1_3, + sum_bytes_to_buffer_1_3, +} + +// verify_u64_1_3 will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_u64_1_3 :: proc (tag: u64 msg, key: []byte) -> bool { + return sum_bytes_1_3(msg, key) == tag +} + +// verify_bytes will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_bytes_1_3 :: proc (tag, msg, key: []byte) -> bool { + derived_tag: [8]byte + sum_bytes_to_buffer_1_3(msg, key, derived_tag[:]) + return crypto.compare_constant_time(derived_tag[:], tag) == 1 +} + +verify_1_3 :: proc { + verify_bytes_1_3, + verify_u64_1_3, +} + +// sum_string_2_4 will hash the given message with the key and return +// the computed hash as a u64 +sum_string_2_4 :: proc(msg, key: string) -> u64 { + return sum_bytes_2_4(transmute([]byte)(msg), transmute([]byte)(key)) +} + +// sum_bytes_2_4 will hash the given message with the key and return +// the computed hash as a u64 +sum_bytes_2_4 :: proc (msg, key: []byte) -> u64 { + ctx: Context + hash: u64 + init(&ctx, key, 2, 4) + update(&ctx, msg) + final(&ctx, &hash) + return hash +} + +// sum_string_to_buffer_2_4 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_string_to_buffer_2_4 :: proc(msg, key: string, dst: []byte) { + sum_bytes_to_buffer_2_4(transmute([]byte)(msg), transmute([]byte)(key), dst) +} + +// sum_bytes_to_buffer_2_4 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_bytes_to_buffer_2_4 :: proc(msg, key, dst: []byte) { + assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8") + hash := sum_bytes_2_4(msg, key) + _collect_output(dst[:], hash) +} + +sum_2_4 :: proc { + sum_string_2_4, + sum_bytes_2_4, + sum_string_to_buffer_2_4, + sum_bytes_to_buffer_2_4, +} + +sum_string :: sum_string_2_4 +sum_bytes :: sum_bytes_2_4 +sum_string_to_buffer :: sum_string_to_buffer_2_4 +sum_bytes_to_buffer :: sum_bytes_to_buffer_2_4 +sum :: proc { + sum_string, + sum_bytes, + sum_string_to_buffer, + sum_bytes_to_buffer, +} + +// verify_u64_2_4 will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_u64_2_4 :: proc (tag: u64 msg, key: []byte) -> bool { + return sum_bytes_2_4(msg, key) == tag +} + +// verify_bytes will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_bytes_2_4 :: proc (tag, msg, key: []byte) -> bool { + derived_tag: [8]byte + sum_bytes_to_buffer_2_4(msg, key, derived_tag[:]) + return crypto.compare_constant_time(derived_tag[:], tag) == 1 +} + +verify_2_4 :: proc { + verify_bytes_2_4, + verify_u64_2_4, +} + +verify_bytes :: verify_bytes_2_4 +verify_u64 :: verify_u64_2_4 +verify :: proc { + verify_bytes, + verify_u64, +} + +// sum_string_4_8 will hash the given message with the key and return +// the computed hash as a u64 +sum_string_4_8 :: proc(msg, key: string) -> u64 { + return sum_bytes_4_8(transmute([]byte)(msg), transmute([]byte)(key)) +} + +// sum_bytes_4_8 will hash the given message with the key and return +// the computed hash as a u64 +sum_bytes_4_8 :: proc (msg, key: []byte) -> u64 { + ctx: Context + hash: u64 + init(&ctx, key, 4, 8) + update(&ctx, msg) + final(&ctx, &hash) + return hash +} + +// sum_string_to_buffer_4_8 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_string_to_buffer_4_8 :: proc(msg, key: string, dst: []byte) { + sum_bytes_to_buffer_4_8(transmute([]byte)(msg), transmute([]byte)(key), dst) +} + +// sum_bytes_to_buffer_4_8 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_bytes_to_buffer_4_8 :: proc(msg, key, dst: []byte) { + assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8") + hash := sum_bytes_4_8(msg, key) + _collect_output(dst[:], hash) +} + +sum_4_8 :: proc { + sum_string_4_8, + sum_bytes_4_8, + sum_string_to_buffer_4_8, + sum_bytes_to_buffer_4_8, +} + +// verify_u64_4_8 will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_u64_4_8 :: proc (tag: u64 msg, key: []byte) -> bool { + return sum_bytes_4_8(msg, key) == tag +} + +// verify_bytes will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_bytes_4_8 :: proc (tag, msg, key: []byte) -> bool { + derived_tag: [8]byte + sum_bytes_to_buffer_4_8(msg, key, derived_tag[:]) + return crypto.compare_constant_time(derived_tag[:], tag) == 1 +} + +verify_4_8 :: proc { + verify_bytes_4_8, + verify_u64_4_8, +} + +/* + Low level API +*/ + +init :: proc(ctx: ^Context, key: []byte, c_rounds, d_rounds: int) { + assert(len(key) == KEY_SIZE, "crypto/siphash: Invalid key size, want 16") + ctx.c_rounds = c_rounds + ctx.d_rounds = d_rounds + is_valid_setting := (ctx.c_rounds == 1 && ctx.d_rounds == 3) || + (ctx.c_rounds == 2 && ctx.d_rounds == 4) || + (ctx.c_rounds == 4 && ctx.d_rounds == 8) + assert(is_valid_setting, "crypto/siphash: Incorrect rounds set up. Valid pairs are (1,3), (2,4) and (4,8)") + ctx.k0 = util.U64_LE(key[:8]) + ctx.k1 = util.U64_LE(key[8:]) + ctx.v0 = 0x736f6d6570736575 ~ ctx.k0 + ctx.v1 = 0x646f72616e646f6d ~ ctx.k1 + ctx.v2 = 0x6c7967656e657261 ~ ctx.k0 + ctx.v3 = 0x7465646279746573 ~ ctx.k1 + ctx.is_initialized = true +} + +update :: proc(ctx: ^Context, data: []byte) { + assert(ctx.is_initialized, "crypto/siphash: Context is not initalized") + ctx.last_block = len(data) / 8 * 8 + ctx.buf = data + i := 0 + m: u64 + for i < ctx.last_block { + m = u64(ctx.buf[i] & 0xff) + i += 1 + + for r in u64(1)..<8 { + m |= u64(ctx.buf[i] & 0xff) << (r * 8) + i += 1 + } + + ctx.v3 ~= m + for _ in 0..<ctx.c_rounds { + _compress(ctx) + } + + ctx.v0 ~= m + } +} + +final :: proc(ctx: ^Context, dst: ^u64) { + m: u64 + for i := len(ctx.buf) - 1; i >= ctx.last_block; i -= 1 { + m <<= 8 + m |= u64(ctx.buf[i] & 0xff) + } + m |= u64(len(ctx.buf) << 56) + + ctx.v3 ~= m + + for _ in 0..<ctx.c_rounds { + _compress(ctx) + } + + ctx.v0 ~= m + ctx.v2 ~= 0xff + + for _ in 0..<ctx.d_rounds { + _compress(ctx) + } + + dst^ = ctx.v0 ~ ctx.v1 ~ ctx.v2 ~ ctx.v3 + + reset(ctx) +} + +reset :: proc(ctx: ^Context) { + ctx.k0, ctx.k1 = 0, 0 + ctx.v0, ctx.v1 = 0, 0 + ctx.v2, ctx.v3 = 0, 0 + ctx.last_block = 0 + ctx.c_rounds = 0 + ctx.d_rounds = 0 + ctx.is_initialized = false +} + +Context :: struct { + v0, v1, v2, v3: u64, // State values + k0, k1: u64, // Split key + c_rounds: int, // Number of message rounds + d_rounds: int, // Number of finalization rounds + buf: []byte, // Provided data + last_block: int, // Offset from the last block + is_initialized: bool, +} + +_get_byte :: #force_inline proc "contextless" (byte_num: byte, into: u64) -> byte { + return byte(into >> (((~byte_num) & (size_of(u64) - 1)) << 3)) +} + +_collect_output :: #force_inline proc "contextless" (dst: []byte, hash: u64) { + dst[0] = _get_byte(7, hash) + dst[1] = _get_byte(6, hash) + dst[2] = _get_byte(5, hash) + dst[3] = _get_byte(4, hash) + dst[4] = _get_byte(3, hash) + dst[5] = _get_byte(2, hash) + dst[6] = _get_byte(1, hash) + dst[7] = _get_byte(0, hash) +} + +_compress :: #force_inline proc "contextless" (ctx: ^Context) { + ctx.v0 += ctx.v1 + ctx.v1 = util.ROTL64(ctx.v1, 13) + ctx.v1 ~= ctx.v0 + ctx.v0 = util.ROTL64(ctx.v0, 32) + ctx.v2 += ctx.v3 + ctx.v3 = util.ROTL64(ctx.v3, 16) + ctx.v3 ~= ctx.v2 + ctx.v0 += ctx.v3 + ctx.v3 = util.ROTL64(ctx.v3, 21) + ctx.v3 ~= ctx.v0 + ctx.v2 += ctx.v1 + ctx.v1 = util.ROTL64(ctx.v1, 17) + ctx.v1 ~= ctx.v2 + ctx.v2 = util.ROTL64(ctx.v2, 32) +} diff --git a/tests/core/crypto/test_core_crypto.odin b/tests/core/crypto/test_core_crypto.odin index 2ad00be66..5682a6167 100644 --- a/tests/core/crypto/test_core_crypto.odin +++ b/tests/core/crypto/test_core_crypto.odin @@ -36,6 +36,7 @@ import "core:crypto/sm3" import "core:crypto/jh" import "core:crypto/groestl" import "core:crypto/haval" +import "core:crypto/siphash" TEST_count := 0 TEST_fail := 0 @@ -114,6 +115,7 @@ main :: proc() { test_haval_192(&t) test_haval_224(&t) test_haval_256(&t) + test_siphash_2_4(&t) // "modern" crypto tests test_chacha20(&t) @@ -1103,3 +1105,44 @@ test_haval_256 :: proc(t: ^testing.T) { expect(t, computed_str == v.hash, fmt.tprintf("Expected: %s for input of %s, but got %s instead", v.hash, v.str, computed_str)) } } + +@(test) +test_siphash_2_4 :: proc(t: ^testing.T) { + // Test vectors from + // https://github.com/veorq/SipHash/blob/master/vectors.h + test_vectors := [?]u64 { + 0x726fdb47dd0e0e31, 0x74f839c593dc67fd, 0x0d6c8009d9a94f5a, 0x85676696d7fb7e2d, + 0xcf2794e0277187b7, 0x18765564cd99a68d, 0xcbc9466e58fee3ce, 0xab0200f58b01d137, + 0x93f5f5799a932462, 0x9e0082df0ba9e4b0, 0x7a5dbbc594ddb9f3, 0xf4b32f46226bada7, + 0x751e8fbc860ee5fb, 0x14ea5627c0843d90, 0xf723ca908e7af2ee, 0xa129ca6149be45e5, + 0x3f2acc7f57c29bdb, 0x699ae9f52cbe4794, 0x4bc1b3f0968dd39c, 0xbb6dc91da77961bd, + 0xbed65cf21aa2ee98, 0xd0f2cbb02e3b67c7, 0x93536795e3a33e88, 0xa80c038ccd5ccec8, + 0xb8ad50c6f649af94, 0xbce192de8a85b8ea, 0x17d835b85bbb15f3, 0x2f2e6163076bcfad, + 0xde4daaaca71dc9a5, 0xa6a2506687956571, 0xad87a3535c49ef28, 0x32d892fad841c342, + 0x7127512f72f27cce, 0xa7f32346f95978e3, 0x12e0b01abb051238, 0x15e034d40fa197ae, + 0x314dffbe0815a3b4, 0x027990f029623981, 0xcadcd4e59ef40c4d, 0x9abfd8766a33735c, + 0x0e3ea96b5304a7d0, 0xad0c42d6fc585992, 0x187306c89bc215a9, 0xd4a60abcf3792b95, + 0xf935451de4f21df2, 0xa9538f0419755787, 0xdb9acddff56ca510, 0xd06c98cd5c0975eb, + 0xe612a3cb9ecba951, 0xc766e62cfcadaf96, 0xee64435a9752fe72, 0xa192d576b245165a, + 0x0a8787bf8ecb74b2, 0x81b3e73d20b49b6f, 0x7fa8220ba3b2ecea, 0x245731c13ca42499, + 0xb78dbfaf3a8d83bd, 0xea1ad565322a1a0b, 0x60e61c23a3795013, 0x6606d7e446282b93, + 0x6ca4ecb15c5f91e1, 0x9f626da15c9625f3, 0xe51b38608ef25f57, 0x958a324ceb064572, + } + + key: [16]byte + for i in 0..<16 { + key[i] = byte(i) + } + + for i in 0..<len(test_vectors) { + data := make([]byte, i) + for j in 0..<i { + data[j] = byte(j) + } + + vector := test_vectors[i] + computed := siphash.sum_2_4(data[:], key[:]) + + expect(t, computed == vector, fmt.tprintf("Expected: 0x%x for input of %v, but got 0x%x instead", vector, data, computed)) + } +} diff --git a/tests/vendor/botan/test_vendor_botan.odin b/tests/vendor/botan/test_vendor_botan.odin index e92410621..148eb03bd 100644 --- a/tests/vendor/botan/test_vendor_botan.odin +++ b/tests/vendor/botan/test_vendor_botan.odin @@ -30,6 +30,7 @@ import "vendor:botan/gost" import "vendor:botan/streebog" import "vendor:botan/sm3" import "vendor:botan/skein512" +import "vendor:botan/siphash" TEST_count := 0 TEST_fail := 0 @@ -82,6 +83,7 @@ main :: proc() { test_sm3(&t) test_skein512_256(&t) test_skein512_512(&t) + test_siphash_2_4(&t) fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count) } @@ -575,3 +577,44 @@ test_skein512_512 :: proc(t: ^testing.T) { expect(t, computed_str == v.hash, fmt.tprintf("Expected: %s for input of %s, but got %s instead", v.hash, v.str, computed_str)) } } + +@(test) +test_siphash_2_4 :: proc(t: ^testing.T) { + // Test vectors from + // https://github.com/veorq/SipHash/blob/master/vectors.h + test_vectors := [?]u64 { + 0x726fdb47dd0e0e31, 0x74f839c593dc67fd, 0x0d6c8009d9a94f5a, 0x85676696d7fb7e2d, + 0xcf2794e0277187b7, 0x18765564cd99a68d, 0xcbc9466e58fee3ce, 0xab0200f58b01d137, + 0x93f5f5799a932462, 0x9e0082df0ba9e4b0, 0x7a5dbbc594ddb9f3, 0xf4b32f46226bada7, + 0x751e8fbc860ee5fb, 0x14ea5627c0843d90, 0xf723ca908e7af2ee, 0xa129ca6149be45e5, + 0x3f2acc7f57c29bdb, 0x699ae9f52cbe4794, 0x4bc1b3f0968dd39c, 0xbb6dc91da77961bd, + 0xbed65cf21aa2ee98, 0xd0f2cbb02e3b67c7, 0x93536795e3a33e88, 0xa80c038ccd5ccec8, + 0xb8ad50c6f649af94, 0xbce192de8a85b8ea, 0x17d835b85bbb15f3, 0x2f2e6163076bcfad, + 0xde4daaaca71dc9a5, 0xa6a2506687956571, 0xad87a3535c49ef28, 0x32d892fad841c342, + 0x7127512f72f27cce, 0xa7f32346f95978e3, 0x12e0b01abb051238, 0x15e034d40fa197ae, + 0x314dffbe0815a3b4, 0x027990f029623981, 0xcadcd4e59ef40c4d, 0x9abfd8766a33735c, + 0x0e3ea96b5304a7d0, 0xad0c42d6fc585992, 0x187306c89bc215a9, 0xd4a60abcf3792b95, + 0xf935451de4f21df2, 0xa9538f0419755787, 0xdb9acddff56ca510, 0xd06c98cd5c0975eb, + 0xe612a3cb9ecba951, 0xc766e62cfcadaf96, 0xee64435a9752fe72, 0xa192d576b245165a, + 0x0a8787bf8ecb74b2, 0x81b3e73d20b49b6f, 0x7fa8220ba3b2ecea, 0x245731c13ca42499, + 0xb78dbfaf3a8d83bd, 0xea1ad565322a1a0b, 0x60e61c23a3795013, 0x6606d7e446282b93, + 0x6ca4ecb15c5f91e1, 0x9f626da15c9625f3, 0xe51b38608ef25f57, 0x958a324ceb064572, + } + + key: [16]byte + for i in 0..<16 { + key[i] = byte(i) + } + + for i in 0..<len(test_vectors) { + data := make([]byte, i) + for j in 0..<i { + data[j] = byte(j) + } + + vector := test_vectors[i] + computed := siphash.sum_2_4(data[:], key[:]) + + expect(t, computed == vector, fmt.tprintf("Expected: 0x%x for input of %v, but got 0x%x instead", vector, data, computed)) + } +}
\ No newline at end of file diff --git a/vendor/botan/bindings/botan.odin b/vendor/botan/bindings/botan.odin index fdddc99a9..70311523d 100644 --- a/vendor/botan/bindings/botan.odin +++ b/vendor/botan/bindings/botan.odin @@ -99,6 +99,10 @@ MAC_HMAC_SHA_384 :: "HMAC(SHA-384)" MAC_HMAC_SHA_512 :: "HMAC(SHA-512)" MAC_HMAC_MD5 :: "HMAC(MD5)" +MAC_SIPHASH_1_3 :: "SipHash(1,3)" +MAC_SIPHASH_2_4 :: "SipHash(2,4)" +MAC_SIPHASH_4_8 :: "SipHash(4,8)" + hash_struct :: struct{} hash_t :: ^hash_struct rng_struct :: struct{} diff --git a/vendor/botan/blake2b/blake2b.odin b/vendor/botan/blake2b/blake2b.odin index 226502e83..67238ec74 100644 --- a/vendor/botan/blake2b/blake2b.odin +++ b/vendor/botan/blake2b/blake2b.odin @@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash); + hash_bytes_to_buffer(transmute([]byte)(data), hash) } // hash_bytes_to_buffer will hash the given input and write the diff --git a/vendor/botan/gost/gost.odin b/vendor/botan/gost/gost.odin index 9f081f9cb..6bf1c5b97 100644 --- a/vendor/botan/gost/gost.odin +++ b/vendor/botan/gost/gost.odin @@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash); + hash_bytes_to_buffer(transmute([]byte)(data), hash) } // hash_bytes_to_buffer will hash the given input and write the diff --git a/vendor/botan/keccak/keccak.odin b/vendor/botan/keccak/keccak.odin index 3316de017..28e7374ba 100644 --- a/vendor/botan/keccak/keccak.odin +++ b/vendor/botan/keccak/keccak.odin @@ -44,7 +44,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash); + hash_bytes_to_buffer_512(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_512 will hash the given input and write the diff --git a/vendor/botan/md4/md4.odin b/vendor/botan/md4/md4.odin index c8a1ad903..174676a82 100644 --- a/vendor/botan/md4/md4.odin +++ b/vendor/botan/md4/md4.odin @@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash); + hash_bytes_to_buffer(transmute([]byte)(data), hash) } // hash_bytes_to_buffer will hash the given input and write the diff --git a/vendor/botan/md5/md5.odin b/vendor/botan/md5/md5.odin index 203f2d092..01e099062 100644 --- a/vendor/botan/md5/md5.odin +++ b/vendor/botan/md5/md5.odin @@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash); + hash_bytes_to_buffer(transmute([]byte)(data), hash) } // hash_bytes_to_buffer will hash the given input and write the diff --git a/vendor/botan/ripemd/ripemd.odin b/vendor/botan/ripemd/ripemd.odin index 0a8195a96..230e4c0d9 100644 --- a/vendor/botan/ripemd/ripemd.odin +++ b/vendor/botan/ripemd/ripemd.odin @@ -44,7 +44,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_160 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_160(transmute([]byte)(data), hash); + hash_bytes_to_buffer_160(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_160 will hash the given input and write the diff --git a/vendor/botan/sha1/sha1.odin b/vendor/botan/sha1/sha1.odin index 005b01821..1f74c8fc2 100644 --- a/vendor/botan/sha1/sha1.odin +++ b/vendor/botan/sha1/sha1.odin @@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash); + hash_bytes_to_buffer(transmute([]byte)(data), hash) } // hash_bytes_to_buffer will hash the given input and write the diff --git a/vendor/botan/sha2/sha2.odin b/vendor/botan/sha2/sha2.odin index f5d6921a8..4c201cc26 100644 --- a/vendor/botan/sha2/sha2.odin +++ b/vendor/botan/sha2/sha2.odin @@ -47,7 +47,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_224 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_224(transmute([]byte)(data), hash); + hash_bytes_to_buffer_224(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_224 will hash the given input and write the @@ -126,7 +126,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash); + hash_bytes_to_buffer_256(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_256 will hash the given input and write the @@ -205,7 +205,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_384 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_384(transmute([]byte)(data), hash); + hash_bytes_to_buffer_384(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_384 will hash the given input and write the @@ -284,7 +284,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash); + hash_bytes_to_buffer_512(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_512 will hash the given input and write the diff --git a/vendor/botan/sha3/sha3.odin b/vendor/botan/sha3/sha3.odin index cf9fa5b2b..4c1b87dda 100644 --- a/vendor/botan/sha3/sha3.odin +++ b/vendor/botan/sha3/sha3.odin @@ -47,7 +47,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_224 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_224(transmute([]byte)(data), hash); + hash_bytes_to_buffer_224(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_224 will hash the given input and write the @@ -126,7 +126,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash); + hash_bytes_to_buffer_256(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_256 will hash the given input and write the @@ -205,7 +205,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_384 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_384(transmute([]byte)(data), hash); + hash_bytes_to_buffer_384(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_384 will hash the given input and write the @@ -284,7 +284,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash); + hash_bytes_to_buffer_512(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_512 will hash the given input and write the diff --git a/vendor/botan/shake/shake.odin b/vendor/botan/shake/shake.odin index ac8432f64..f1023b90e 100644 --- a/vendor/botan/shake/shake.odin +++ b/vendor/botan/shake/shake.odin @@ -45,7 +45,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_128 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_128(transmute([]byte)(data), hash); + hash_bytes_to_buffer_128(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_128 will hash the given input and write the @@ -124,7 +124,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash); + hash_bytes_to_buffer_256(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_256 will hash the given input and write the diff --git a/vendor/botan/siphash/siphash.odin b/vendor/botan/siphash/siphash.odin new file mode 100644 index 000000000..c2b7b64f4 --- /dev/null +++ b/vendor/botan/siphash/siphash.odin @@ -0,0 +1,253 @@ +package siphash + +/* + Copyright 2022 zhibog + Made available under the BSD-3 license. + + List of contributors: + zhibog: Initial implementation. + + Interface for the SipHash hashing algorithm. + The hash will be computed via bindings to the Botan crypto library + + Use the specific procedures for a certain setup. The generic procdedures will default to Siphash 2-4 +*/ + +import "core:crypto" +import "core:crypto/util" + +import botan "../bindings" + +KEY_SIZE :: 16 +DIGEST_SIZE :: 8 + +// sum_string_1_3 will hash the given message with the key and return +// the computed hash as a u64 +sum_string_1_3 :: proc(msg, key: string) -> u64 { + return sum_bytes_1_3(transmute([]byte)(msg), transmute([]byte)(key)) +} + +// sum_bytes_1_3 will hash the given message with the key and return +// the computed hash as a u64 +sum_bytes_1_3 :: proc (msg, key: []byte) -> u64 { + dst: [8]byte + ctx: botan.mac_t + init(&ctx, key[:], 1, 3) + update(&ctx, msg[:]) + final(&ctx, dst[:]) + return util.U64_LE(dst[:]) +} + +// sum_string_to_buffer_1_3 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_string_to_buffer_1_3 :: proc(msg, key: string, dst: []byte) { + sum_bytes_to_buffer_1_3(transmute([]byte)(msg), transmute([]byte)(key), dst) +} + +// sum_bytes_to_buffer_1_3 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_bytes_to_buffer_1_3 :: proc(msg, key, dst: []byte) { + assert(len(dst) >= DIGEST_SIZE, "vendor/botan: Destination buffer needs to be at least of size 8") + ctx: botan.mac_t + init(&ctx, key[:], 1, 3) + update(&ctx, msg[:]) + final(&ctx, dst[:]) +} + +sum_1_3 :: proc { + sum_string_1_3, + sum_bytes_1_3, + sum_string_to_buffer_1_3, + sum_bytes_to_buffer_1_3, +} + +// verify_u64_1_3 will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_u64_1_3 :: proc (tag: u64 msg, key: []byte) -> bool { + return sum_bytes_1_3(msg, key) == tag +} + +// verify_bytes_1_3 will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_bytes_1_3 :: proc (tag, msg, key: []byte) -> bool { + derived_tag: [8]byte + sum_bytes_to_buffer_1_3(msg, key, derived_tag[:]) + return crypto.compare_constant_time(derived_tag[:], tag) == 1 +} + +verify_1_3 :: proc { + verify_bytes_1_3, + verify_u64_1_3, +} + +// sum_string_2_4 will hash the given message with the key and return +// the computed hash as a u64 +sum_string_2_4 :: proc(msg, key: string) -> u64 { + return sum_bytes_2_4(transmute([]byte)(msg), transmute([]byte)(key)) +} + +// sum_bytes_2_4 will hash the given message with the key and return +// the computed hash as a u64 +sum_bytes_2_4 :: proc (msg, key: []byte) -> u64 { + dst: [8]byte + ctx: botan.mac_t + init(&ctx, key[:]) + update(&ctx, msg[:]) + final(&ctx, dst[:]) + return util.U64_LE(dst[:]) +} + +// sum_string_to_buffer_2_4 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_string_to_buffer_2_4 :: proc(msg, key: string, dst: []byte) { + sum_bytes_to_buffer_2_4(transmute([]byte)(msg), transmute([]byte)(key), dst) +} + +// sum_bytes_to_buffer_2_4 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_bytes_to_buffer_2_4 :: proc(msg, key, dst: []byte) { + assert(len(dst) >= DIGEST_SIZE, "vendor/botan: Destination buffer needs to be at least of size 8") + ctx: botan.mac_t + init(&ctx, key[:]) + update(&ctx, msg[:]) + final(&ctx, dst[:]) +} + +sum_2_4 :: proc { + sum_string_2_4, + sum_bytes_2_4, + sum_string_to_buffer_2_4, + sum_bytes_to_buffer_2_4, +} + +sum_string :: sum_string_2_4 +sum_bytes :: sum_bytes_2_4 +sum_string_to_buffer :: sum_string_to_buffer_2_4 +sum_bytes_to_buffer :: sum_bytes_to_buffer_2_4 +sum :: proc { + sum_string, + sum_bytes, + sum_string_to_buffer, + sum_bytes_to_buffer, +} + + +// verify_u64_2_4 will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_u64_2_4 :: proc (tag: u64 msg, key: []byte) -> bool { + return sum_bytes_2_4(msg, key) == tag +} + +// verify_bytes_2_4 will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_bytes_2_4 :: proc (tag, msg, key: []byte) -> bool { + derived_tag: [8]byte + sum_bytes_to_buffer_2_4(msg, key, derived_tag[:]) + return crypto.compare_constant_time(derived_tag[:], tag) == 1 +} + +verify_2_4 :: proc { + verify_bytes_2_4, + verify_u64_2_4, +} + +verify_bytes :: verify_bytes_2_4 +verify_u64 :: verify_u64_2_4 +verify :: proc { + verify_bytes, + verify_u64, +} + +// sum_string_4_8 will hash the given message with the key and return +// the computed hash as a u64 +sum_string_4_8 :: proc(msg, key: string) -> u64 { + return sum_bytes_4_8(transmute([]byte)(msg), transmute([]byte)(key)) +} + +// sum_bytes_4_8 will hash the given message with the key and return +// the computed hash as a u64 +sum_bytes_4_8 :: proc (msg, key: []byte) -> u64 { + dst: [8]byte + ctx: botan.mac_t + init(&ctx, key[:], 4, 8) + update(&ctx, msg[:]) + final(&ctx, dst[:]) + return util.U64_LE(dst[:]) +} + +// sum_string_to_buffer_4_8 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_string_to_buffer_4_8 :: proc(msg, key: string, dst: []byte) { + sum_bytes_to_buffer_2_4(transmute([]byte)(msg), transmute([]byte)(key), dst) +} + +// sum_bytes_to_buffer_4_8 will hash the given message with the key and write +// the computed hash into the provided destination buffer +sum_bytes_to_buffer_4_8 :: proc(msg, key, dst: []byte) { + assert(len(dst) >= DIGEST_SIZE, "vendor/botan: Destination buffer needs to be at least of size 8") + ctx: botan.mac_t + init(&ctx, key[:], 4, 8) + update(&ctx, msg[:]) + final(&ctx, dst[:]) +} + +sum_4_8 :: proc { + sum_string_4_8, + sum_bytes_4_8, + sum_string_to_buffer_4_8, + sum_bytes_to_buffer_4_8, +} + +// verify_u64_4_8 will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_u64_4_8 :: proc (tag: u64 msg, key: []byte) -> bool { + return sum_bytes_4_8(msg, key) == tag +} + +// verify_bytes_4_8 will check if the supplied tag matches with the output you +// will get from the provided message and key +verify_bytes_4_8 :: proc (tag, msg, key: []byte) -> bool { + derived_tag: [8]byte + sum_bytes_to_buffer_4_8(msg, key, derived_tag[:]) + return crypto.compare_constant_time(derived_tag[:], tag) == 1 +} + +verify_4_8 :: proc { + verify_bytes_4_8, + verify_u64_4_8, +} + +/* + Low level API +*/ + +Context :: botan.mac_t + +init :: proc(ctx: ^botan.mac_t, key: []byte, c_rounds := 2, d_rounds := 4) { + assert(len(key) == KEY_SIZE, "vendor/botan: Invalid key size, want 16") + is_valid_setting := (c_rounds == 1 && d_rounds == 3) || + (c_rounds == 2 && d_rounds == 4) || + (c_rounds == 4 && d_rounds == 8) + assert(is_valid_setting, "vendor/botan: Incorrect rounds set up. Valid pairs are (1,3), (2,4) and (4,8)") + if c_rounds == 1 && d_rounds == 3 { + botan.mac_init(ctx, botan.MAC_SIPHASH_1_3, 0) + } else if c_rounds == 2 && d_rounds == 4 { + botan.mac_init(ctx, botan.MAC_SIPHASH_2_4, 0) + } else if c_rounds == 4 && d_rounds == 8 { + botan.mac_init(ctx, botan.MAC_SIPHASH_4_8, 0) + } + botan.mac_set_key(ctx^, len(key) == 0 ? nil : &key[0], uint(len(key))) +} + +update :: proc "contextless" (ctx: ^botan.mac_t, data: []byte) { + botan.mac_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data))) +} + +final :: proc(ctx: ^botan.mac_t, dst: []byte) { + botan.mac_final(ctx^, &dst[0]) + reset(ctx) +} + +reset :: proc(ctx: ^botan.mac_t) { + botan.mac_destroy(ctx^) +}
\ No newline at end of file diff --git a/vendor/botan/skein512/skein512.odin b/vendor/botan/skein512/skein512.odin index 490eeba03..4fed07853 100644 --- a/vendor/botan/skein512/skein512.odin +++ b/vendor/botan/skein512/skein512.odin @@ -47,7 +47,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash); + hash_bytes_to_buffer_256(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_256 will hash the given input and write the @@ -126,7 +126,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash); + hash_bytes_to_buffer_512(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_512 will hash the given input and write the @@ -205,7 +205,7 @@ hash_bytes_slice :: proc(data: []byte, bit_size: int, allocator := context.alloc // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_slice :: proc(data: string, hash: []byte, bit_size: int, allocator := context.allocator) { - hash_bytes_to_buffer_slice(transmute([]byte)(data), hash, bit_size, allocator); + hash_bytes_to_buffer_slice(transmute([]byte)(data), hash, bit_size, allocator) } // hash_bytes_to_buffer_slice will hash the given input and write the diff --git a/vendor/botan/sm3/sm3.odin b/vendor/botan/sm3/sm3.odin index 7eb3f1f8d..75cf40679 100644 --- a/vendor/botan/sm3/sm3.odin +++ b/vendor/botan/sm3/sm3.odin @@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash); + hash_bytes_to_buffer(transmute([]byte)(data), hash) } // hash_bytes_to_buffer will hash the given input and write the diff --git a/vendor/botan/streebog/streebog.odin b/vendor/botan/streebog/streebog.odin index cbf2047ed..20b4e6adb 100644 --- a/vendor/botan/streebog/streebog.odin +++ b/vendor/botan/streebog/streebog.odin @@ -45,7 +45,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash); + hash_bytes_to_buffer_256(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_256 will hash the given input and write the @@ -124,7 +124,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash); + hash_bytes_to_buffer_512(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_512 will hash the given input and write the diff --git a/vendor/botan/tiger/tiger.odin b/vendor/botan/tiger/tiger.odin index b29602b26..f24dc7019 100644 --- a/vendor/botan/tiger/tiger.odin +++ b/vendor/botan/tiger/tiger.odin @@ -46,7 +46,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_128 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_128(transmute([]byte)(data), hash); + hash_bytes_to_buffer_128(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_128 will hash the given input and write the @@ -125,7 +125,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_160 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_160(transmute([]byte)(data), hash); + hash_bytes_to_buffer_160(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_160 will hash the given input and write the @@ -204,7 +204,7 @@ hash_bytes_192 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_192 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_192(transmute([]byte)(data), hash); + hash_bytes_to_buffer_192(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_192 will hash the given input and write the diff --git a/vendor/botan/whirlpool/whirlpool.odin b/vendor/botan/whirlpool/whirlpool.odin index 2aff3c8ed..a7c1abbe8 100644 --- a/vendor/botan/whirlpool/whirlpool.odin +++ b/vendor/botan/whirlpool/whirlpool.odin @@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte { // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash); + hash_bytes_to_buffer(transmute([]byte)(data), hash) } // hash_bytes_to_buffer will hash the given input and write the |