Add Botan crypto lib as a vendor library

This commit is contained in:
zhibog
2021-11-09 23:49:17 +01:00
parent 600d19c51b
commit cef9632607
22 changed files with 3321 additions and 1 deletions
+10 -1
View File
@@ -117,4 +117,13 @@ See also LICENSE.txt in the `portmidi` directory itself.
`enet.lib` and `enet64.lib` are available under ENet's [MIT](http://enet.bespin.org/License.html) license.
See also LICENSE in the `ENet` directory itself.
See also LICENSE in the `ENet` directory itself.
## Botan
[Botan](https://botan.randombit.net/) Crypto and TLS library.
`botan.lib` is available under Botan's [BSD](https://botan.randombit.net/license.txt) license.
See also LICENSE in the `botan` directory itself.
Includes full bindings as well as wrappers to match the `core:crypto` API.
+64
View File
@@ -0,0 +1,64 @@
# botan
A wrapper for the Botan crypto library
## Supported
This library offers full bindings for everything exposed by Botan's FFI.
Wrappers for hashing algorithms have been added to match the API within the Odin `core:crypto` library.
## Hashing algorithms
| Algorithm | |
|:-------------------------------------------------------------------------------------------------------------|:-----------------|
| [BLAKE2B](https://datatracker.ietf.org/doc/html/rfc7693) | ✔️ |
| [GOST](https://datatracker.ietf.org/doc/html/rfc5831) | ✔️ |
| [Keccak](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) | ✔️ |
| [MD4](https://datatracker.ietf.org/doc/html/rfc1320) | ✔️ |
| [MD5](https://datatracker.ietf.org/doc/html/rfc1321) | ✔️ |
| [RIPEMD-160](https://homes.esat.kuleuven.be/~bosselae/ripemd160.html) | ✔️ |
| [SHA-1](https://datatracker.ietf.org/doc/html/rfc3174) | ✔️ |
| [SHA-2](https://csrc.nist.gov/csrc/media/publications/fips/180/2/archive/2002-08-01/documents/fips180-2.pdf) | ✔️ |
| [SHA-3](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) | ✔️ |
| [SHAKE](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) | ✔️ |
| [Skein-512](https://www.schneier.com/academic/skein/) | ✔️ |
| [SM3](https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02) | ✔️ |
| [Streebog](https://datatracker.ietf.org/doc/html/rfc6986) | ✔️ |
| [Tiger](https://www.cs.technion.ac.il/~biham/Reports/Tiger/) | ✔️ |
| [Whirlpool](https://web.archive.org/web/20171129084214/http://www.larc.usp.br/~pbarreto/WhirlpoolPage.html) | ✔️ |
#### High level API
Each hash algorithm contains a procedure group named `hash`, or if the algorithm provides more than one digest size `hash_<size>`.
Included in these groups are four procedures.
* `hash_string` - Hash a given string and return the computed hash. Just calls `hash_bytes` internally
* `hash_bytes` - Hash a given byte slice and return the computed hash
* `hash_stream` - Takes a stream from io.Stream and returns the computed hash from it
* `hash_file` - Takes a file handle and returns the computed hash from it. A second optional boolean parameter controls if the file is streamed (this is the default) or read at once (set to true)
#### Low level API
The above mentioned procedures internally call three procedures: `init`, `update` and `final`.
You may also directly call them, if you wish.
#### Example
```odin
package crypto_example
// Import the desired package
import "vendor:botan/md4"
main :: proc() {
input := "foo"
// Compute the hash, using the high level API
computed_hash := md4.hash(input)
// Compute the hash, using the low level API
// @note: Botan's structs are opaque by design, they don't expose any fields
ctx: md4.Md4_Context
computed_hash_low: [16]byte
md4.init(&ctx)
md4.update(&ctx, transmute([]byte)input)
md4.final(&ctx, computed_hash_low[:])
}
```
For example uses of all available algorithms, please see the tests within `tests/vendor/botan`.
### License
This library is made available under the BSD-3 license.
BIN
View File
Binary file not shown.
+470
View File
@@ -0,0 +1,470 @@
package botan_bindings
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog: Initial creation and testing of the bindings.
Bindings for the Botan crypto library.
Created for version 2.18.1, using the provided FFI header within Botan.
The "botan_" prefix has been stripped from the identifiers to remove redundancy,
since the package is already named botan.
*/
import "core:c"
FFI_ERROR :: #type c.int
FFI_SUCCESS :: FFI_ERROR(0)
FFI_INVALID_VERIFIER :: FFI_ERROR(1)
FFI_ERROR_INVALID_INPUT :: FFI_ERROR(-1)
FFI_ERROR_BAD_MAC :: FFI_ERROR(-2)
FFI_ERROR_INSUFFICIENT_BUFFER_SPACE :: FFI_ERROR(-10)
FFI_ERROR_EXCEPTION_THROWN :: FFI_ERROR(-20)
FFI_ERROR_OUT_OF_MEMORY :: FFI_ERROR(-21)
FFI_ERROR_BAD_FLAG :: FFI_ERROR(-30)
FFI_ERROR_NULL_POINTER :: FFI_ERROR(-31)
FFI_ERROR_BAD_PARAMETER :: FFI_ERROR(-32)
FFI_ERROR_KEY_NOT_SET :: FFI_ERROR(-33)
FFI_ERROR_INVALID_KEY_LENGTH :: FFI_ERROR(-34)
FFI_ERROR_NOT_IMPLEMENTED :: FFI_ERROR(-40)
FFI_ERROR_INVALID_OBJECT :: FFI_ERROR(-50)
FFI_ERROR_UNKNOWN_ERROR :: FFI_ERROR(-100)
FFI_HEX_LOWER_CASE :: 1
CIPHER_INIT_FLAG_MASK_DIRECTION :: 1
CIPHER_INIT_FLAG_ENCRYPT :: 0
CIPHER_INIT_FLAG_DECRYPT :: 1
CIPHER_UPDATE_FLAG_FINAL :: 1 << 0
CHECK_KEY_EXPENSIVE_TESTS :: 1
PRIVKEY_EXPORT_FLAG_DER :: 0
PRIVKEY_EXPORT_FLAG_PEM :: 1
PUBKEY_DER_FORMAT_SIGNATURE :: 1
FPE_FLAG_FE1_COMPAT_MODE :: 1
x509_cert_key_constraints :: #type c.int
NO_CONSTRAINTS :: x509_cert_key_constraints(0)
DIGITAL_SIGNATURE :: x509_cert_key_constraints(32768)
NON_REPUDIATION :: x509_cert_key_constraints(16384)
KEY_ENCIPHERMENT :: x509_cert_key_constraints(8192)
DATA_ENCIPHERMENT :: x509_cert_key_constraints(4096)
KEY_AGREEMENT :: x509_cert_key_constraints(2048)
KEY_CERT_SIGN :: x509_cert_key_constraints(1024)
CRL_SIGN :: x509_cert_key_constraints(512)
ENCIPHER_ONLY :: x509_cert_key_constraints(256)
DECIPHER_ONLY :: x509_cert_key_constraints(128)
HASH_SHA1 :: "SHA1"
HASH_SHA_224 :: "SHA-224"
HASH_SHA_256 :: "SHA-256"
HASH_SHA_384 :: "SHA-384"
HASH_SHA_512 :: "SHA-512"
HASH_SHA3_224 :: "SHA-3(224)"
HASH_SHA3_256 :: "SHA-3(256)"
HASH_SHA3_384 :: "SHA-3(384)"
HASH_SHA3_512 :: "SHA-3(512)"
HASH_SHAKE_128 :: "SHAKE-128"
HASH_SHAKE_256 :: "SHAKE-256"
HASH_KECCAK_512 :: "Keccak-1600"
HASH_RIPEMD_160 :: "RIPEMD-160"
HASH_WHIRLPOOL :: "Whirlpool"
HASH_BLAKE2B :: "BLAKE2b"
HASH_MD4 :: "MD4"
HASH_MD5 :: "MD5"
HASH_TIGER_128 :: "Tiger(16,3)"
HASH_TIGER_160 :: "Tiger(20,3)"
HASH_TIGER_192 :: "Tiger(24,3)"
HASH_GOST :: "GOST-34.11"
HASH_STREEBOG_256 :: "Streebog-256"
HASH_STREEBOG_512 :: "Streebog-512"
HASH_SM3 :: "SM3"
HASH_SKEIN_512_256 :: "Skein-512(256)"
HASH_SKEIN_512_512 :: "Skein-512(512)"
// Not real values from Botan, only used for context setup within the crypto lib
HASH_SKEIN_512 :: "SKEIN_512"
MAC_HMAC_SHA1 :: "HMAC(SHA1)"
MAC_HMAC_SHA_224 :: "HMAC(SHA-224)"
MAC_HMAC_SHA_256 :: "HMAC(SHA-256)"
MAC_HMAC_SHA_384 :: "HMAC(SHA-384)"
MAC_HMAC_SHA_512 :: "HMAC(SHA-512)"
MAC_HMAC_MD5 :: "HMAC(MD5)"
hash_struct :: struct{}
hash_t :: ^hash_struct
rng_struct :: struct{}
rng_t :: ^rng_struct
mac_struct :: struct{}
mac_t :: ^mac_struct
cipher_struct :: struct{}
cipher_t :: ^cipher_struct
block_cipher_struct :: struct{}
block_cipher_t :: ^block_cipher_struct
mp_struct :: struct{}
mp_t :: ^mp_struct
privkey_struct :: struct{}
privkey_t :: ^privkey_struct
pubkey_struct :: struct{}
pubkey_t :: ^pubkey_struct
pk_op_encrypt_struct :: struct{}
pk_op_encrypt_t :: ^pk_op_encrypt_struct
pk_op_decrypt_struct :: struct{}
pk_op_decrypt_t :: ^pk_op_decrypt_struct
pk_op_sign_struct :: struct{}
pk_op_sign_t :: ^pk_op_sign_struct
pk_op_verify_struct :: struct{}
pk_op_verify_t :: ^pk_op_verify_struct
pk_op_ka_struct :: struct{}
pk_op_ka_t :: ^pk_op_ka_struct
x509_cert_struct :: struct{}
x509_cert_t :: ^x509_cert_struct
x509_crl_struct :: struct{}
x509_crl_t :: ^x509_crl_struct
hotp_struct :: struct{}
hotp_t :: ^hotp_struct
totp_struct :: struct{}
totp_t :: ^totp_struct
fpe_struct :: struct{}
fpe_t :: ^fpe_struct
when ODIN_OS == "windows" {
foreign import botan_lib "botan.lib"
} else when ODIN_OS == "linux" {
foreign import botan_lib "system:botan-2"
} else when ODIN_OS == "darwin" {
foreign import botan_lib "system:botan-2"
}
@(default_calling_convention="c")
@(link_prefix="botan_")
foreign botan_lib {
error_description :: proc(err: c.int) -> cstring ---
ffi_api_version :: proc() -> c.int ---
ffi_supports_api :: proc(api_version: c.int) -> c.int ---
version_string :: proc() -> cstring ---
version_major :: proc() -> c.int ---
version_minor :: proc() -> c.int ---
version_patch :: proc() -> c.int ---
version_datestamp :: proc() -> c.int ---
constant_time_compare :: proc(x, y: ^c.char, length: c.size_t) -> c.int ---
same_mem :: proc(x, y: ^c.char, length: c.size_t) -> c.int ---
scrub_mem :: proc(mem: rawptr, bytes: c.size_t) -> c.int ---
hex_encode :: proc(x: ^c.char, length: c.size_t, out: ^c.char, flags: c.uint) -> c.int ---
hex_decode :: proc(hex_str: cstring, in_len: c.size_t, out: ^c.char, out_len: c.size_t) -> c.int ---
base64_encode :: proc(x: ^c.char, length: c.size_t, out: ^c.char, out_len: c.size_t) -> c.int ---
base64_decode :: proc(base64_str: cstring, in_len: c.size_t, out: ^c.char, out_len: c.size_t) -> c.int ---
rng_init :: proc(rng: ^rng_t, rng_type: cstring) -> c.int ---
rng_init_custom :: proc(rng_out: ^rng_t, rng_name: cstring, ctx: rawptr,
get_cb: proc(ctx: rawptr, out: ^c.char, out_len: c.size_t) -> ^c.int,
add_entropy_cb: proc(ctx: rawptr, input: ^c.char, length: c.size_t) -> ^c.int,
destroy_cb: proc(ctx: rawptr) -> rawptr) -> c.int ---
rng_get :: proc(rng: rng_t, out: ^c.char, out_len: c.size_t) -> c.int ---
rng_reseed :: proc(rng: rng_t, bits: c.size_t) -> c.int ---
rng_reseed_from_rng :: proc(rng, source_rng: rng_t, bits: c.size_t) -> c.int ---
rng_add_entropy :: proc(rng: rng_t, entropy: ^c.char, entropy_len: c.size_t) -> c.int ---
rng_destroy :: proc(rng: rng_t) -> c.int ---
hash_init :: proc(hash: ^hash_t, hash_name: cstring, flags: c.uint) -> c.int ---
hash_copy_state :: proc(dest: ^hash_t, source: hash_t) -> c.int ---
hash_output_length :: proc(hash: hash_t, output_length: ^c.size_t) -> c.int ---
hash_block_size :: proc(hash: hash_t, block_size: ^c.size_t) -> c.int ---
hash_update :: proc(hash: hash_t, input: ^c.char, input_len: c.size_t) -> c.int ---
hash_final :: proc(hash: hash_t, out: ^c.char) -> c.int ---
hash_clear :: proc(hash: hash_t) -> c.int ---
hash_destroy :: proc(hash: hash_t) -> c.int ---
hash_name :: proc(hash: hash_t, name: ^c.char, name_len: ^c.size_t) -> c.int ---
mac_init :: proc(mac: ^mac_t, hash_name: cstring, flags: c.uint) -> c.int ---
mac_output_length :: proc(mac: mac_t, output_length: ^c.size_t) -> c.int ---
mac_set_key :: proc(mac: mac_t, key: ^c.char, key_len: c.size_t) -> c.int ---
mac_update :: proc(mac: mac_t, buf: ^c.char, length: c.size_t) -> c.int ---
mac_final :: proc(mac: mac_t, out: ^c.char) -> c.int ---
mac_clear :: proc(mac: mac_t) -> c.int ---
mac_name :: proc(mac: mac_t, name: ^c.char, name_len: ^c.size_t) -> c.int ---
mac_get_keyspec :: proc(mac: mac_t, out_minimum_keylength, out_maximum_keylength, out_keylength_modulo: ^c.size_t) -> c.int ---
mac_destroy :: proc(mac: mac_t) -> c.int ---
cipher_init :: proc(cipher: ^cipher_t, name: cstring, flags: c.uint) -> c.int ---
cipher_name :: proc(cipher: cipher_t, name: ^c.char, name_len: ^c.size_t) -> c.int ---
cipher_output_length :: proc(cipher: cipher_t, output_length: ^c.size_t) -> c.int ---
cipher_valid_nonce_length :: proc(cipher: cipher_t, nl: c.size_t) -> c.int ---
cipher_get_tag_length :: proc(cipher: cipher_t, tag_size: ^c.size_t) -> c.int ---
cipher_get_default_nonce_length :: proc(cipher: cipher_t, nl: ^c.size_t) -> c.int ---
cipher_get_update_granularity :: proc(cipher: cipher_t, ug: ^c.size_t) -> c.int ---
cipher_query_keylen :: proc(cipher: cipher_t, out_minimum_keylength, out_maximum_keylength: ^c.size_t) -> c.int ---
cipher_get_keyspec :: proc(cipher: cipher_t, min_keylen, max_keylen, mod_keylen: ^c.size_t) -> c.int ---
cipher_set_key :: proc(cipher: cipher_t, key: ^c.char, key_len: c.size_t) -> c.int ---
cipher_reset :: proc(cipher: cipher_t) -> c.int ---
cipher_set_associated_data :: proc(cipher: cipher_t, ad: ^c.char, ad_len: c.size_t) -> c.int ---
cipher_start :: proc(cipher: cipher_t, nonce: ^c.char, nonce_len: c.size_t) -> c.int ---
cipher_update :: proc(cipher: cipher_t, flags: c.uint, output: ^c.char, output_size: c.size_t, output_written: ^c.size_t,
input_bytes: ^c.char, input_size: c.size_t, input_consumed: ^c.size_t) -> c.int ---
cipher_clear :: proc(hash: cipher_t) -> c.int ---
cipher_destroy :: proc(cipher: cipher_t) -> c.int ---
@(deprecated="Use botan.pwdhash")
pbkdf :: proc(pbkdf_algo: cstring, out: ^c.char, out_len: c.size_t, passphrase: cstring, salt: ^c.char,
salt_len, iterations: c.size_t) -> c.int ---
@(deprecated="Use botan.pwdhash_timed")
pbkdf_timed :: proc(pbkdf_algo: cstring, out: ^c.char, out_len: c.size_t, passphrase: cstring, salt: ^c.char,
salt_len, milliseconds_to_run: c.size_t, out_iterations_used: ^c.size_t) -> c.int ---
pwdhash :: proc(algo: cstring, param1, param2, param3: c.size_t, out: ^c.char, out_len: c.size_t, passphrase: cstring,
passphrase_len: c.size_t, salt: ^c.char, salt_len: c.size_t) -> c.int ---
pwdhash_timed :: proc(algo: cstring, msec: c.uint, param1, param2, param3: c.size_t, out: ^c.char, out_len: c.size_t,
passphrase: cstring, passphrase_len: c.size_t, salt: ^c.char, salt_len: c.size_t) -> c.int ---
@(deprecated="Use botan.pwdhash")
scrypt :: proc(out: ^c.char, out_len: c.size_t, passphrase: cstring, salt: ^c.char, salt_len, N, r, p: c.size_t) -> c.int ---
kdf :: proc(kdf_algo: cstring, out: ^c.char, out_len: c.size_t, secret: ^c.char, secret_lent: c.size_t, salt: ^c.char,
salt_len: c.size_t, label: ^c.char, label_len: c.size_t) -> c.int ---
block_cipher_init :: proc(bc: ^block_cipher_t, name: cstring) -> c.int ---
block_cipher_destroy :: proc(bc: block_cipher_t) -> c.int ---
block_cipher_clear :: proc(bc: block_cipher_t) -> c.int ---
block_cipher_set_key :: proc(bc: block_cipher_t, key: ^c.char, key_len: c.size_t) -> c.int ---
block_cipher_block_size :: proc(bc: block_cipher_t) -> c.int ---
block_cipher_encrypt_blocks :: proc(bc: block_cipher_t, input, out: ^c.char, blocks: c.size_t) -> c.int ---
block_cipher_decrypt_blocks :: proc(bc: block_cipher_t, input, out: ^c.char, blocks: c.size_t) -> c.int ---
block_cipher_name :: proc(bc: block_cipher_t, name: ^c.char, name_len: ^c.size_t) -> c.int ---
block_cipher_get_keyspec :: proc(bc: block_cipher_t, out_minimum_keylength, out_maximum_keylength, out_keylength_modulo: ^c.size_t) -> c.int ---
mp_init :: proc(mp: ^mp_t) -> c.int ---
mp_destroy :: proc(mp: mp_t) -> c.int ---
mp_to_hex :: proc(mp: mp_t, out: ^c.char) -> c.int ---
mp_to_str :: proc(mp: mp_t, base: c.char, out: ^c.char, out_len: ^c.size_t) -> c.int ---
mp_clear :: proc(mp: mp_t) -> c.int ---
mp_set_from_int :: proc(mp: mp_t, initial_value: c.int) -> c.int ---
mp_set_from_mp :: proc(dest, source: mp_t) -> c.int ---
mp_set_from_str :: proc(dest: mp_t, str: cstring) -> c.int ---
mp_set_from_radix_str :: proc(mp: mp_t, str: cstring, radix: c.size_t) -> c.int ---
mp_num_bits :: proc(n: mp_t, bits: ^c.size_t) -> c.int ---
mp_num_bytes :: proc(n: mp_t, bytes: ^c.size_t) -> c.int ---
mp_to_bin :: proc(mp: mp_t, vec: ^c.char) -> c.int ---
mp_from_bin :: proc(mp: mp_t, vec: ^c.char, vec_len: c.size_t) -> c.int ---
mp_to_uint32 :: proc(mp: mp_t, val: ^c.uint) -> c.int ---
mp_is_positive :: proc(mp: mp_t) -> c.int ---
mp_is_negative :: proc(mp: mp_t) -> c.int ---
mp_flip_sign :: proc(mp: mp_t) -> c.int ---
mp_is_zero :: proc(mp: mp_t) -> c.int ---
@(deprecated="Use botan.mp_get_bit(0)")
mp_is_odd :: proc(mp: mp_t) -> c.int ---
@(deprecated="Use botan.mp_get_bit(0)")
mp_is_even :: proc(mp: mp_t) -> c.int ---
mp_add_u32 :: proc(result, x: mp_t, y: c.uint) -> c.int ---
mp_sub_u32 :: proc(result, x: mp_t, y: c.uint) -> c.int ---
mp_add :: proc(result, x, y: mp_t) -> c.int ---
mp_sub :: proc(result, x, y: mp_t) -> c.int ---
mp_mul :: proc(result, x, y: mp_t) -> c.int ---
mp_div :: proc(quotient, remainder, x, y: mp_t) -> c.int ---
mp_mod_mul :: proc(result, x, y, mod: mp_t) -> c.int ---
mp_equal :: proc(x, y: mp_t) -> c.int ---
mp_cmp :: proc(result: ^c.int, x, y: mp_t) -> c.int ---
mp_swap :: proc(x, y: mp_t) -> c.int ---
mp_powmod :: proc(out, base, exponent, modulus: mp_t) -> c.int ---
mp_lshift :: proc(out, input: mp_t, shift: c.size_t) -> c.int ---
mp_rshift :: proc(out, input: mp_t, shift: c.size_t) -> c.int ---
mp_mod_inverse :: proc(out, input, modulus: mp_t) -> c.int ---
mp_rand_bits :: proc(rand_out: mp_t, rng: rng_t, bits: c.size_t) -> c.int ---
mp_rand_range :: proc(rand_out: mp_t, rng: rng_t, lower_bound, upper_bound: mp_t) -> c.int ---
mp_gcd :: proc(out, x, y: mp_t) -> c.int ---
mp_is_prime :: proc(n: mp_t, rng: rng_t, test_prob: c.size_t) -> c.int ---
mp_get_bit :: proc(n: mp_t, bit: c.size_t) -> c.int ---
mp_set_bit :: proc(n: mp_t, bit: c.size_t) -> c.int ---
mp_clear_bit :: proc(n: mp_t, bit: c.size_t) -> c.int ---
bcrypt_generate :: proc(out: ^c.char, out_len: ^c.size_t, password: cstring, rng: rng_t, work_factor: c.size_t, flags: c.uint) -> c.int ---
bcrypt_is_valid :: proc(pass, hash: cstring) -> c.int ---
privkey_create :: proc(key: ^privkey_t, algo_name, algo_params: cstring, rng: rng_t) -> c.int ---
@(deprecated="Use botan.privkey_create")
privkey_check_key :: proc(key: privkey_t, rng: rng_t, flags: c.uint) -> c.int ---
@(deprecated="Use botan.privkey_create")
privkey_create_rsa :: proc(key: ^privkey_t, rng: rng_t, bits: c.size_t) -> c.int ---
@(deprecated="Use botan.privkey_create")
privkey_create_ecdsa :: proc(key: ^privkey_t, rng: rng_t, params: cstring) -> c.int ---
@(deprecated="Use botan.privkey_create")
privkey_create_ecdh :: proc(key: ^privkey_t, rng: rng_t, params: cstring) -> c.int ---
@(deprecated="Use botan.privkey_create")
privkey_create_mceliece :: proc(key: ^privkey_t, rng: rng_t, n, t: c.size_t) -> c.int ---
@(deprecated="Use botan.privkey_create")
privkey_create_dh :: proc(key: ^privkey_t, rng: rng_t, param: cstring) -> c.int ---
privkey_create_dsa :: proc(key: ^privkey_t, rng: rng_t, pbits, qbits: c.size_t) -> c.int ---
privkey_create_elgamal :: proc(key: ^privkey_t, rng: rng_t, pbits, qbits: c.size_t) -> c.int ---
privkey_load :: proc(key: ^privkey_t, rng: rng_t, bits: ^c.char, length: c.size_t, password: cstring) -> c.int ---
privkey_destroy :: proc(key: privkey_t) -> c.int ---
privkey_export :: proc(key: privkey_t, out: ^c.char, out_len: ^c.size_t, flags: c.uint) -> c.int ---
privkey_algo_name :: proc(key: privkey_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
@(deprecated="Use botan.privkey_export_encrypted_pbkdf_{msec,iter}")
privkey_export_encrypted :: proc(key: privkey_t, out: ^c.char, out_len: ^c.size_t, rng: rng_t, passphrase, encryption_algo: cstring, flags: c.uint) -> c.int ---
privkey_export_encrypted_pbkdf_msec :: proc(key: privkey_t, out: ^c.char, out_len: ^c.size_t, rng: rng_t, passphrase: cstring, pbkdf_msec_runtime: c.uint,
pbkdf_iterations_out: ^c.size_t, cipher_algo, pbkdf_algo: cstring, flags: c.uint) -> c.int ---
privkey_export_encrypted_pbkdf_iter :: proc(key: privkey_t, out: ^c.char, out_len: ^c.size_t, rng: rng_t, passphrase: cstring, pbkdf_iterations: c.size_t,
cipher_algo, pbkdf_algo: cstring, flags: c.uint) -> c.int ---
pubkey_load :: proc(key: ^pubkey_t, bits: ^c.char, length: c.size_t) -> c.int ---
privkey_export_pubkey :: proc(out: ^pubkey_t, input: privkey_t) -> c.int ---
pubkey_export :: proc(key: pubkey_t, out: ^c.char, out_len: ^c.size_t, flags: c.uint) -> c.int ---
pubkey_algo_name :: proc(key: pubkey_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
pubkey_check_key :: proc(key: pubkey_t, rng: rng_t, flags: c.uint) -> c.int ---
pubkey_estimated_strength :: proc(key: pubkey_t, estimate: ^c.size_t) -> c.int ---
pubkey_fingerprint :: proc(key: pubkey_t, hash: cstring, out: ^c.char, out_len: ^c.size_t) -> c.int ---
pubkey_destroy :: proc(key: pubkey_t) -> c.int ---
pubkey_get_field :: proc(output: mp_t, key: pubkey_t, field_name: cstring) -> c.int ---
privkey_get_field :: proc(output: mp_t, key: privkey_t, field_name: cstring) -> c.int ---
privkey_load_rsa :: proc(key: ^privkey_t, p, q, e: mp_t) -> c.int ---
privkey_load_rsa_pkcs1 :: proc(key: ^privkey_t, bits: ^c.char, length: c.size_t) -> c.int ---
@(deprecated="Use botan.privkey_get_field")
privkey_rsa_get_p :: proc(p: mp_t, rsa_key: privkey_t) -> c.int ---
@(deprecated="Use botan.privkey_get_field")
privkey_rsa_get_q :: proc(q: mp_t, rsa_key: privkey_t) -> c.int ---
@(deprecated="Use botan.privkey_get_field")
privkey_rsa_get_d :: proc(d: mp_t, rsa_key: privkey_t) -> c.int ---
@(deprecated="Use botan.privkey_get_field")
privkey_rsa_get_n :: proc(n: mp_t, rsa_key: privkey_t) -> c.int ---
@(deprecated="Use botan.privkey_get_field")
privkey_rsa_get_e :: proc(e: mp_t, rsa_key: privkey_t) -> c.int ---
privkey_rsa_get_privkey :: proc(rsa_key: privkey_t, out: ^c.char, out_len: ^c.size_t, flags: c.uint) -> c.int ---
pubkey_load_rsa :: proc(key: ^pubkey_t, n, e: mp_t) -> c.int ---
@(deprecated="Use botan.pubkey_get_field")
pubkey_rsa_get_e :: proc(e: mp_t, rsa_key: pubkey_t) -> c.int ---
@(deprecated="Use botan.pubkey_get_field")
pubkey_rsa_get_n :: proc(n: mp_t, rsa_key: pubkey_t) -> c.int ---
privkey_load_dsa :: proc(key: ^privkey_t, p, q, g, x: mp_t) -> c.int ---
pubkey_load_dsa :: proc(key: ^pubkey_t, p, q, g, y: mp_t) -> c.int ---
@(deprecated="Use botan.pubkey_get_field")
privkey_dsa_get_x :: proc(n: mp_t, key: privkey_t) -> c.int ---
@(deprecated="Use botan.pubkey_get_field")
pubkey_dsa_get_p :: proc(p: mp_t, key: pubkey_t) -> c.int ---
@(deprecated="Use botan.pubkey_get_field")
pubkey_dsa_get_q :: proc(q: mp_t, key: pubkey_t) -> c.int ---
@(deprecated="Use botan.pubkey_get_field")
pubkey_dsa_get_g :: proc(d: mp_t, key: pubkey_t) -> c.int ---
@(deprecated="Use botan.pubkey_get_field")
pubkey_dsa_get_y :: proc(y: mp_t, key: pubkey_t) -> c.int ---
privkey_load_dh :: proc(key: ^privkey_t, p, g, y: mp_t) -> c.int ---
pubkey_load_dh :: proc(key: ^pubkey_t, p, g, x: mp_t) -> c.int ---
privkey_load_elgamal :: proc(key: ^privkey_t, p, g, y: mp_t) -> c.int ---
pubkey_load_elgamal :: proc(key: ^pubkey_t, p, g, x: mp_t) -> c.int ---
privkey_load_ed25519 :: proc(key: ^privkey_t, privkey: [32]c.char) -> c.int ---
pubkey_load_ed25519 :: proc(key: ^pubkey_t, pubkey: [32]c.char) -> c.int ---
privkey_ed25519_get_privkey :: proc(key: ^privkey_t, output: [64]c.char) -> c.int ---
pubkey_ed25519_get_pubkey :: proc(key: ^pubkey_t, pubkey: [32]c.char) -> c.int ---
privkey_load_x25519 :: proc(key: ^privkey_t, privkey: [32]c.char) -> c.int ---
pubkey_load_x25519 :: proc(key: ^pubkey_t, pubkey: [32]c.char) -> c.int ---
privkey_x25519_get_privkey :: proc(key: ^privkey_t, output: [32]c.char) -> c.int ---
pubkey_x25519_get_pubkey :: proc(key: ^pubkey_t, pubkey: [32]c.char) -> c.int ---
privkey_load_ecdsa :: proc(key: ^privkey_t, scalar: mp_t, curve_name: cstring) -> c.int ---
pubkey_load_ecdsa :: proc(key: ^pubkey_t, public_x, public_y: mp_t, curve_name: cstring) -> c.int ---
pubkey_load_ecdh :: proc(key: ^pubkey_t, public_x, public_y: mp_t, curve_name: cstring) -> c.int ---
privkey_load_ecdh :: proc(key: ^privkey_t, scalar: mp_t, curve_name: cstring) -> c.int ---
pubkey_load_sm2 :: proc(key: ^pubkey_t, public_x, public_y: mp_t, curve_name: cstring) -> c.int ---
privkey_load_sm2 :: proc(key: ^privkey_t, scalar: mp_t, curve_name: cstring) -> c.int ---
@(deprecated="Use botan.pubkey_load_sm2")
pubkey_load_sm2_enc :: proc(key: ^pubkey_t, public_x, public_y: mp_t, curve_name: cstring) -> c.int ---
@(deprecated="Use botan.privkey_load_sm2")
privkey_load_sm2_enc :: proc(key: ^privkey_t, scalar: mp_t, curve_name: cstring) -> c.int ---
pubkey_sm2_compute_za :: proc(out: ^c.char, out_len: ^c.size_t, ident, hash_algo: cstring, key: pubkey_t) -> c.int ---
pk_op_encrypt_create :: proc(op: ^pk_op_encrypt_t, key: pubkey_t, padding: cstring, flags: c.uint) -> c.int ---
pk_op_encrypt_destroy :: proc(op: pk_op_encrypt_t) -> c.int ---
pk_op_encrypt_output_length :: proc(op: pk_op_encrypt_t, ptext_len: c.size_t, ctext_len: ^c.size_t) -> c.int ---
pk_op_encrypt :: proc(op: pk_op_encrypt_t, rng: rng_t, out: ^c.char, out_len: ^c.size_t, plaintext: cstring, plaintext_len: c.size_t) -> c.int ---
pk_op_decrypt_create :: proc(op: ^pk_op_decrypt_t, key: privkey_t, padding: cstring, flags: c.uint) -> c.int ---
pk_op_decrypt_destroy :: proc(op: pk_op_decrypt_t) -> c.int ---
pk_op_decrypt_output_length :: proc(op: pk_op_decrypt_t, ptext_len: c.size_t, ctext_len: ^c.size_t) -> c.int ---
pk_op_decrypt :: proc(op: pk_op_decrypt_t, rng: rng_t, out: ^c.char, out_len: ^c.size_t, ciphertext: cstring, ciphertext_len: c.size_t) -> c.int ---
pk_op_sign_create :: proc(op: ^pk_op_sign_t, key: privkey_t, hash_and_padding: cstring, flags: c.uint) -> c.int ---
pk_op_sign_destroy :: proc(op: pk_op_sign_t) -> c.int ---
pk_op_sign_output_length :: proc(op: pk_op_sign_t, olen: ^c.size_t) -> c.int ---
pk_op_sign_update :: proc(op: pk_op_sign_t, input: ^c.char, input_len: c.size_t) -> c.int ---
pk_op_sign_finish :: proc(op: pk_op_sign_t, rng: rng_t, sig: ^c.char, sig_len: ^c.size_t) -> c.int ---
pk_op_verify_create :: proc(op: ^pk_op_verify_t, hash_and_padding: cstring, flags: c.uint) -> c.int ---
pk_op_verify_destroy :: proc(op: pk_op_verify_t) -> c.int ---
pk_op_verify_update :: proc(op: pk_op_verify_t, input: ^c.char, input_len: c.size_t) -> c.int ---
pk_op_verify_finish :: proc(op: pk_op_verify_t, sig: ^c.char, sig_len: c.size_t) -> c.int ---
pk_op_key_agreement_create :: proc(op: ^pk_op_ka_t, kdf: cstring, flags: c.uint) -> c.int ---
pk_op_key_agreement_destroy :: proc(op: pk_op_ka_t) -> c.int ---
pk_op_key_agreement_export_public :: proc(key: privkey_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
pk_op_key_agreement_size :: proc(op: pk_op_ka_t, out_len: ^c.size_t) -> c.int ---
pk_op_key_agreement :: proc(op: pk_op_ka_t, out: ^c.char, out_len: ^c.size_t, other_key: ^c.char, other_key_len: c.size_t, salt: ^c.char,
salt_len: c.size_t) -> c.int ---
pkcs_hash_id :: proc(hash_name: cstring, pkcs_id: ^c.char, pkcs_id_len: ^c.size_t) -> c.int ---
@(deprecated="Poorly specified, avoid in new code")
mceies_encrypt :: proc(mce_key: pubkey_t, rng: rng_t, aead: cstring, pt: ^c.char, pt_len: c.size_t, ad: ^c.char, ad_len: c.size_t,
ct: ^c.char, ct_len: ^c.size_t) -> c.int ---
@(deprecated="Poorly specified, avoid in new code")
mceies_decrypt :: proc(mce_key: privkey_t, aead: cstring, ct: ^c.char, ct_len: c.size_t, ad: ^c.char, ad_len: c.size_t, pt: ^c.char,
pt_len: ^c.size_t) -> c.int ---
x509_cert_load :: proc(cert_obj: ^x509_cert_t, cert: ^c.char, cert_len: c.size_t) -> c.int ---
x509_cert_load_file :: proc(cert_obj: ^x509_cert_t, filename: cstring) -> c.int ---
x509_cert_destroy :: proc(cert: x509_cert_t) -> c.int ---
x509_cert_dup :: proc(new_cert: ^x509_cert_t, cert: x509_cert_t) -> c.int ---
x509_cert_get_time_starts :: proc(cert: x509_cert_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
x509_cert_get_time_expires :: proc(cert: x509_cert_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
x509_cert_not_before :: proc(cert: x509_cert_t, time_since_epoch: ^c.ulonglong) -> c.int ---
x509_cert_not_after :: proc(cert: x509_cert_t, time_since_epoch: ^c.ulonglong) -> c.int ---
x509_cert_get_fingerprint :: proc(cert: x509_cert_t, hash: cstring, out: ^c.char, out_len: ^c.size_t) -> c.int ---
x509_cert_get_serial_number :: proc(cert: x509_cert_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
x509_cert_get_authority_key_id :: proc(cert: x509_cert_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
x509_cert_get_subject_key_id :: proc(cert: x509_cert_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
x509_cert_get_public_key_bits :: proc(cert: x509_cert_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
x509_cert_get_public_key :: proc(cert: x509_cert_t, key: ^pubkey_t) -> c.int ---
x509_cert_get_issuer_dn :: proc(cert: x509_cert_t, key: ^c.char, index: c.size_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
x509_cert_get_subject_dn :: proc(cert: x509_cert_t, key: ^c.char, index: c.size_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
x509_cert_to_string :: proc(cert: x509_cert_t, out: ^c.char, out_len: ^c.size_t) -> c.int ---
x509_cert_allowed_usage :: proc(cert: x509_cert_t, key_usage: c.uint) -> c.int ---
x509_cert_hostname_match :: proc(cert: x509_cert_t, hostname: cstring) -> c.int ---
x509_cert_verify :: proc(validation_result: ^c.int, cert: x509_cert_t, intermediates: ^x509_cert_t, intermediates_len: c.size_t, trusted: ^x509_cert_t,
trusted_len: c.size_t, trusted_path: cstring, required_strength: c.size_t, hostname: cstring, reference_time: c.ulonglong) -> c.int ---
x509_cert_validation_status :: proc(code: c.int) -> cstring ---
x509_crl_load_file :: proc(crl_obj: ^x509_crl_t, crl_path: cstring) -> c.int ---
x509_crl_load :: proc(crl_obj: ^x509_crl_t, crl_bits: ^c.char, crl_bits_len: c.size_t) -> c.int ---
x509_crl_destroy :: proc(crl: x509_crl_t) -> c.int ---
x509_is_revoked :: proc(crl: x509_crl_t, cert: x509_cert_t) -> c.int ---
x509_cert_verify_with_crl :: proc(validation_result: ^c.int, cert: x509_cert_t, intermediates: ^x509_cert_t, intermediates_len: c.size_t, trusted: ^x509_cert_t,
trusted_len: c.size_t, crls: ^x509_crl_t, crls_len: c.size_t, trusted_path: cstring, required_strength: c.size_t,
hostname: cstring, reference_time: c.ulonglong) -> c.int ---
key_wrap3394 :: proc(key: ^c.char, key_len: c.size_t, kek: ^c.char, kek_len: c.size_t, wrapped_key: ^c.char, wrapped_key_len: ^c.size_t) -> c.int ---
key_unwrap3394 :: proc(wrapped_key: ^c.char, wrapped_key_len: c.size_t, kek: ^c.char, kek_len: c.size_t, key: ^c.char, key_len: ^c.size_t) -> c.int ---
hotp_init :: proc(hotp: ^hotp_t, key: ^c.char, key_len: c.size_t, hash_algo: cstring, digits: c.size_t) -> c.int ---
hotp_destroy :: proc(hotp: hotp_t) -> c.int ---
hotp_generate :: proc(hotp: hotp_t, hotp_code: ^c.uint, hotp_counter: c.ulonglong) -> c.int ---
hotp_check :: proc(hotp: hotp_t, next_hotp_counter: ^c.ulonglong, hotp_code: c.uint, hotp_counter: c.ulonglong, resync_range: c.size_t) -> c.int ---
totp_init :: proc(totp: ^totp_t, key: ^c.char, key_len: c.size_t, hash_algo: cstring, digits, time_step: c.size_t) -> c.int ---
totp_destroy :: proc(totp: totp_t) -> c.int ---
totp_generate :: proc(totp: totp_t, totp_code: ^c.uint, timestamp: c.ulonglong) -> c.int ---
totp_check :: proc(totp: totp_t, totp_code: ^c.uint, timestamp: c.ulonglong, acceptable_clock_drift: c.size_t) -> c.int ---
fpe_fe1_init :: proc(fpe: ^fpe_t, n: mp_t, key: ^c.char, key_len, rounds: c.size_t, flags: c.uint) -> c.int ---
fpe_destroy :: proc(fpe: fpe_t) -> c.int ---
fpe_encrypt :: proc(fpe: fpe_t, x: mp_t, tweak: ^c.char, tweak_len: c.size_t) -> c.int ---
fpe_decrypt :: proc(fpe: fpe_t, x: mp_t, tweak: ^c.char, tweak_len: c.size_t) -> c.int ---
}
+98
View File
@@ -0,0 +1,98 @@
package botan_blake2b
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog: Initial implementation.
Interface for the BLAKE2B hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string will hash the given input and return the
// computed hash
hash_string :: proc "contextless" (data: string) -> [64]byte {
return hash_bytes(transmute([]byte)(data))
}
// hash_bytes will hash the given input and return the
// computed hash
hash_bytes :: proc "contextless" (data: []byte) -> [64]byte {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_BLAKE2B, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream will read the stream in chunks and compute a
// hash from its contents
hash_stream :: proc(s: io.Stream) -> ([64]byte, bool) {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_BLAKE2B, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file will read the file provided by the given handle
// and compute a hash
hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
if !load_at_once {
return hash_stream(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes(buf[:]), ok
}
}
return [64]byte{}, false
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
}
/*
Low level API
*/
Blake2b_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t) {
botan.hash_init(ctx, botan.HASH_BLAKE2B, 0)
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+98
View File
@@ -0,0 +1,98 @@
package gost
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog: Initial implementation.
Interface for the GOST hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string will hash the given input and return the
// computed hash
hash_string :: proc "contextless" (data: string) -> [32]byte {
return hash_bytes(transmute([]byte)(data))
}
// hash_bytes will hash the given input and return the
// computed hash
hash_bytes :: proc "contextless" (data: []byte) -> [32]byte {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_GOST, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream will read the stream in chunks and compute a
// hash from its contents
hash_stream :: proc(s: io.Stream) -> ([32]byte, bool) {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_GOST, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file will read the file provided by the given handle
// and compute a hash
hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
if !load_at_once {
return hash_stream(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes(buf[:]), ok
}
}
return [32]byte{}, false
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
}
/*
Low level API
*/
Gost_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t) {
botan.hash_init(ctx, botan.HASH_GOST, 0)
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+98
View File
@@ -0,0 +1,98 @@
package keccak
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog, dotbmp: Initial implementation.
Interface for the Keccak hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string_512 will hash the given input and return the
// computed hash
hash_string_512 :: proc(data: string) -> [64]byte {
return hash_bytes_512(transmute([]byte)(data))
}
// hash_bytes_512 will hash the given input and return the
// computed hash
hash_bytes_512 :: proc(data: []byte) -> [64]byte {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_KECCAK_512, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_512 will read the stream in chunks and compute a
// hash from its contents
hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_KECCAK_512, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_512 will read the file provided by the given handle
// and compute a hash
hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
if !load_at_once {
return hash_stream_512(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_512(buf[:]), ok
}
}
return [64]byte{}, false
}
hash_512 :: proc {
hash_stream_512,
hash_file_512,
hash_bytes_512,
hash_string_512,
}
/*
Low level API
*/
Keccak_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t) {
botan.hash_init(ctx, botan.HASH_KECCAK_512, 0)
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+98
View File
@@ -0,0 +1,98 @@
package md4
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog: Initial implementation.
Interface for the MD4 hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string will hash the given input and return the
// computed hash
hash_string :: proc "contextless" (data: string) -> [16]byte {
return hash_bytes(transmute([]byte)(data))
}
// hash_bytes will hash the given input and return the
// computed hash
hash_bytes :: proc "contextless" (data: []byte) -> [16]byte {
hash: [16]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_MD4, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream will read the stream in chunks and compute a
// hash from its contents
hash_stream :: proc(s: io.Stream) -> ([16]byte, bool) {
hash: [16]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_MD4, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file will read the file provided by the given handle
// and compute a hash
hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
if !load_at_once {
return hash_stream(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes(buf[:]), ok
}
}
return [16]byte{}, false
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
}
/*
Low level API
*/
Md4_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t) {
botan.hash_init(ctx, botan.HASH_MD4, 0)
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+98
View File
@@ -0,0 +1,98 @@
package md5
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog: Initial implementation.
Interface for the MD5 hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string will hash the given input and return the
// computed hash
hash_string :: proc "contextless" (data: string) -> [16]byte {
return hash_bytes(transmute([]byte)(data))
}
// hash_bytes will hash the given input and return the
// computed hash
hash_bytes :: proc "contextless" (data: []byte) -> [16]byte {
hash: [16]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_MD5, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream will read the stream in chunks and compute a
// hash from its contents
hash_stream :: proc(s: io.Stream) -> ([16]byte, bool) {
hash: [16]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_MD5, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file will read the file provided by the given handle
// and compute a hash
hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
if !load_at_once {
return hash_stream(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes(buf[:]), ok
}
}
return [16]byte{}, false
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
}
/*
Low level API
*/
Md5_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t) {
botan.hash_init(ctx, botan.HASH_MD5, 0)
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+98
View File
@@ -0,0 +1,98 @@
package ripemd
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog, dotbmp: Initial implementation.
Interface for the RIPEMD-160 hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string_160 will hash the given input and return the
// computed hash
hash_string_160 :: proc(data: string) -> [20]byte {
return hash_bytes_160(transmute([]byte)(data))
}
// hash_bytes_160 will hash the given input and return the
// computed hash
hash_bytes_160 :: proc(data: []byte) -> [20]byte {
hash: [20]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_RIPEMD_160, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_160 will read the stream in chunks and compute a
// hash from its contents
hash_stream_160 :: proc(s: io.Stream) -> ([20]byte, bool) {
hash: [20]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_RIPEMD_160, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_160 will read the file provided by the given handle
// and compute a hash
hash_file_160 :: proc(hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
if !load_at_once {
return hash_stream_160(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_160(buf[:]), ok
}
}
return [20]byte{}, false
}
hash_160 :: proc {
hash_stream_160,
hash_file_160,
hash_bytes_160,
hash_string_160,
}
/*
Low level API
*/
Ripemd160_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t) {
botan.hash_init(ctx, botan.HASH_RIPEMD_160, 0)
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+98
View File
@@ -0,0 +1,98 @@
package sha1
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog: Initial implementation.
Interface for the SHA-1 hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string will hash the given input and return the
// computed hash
hash_string :: proc "contextless" (data: string) -> [20]byte {
return hash_bytes(transmute([]byte)(data))
}
// hash_bytes will hash the given input and return the
// computed hash
hash_bytes :: proc "contextless" (data: []byte) -> [20]byte {
hash: [20]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA1, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream will read the stream in chunks and compute a
// hash from its contents
hash_stream :: proc(s: io.Stream) -> ([20]byte, bool) {
hash: [20]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA1, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file will read the file provided by the given handle
// and compute a hash
hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
if !load_at_once {
return hash_stream(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes(buf[:]), ok
}
}
return [20]byte{}, false
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
}
/*
Low level API
*/
Sha1_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t) {
botan.hash_init(ctx, botan.HASH_SHA1, 0)
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+277
View File
@@ -0,0 +1,277 @@
package sha2
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog, dotbmp: Initial implementation.
Interface for the SHA-2 hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string_224 will hash the given input and return the
// computed hash
hash_string_224 :: proc(data: string) -> [28]byte {
return hash_bytes_224(transmute([]byte)(data))
}
// hash_bytes_224 will hash the given input and return the
// computed hash
hash_bytes_224 :: proc(data: []byte) -> [28]byte {
hash: [28]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA_224, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_224 will read the stream in chunks and compute a
// hash from its contents
hash_stream_224 :: proc(s: io.Stream) -> ([28]byte, bool) {
hash: [28]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA_224, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_224 will read the file provided by the given handle
// and compute a hash
hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
if !load_at_once {
return hash_stream_224(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_224(buf[:]), ok
}
}
return [28]byte{}, false
}
hash_224 :: proc {
hash_stream_224,
hash_file_224,
hash_bytes_224,
hash_string_224,
}
// hash_string_256 will hash the given input and return the
// computed hash
hash_string_256 :: proc(data: string) -> [32]byte {
return hash_bytes_256(transmute([]byte)(data))
}
// hash_bytes_256 will hash the given input and return the
// computed hash
hash_bytes_256 :: proc(data: []byte) -> [32]byte {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA_256, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_256 will read the stream in chunks and compute a
// hash from its contents
hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA_256, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_256 will read the file provided by the given handle
// and compute a hash
hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
if !load_at_once {
return hash_stream_256(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_256(buf[:]), ok
}
}
return [32]byte{}, false
}
hash_256 :: proc {
hash_stream_256,
hash_file_256,
hash_bytes_256,
hash_string_256,
}
// hash_string_384 will hash the given input and return the
// computed hash
hash_string_384 :: proc(data: string) -> [48]byte {
return hash_bytes_384(transmute([]byte)(data))
}
// hash_bytes_384 will hash the given input and return the
// computed hash
hash_bytes_384 :: proc(data: []byte) -> [48]byte {
hash: [48]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA_384, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_384 will read the stream in chunks and compute a
// hash from its contents
hash_stream_384 :: proc(s: io.Stream) -> ([48]byte, bool) {
hash: [48]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA_384, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_384 will read the file provided by the given handle
// and compute a hash
hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
if !load_at_once {
return hash_stream_384(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_384(buf[:]), ok
}
}
return [48]byte{}, false
}
hash_384 :: proc {
hash_stream_384,
hash_file_384,
hash_bytes_384,
hash_string_384,
}
// hash_string_512 will hash the given input and return the
// computed hash
hash_string_512 :: proc(data: string) -> [64]byte {
return hash_bytes_512(transmute([]byte)(data))
}
// hash_bytes_512 will hash the given input and return the
// computed hash
hash_bytes_512 :: proc(data: []byte) -> [64]byte {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA_512, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_512 will read the stream in chunks and compute a
// hash from its contents
hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA_512, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_512 will read the file provided by the given handle
// and compute a hash
hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
if !load_at_once {
return hash_stream_512(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_512(buf[:]), ok
}
}
return [64]byte{}, false
}
hash_512 :: proc {
hash_stream_512,
hash_file_512,
hash_bytes_512,
hash_string_512,
}
/*
Low level API
*/
Sha2_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t, hash_size := 512) {
switch hash_size {
case 224: botan.hash_init(ctx, botan.HASH_SHA_224, 0)
case 256: botan.hash_init(ctx, botan.HASH_SHA_256, 0)
case 384: botan.hash_init(ctx, botan.HASH_SHA_384, 0)
case 512: botan.hash_init(ctx, botan.HASH_SHA_512, 0)
}
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+277
View File
@@ -0,0 +1,277 @@
package sha3
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog, dotbmp: Initial implementation.
Interface for the SHA-3 hashing algorithm. Variants for Keccak and SHAKE can be found in the appropriate packages.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string_224 will hash the given input and return the
// computed hash
hash_string_224 :: proc(data: string) -> [28]byte {
return hash_bytes_224(transmute([]byte)(data))
}
// hash_bytes_224 will hash the given input and return the
// computed hash
hash_bytes_224 :: proc(data: []byte) -> [28]byte {
hash: [28]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA3_224, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_224 will read the stream in chunks and compute a
// hash from its contents
hash_stream_224 :: proc(s: io.Stream) -> ([28]byte, bool) {
hash: [28]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA3_224, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_224 will read the file provided by the given handle
// and compute a hash
hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
if !load_at_once {
return hash_stream_224(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_224(buf[:]), ok
}
}
return [28]byte{}, false
}
hash_224 :: proc {
hash_stream_224,
hash_file_224,
hash_bytes_224,
hash_string_224,
}
// hash_string_256 will hash the given input and return the
// computed hash
hash_string_256 :: proc(data: string) -> [32]byte {
return hash_bytes_256(transmute([]byte)(data))
}
// hash_bytes_256 will hash the given input and return the
// computed hash
hash_bytes_256 :: proc(data: []byte) -> [32]byte {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA3_256, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_256 will read the stream in chunks and compute a
// hash from its contents
hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA3_256, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_256 will read the file provided by the given handle
// and compute a hash
hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
if !load_at_once {
return hash_stream_256(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_256(buf[:]), ok
}
}
return [32]byte{}, false
}
hash_256 :: proc {
hash_stream_256,
hash_file_256,
hash_bytes_256,
hash_string_256,
}
// hash_string_384 will hash the given input and return the
// computed hash
hash_string_384 :: proc(data: string) -> [48]byte {
return hash_bytes_384(transmute([]byte)(data))
}
// hash_bytes_384 will hash the given input and return the
// computed hash
hash_bytes_384 :: proc(data: []byte) -> [48]byte {
hash: [48]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA3_384, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_384 will read the stream in chunks and compute a
// hash from its contents
hash_stream_384 :: proc(s: io.Stream) -> ([48]byte, bool) {
hash: [48]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA3_384, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_384 will read the file provided by the given handle
// and compute a hash
hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
if !load_at_once {
return hash_stream_384(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_384(buf[:]), ok
}
}
return [48]byte{}, false
}
hash_384 :: proc {
hash_stream_384,
hash_file_384,
hash_bytes_384,
hash_string_384,
}
// hash_string_512 will hash the given input and return the
// computed hash
hash_string_512 :: proc(data: string) -> [64]byte {
return hash_bytes_512(transmute([]byte)(data))
}
// hash_bytes_512 will hash the given input and return the
// computed hash
hash_bytes_512 :: proc(data: []byte) -> [64]byte {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA3_512, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_512 will read the stream in chunks and compute a
// hash from its contents
hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHA3_512, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_512 will read the file provided by the given handle
// and compute a hash
hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
if !load_at_once {
return hash_stream_512(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_512(buf[:]), ok
}
}
return [64]byte{}, false
}
hash_512 :: proc {
hash_stream_512,
hash_file_512,
hash_bytes_512,
hash_string_512,
}
/*
Low level API
*/
Sha3_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t, hash_size := 512) {
switch hash_size {
case 224: botan.hash_init(ctx, botan.HASH_SHA3_224, 0)
case 256: botan.hash_init(ctx, botan.HASH_SHA3_256, 0)
case 384: botan.hash_init(ctx, botan.HASH_SHA3_384, 0)
case 512: botan.hash_init(ctx, botan.HASH_SHA3_512, 0)
}
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+159
View File
@@ -0,0 +1,159 @@
package shake
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog, dotbmp: Initial implementation.
Interface for the SHAKE hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string_128 will hash the given input and return the
// computed hash
hash_string_128 :: proc(data: string) -> [16]byte {
return hash_bytes_128(transmute([]byte)(data))
}
// hash_bytes_128 will hash the given input and return the
// computed hash
hash_bytes_128 :: proc(data: []byte) -> [16]byte {
hash: [16]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHAKE_128, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_128 will read the stream in chunks and compute a
// hash from its contents
hash_stream_128 :: proc(s: io.Stream) -> ([16]byte, bool) {
hash: [16]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHAKE_128, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_128 will read the file provided by the given handle
// and compute a hash
hash_file_128 :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
if !load_at_once {
return hash_stream_128(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_128(buf[:]), ok
}
}
return [16]byte{}, false
}
hash_128 :: proc {
hash_stream_128,
hash_file_128,
hash_bytes_128,
hash_string_128,
}
// hash_string_256 will hash the given input and return the
// computed hash
hash_string_256 :: proc(data: string) -> [32]byte {
return hash_bytes_256(transmute([]byte)(data))
}
// hash_bytes_256 will hash the given input and return the
// computed hash
hash_bytes_256 :: proc(data: []byte) -> [32]byte {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHAKE_256, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_256 will read the stream in chunks and compute a
// hash from its contents
hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SHAKE_256, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_256 will read the file provided by the given handle
// and compute a hash
hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
if !load_at_once {
return hash_stream_256(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_256(buf[:]), ok
}
}
return [32]byte{}, false
}
hash_256 :: proc {
hash_stream_256,
hash_file_256,
hash_bytes_256,
hash_string_256,
}
/*
Low level API
*/
Shake_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t, hash_size := 256) {
switch hash_size {
case 128: botan.hash_init(ctx, botan.HASH_SHAKE_128, 0)
case 256: botan.hash_init(ctx, botan.HASH_SHAKE_256, 0)
}
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+220
View File
@@ -0,0 +1,220 @@
package skein512
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog, dotbmp: Initial implementation.
Interface for the SKEIN-512 hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import "core:strings"
import "core:fmt"
import botan "../bindings"
/*
High level API
*/
// hash_string_256 will hash the given input and return the
// computed hash
hash_string_256 :: proc(data: string) -> [32]byte {
return hash_bytes_256(transmute([]byte)(data))
}
// hash_bytes_256 will hash the given input and return the
// computed hash
hash_bytes_256 :: proc(data: []byte) -> [32]byte {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SKEIN_512_256, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_256 will read the stream in chunks and compute a
// hash from its contents
hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SKEIN_512_256, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_256 will read the file provided by the given handle
// and compute a hash
hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
if !load_at_once {
return hash_stream_256(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_256(buf[:]), ok
}
}
return [32]byte{}, false
}
hash_256 :: proc {
hash_stream_256,
hash_file_256,
hash_bytes_256,
hash_string_256,
}
// hash_string_512 will hash the given input and return the
// computed hash
hash_string_512 :: proc(data: string) -> [64]byte {
return hash_bytes_512(transmute([]byte)(data))
}
// hash_bytes_512 will hash the given input and return the
// computed hash
hash_bytes_512 :: proc(data: []byte) -> [64]byte {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SKEIN_512_512, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_512 will read the stream in chunks and compute a
// hash from its contents
hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SKEIN_512_512, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_512 will read the file provided by the given handle
// and compute a hash
hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
if !load_at_once {
return hash_stream_512(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_512(buf[:]), ok
}
}
return [64]byte{}, false
}
hash_512 :: proc {
hash_stream_512,
hash_file_512,
hash_bytes_512,
hash_string_512,
}
// hash_string_slice will hash the given input and return the
// computed hash
hash_string_slice :: proc(data: string, bit_size: int, allocator := context.allocator) -> []byte {
return hash_bytes_slice(transmute([]byte)(data), bit_size, allocator)
}
// hash_bytes_slice will hash the given input and return the
// computed hash
hash_bytes_slice :: proc(data: []byte, bit_size: int, allocator := context.allocator) -> []byte {
hash := make([]byte, bit_size, allocator)
ctx: botan.hash_t
botan.hash_init(&ctx, strings.unsafe_string_to_cstring(fmt.tprintf("Skein-512(%d)", bit_size * 8)), 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_slice will read the stream in chunks and compute a
// hash from its contents
hash_stream_slice :: proc(s: io.Stream, bit_size: int, allocator := context.allocator) -> ([]byte, bool) {
hash := make([]byte, bit_size, allocator)
ctx: botan.hash_t
botan.hash_init(&ctx, strings.unsafe_string_to_cstring(fmt.tprintf("Skein-512(%d)", bit_size * 8)), 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_slice will read the file provided by the given handle
// and compute a hash
hash_file_slice :: proc(hd: os.Handle, bit_size: int, load_at_once := false, allocator := context.allocator) -> ([]byte, bool) {
if !load_at_once {
return hash_stream_slice(os.stream_from_handle(hd), bit_size, allocator)
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_slice(buf[:], bit_size, allocator), ok
}
}
return nil, false
}
hash_slice :: proc {
hash_stream_slice,
hash_file_slice,
hash_bytes_slice,
hash_string_slice,
}
/*
Low level API
*/
Skein512_Context :: botan.hash_t
init :: proc(ctx: ^botan.hash_t, hash_size := 512) {
switch hash_size {
case 256: botan.hash_init(ctx, botan.HASH_SKEIN_512_256, 0)
case 512: botan.hash_init(ctx, botan.HASH_SKEIN_512_512, 0)
case: botan.hash_init(ctx, strings.unsafe_string_to_cstring(fmt.tprintf("Skein-512(%d)", hash_size)), 0)
}
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+98
View File
@@ -0,0 +1,98 @@
package sm3
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog: Initial implementation.
Interface for the SM3 hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string will hash the given input and return the
// computed hash
hash_string :: proc "contextless" (data: string) -> [32]byte {
return hash_bytes(transmute([]byte)(data))
}
// hash_bytes will hash the given input and return the
// computed hash
hash_bytes :: proc "contextless" (data: []byte) -> [32]byte {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SM3, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream will read the stream in chunks and compute a
// hash from its contents
hash_stream :: proc(s: io.Stream) -> ([32]byte, bool) {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_SM3, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file will read the file provided by the given handle
// and compute a hash
hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
if !load_at_once {
return hash_stream(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes(buf[:]), ok
}
}
return [32]byte{}, false
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
}
/*
Low level API
*/
Sm3_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t) {
botan.hash_init(ctx, botan.HASH_SM3, 0)
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+159
View File
@@ -0,0 +1,159 @@
package streebog
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog: Initial implementation.
Interface for the Streebog hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string_256 will hash the given input and return the
// computed hash
hash_string_256 :: proc(data: string) -> [32]byte {
return hash_bytes_256(transmute([]byte)(data))
}
// hash_bytes_256 will hash the given input and return the
// computed hash
hash_bytes_256 :: proc(data: []byte) -> [32]byte {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_STREEBOG_256, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_256 will read the stream in chunks and compute a
// hash from its contents
hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
hash: [32]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_STREEBOG_256, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_256 will read the file provided by the given handle
// and compute a hash
hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
if !load_at_once {
return hash_stream_256(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_256(buf[:]), ok
}
}
return [32]byte{}, false
}
hash_256 :: proc {
hash_stream_256,
hash_file_256,
hash_bytes_256,
hash_string_256,
}
// hash_string_512 will hash the given input and return the
// computed hash
hash_string_512 :: proc(data: string) -> [64]byte {
return hash_bytes_512(transmute([]byte)(data))
}
// hash_bytes_512 will hash the given input and return the
// computed hash
hash_bytes_512 :: proc(data: []byte) -> [64]byte {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_STREEBOG_512, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_512 will read the stream in chunks and compute a
// hash from its contents
hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_STREEBOG_512, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_512 will read the file provided by the given handle
// and compute a hash
hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
if !load_at_once {
return hash_stream_512(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_512(buf[:]), ok
}
}
return [64]byte{}, false
}
hash_512 :: proc {
hash_stream_512,
hash_file_512,
hash_bytes_512,
hash_string_512,
}
/*
Low level API
*/
Streebog_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t, hash_size := 512) {
switch hash_size {
case 256: botan.hash_init(ctx, botan.HASH_STREEBOG_256, 0)
case 512: botan.hash_init(ctx, botan.HASH_STREEBOG_512, 0)
}
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+218
View File
@@ -0,0 +1,218 @@
package tiger
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog: Initial implementation.
Interface for the Tiger hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string_128 will hash the given input and return the
// computed hash
hash_string_128 :: proc(data: string) -> [16]byte {
return hash_bytes_128(transmute([]byte)(data))
}
// hash_bytes_128 will hash the given input and return the
// computed hash
hash_bytes_128 :: proc(data: []byte) -> [16]byte {
hash: [16]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_TIGER_128, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_128 will read the stream in chunks and compute a
// hash from its contents
hash_stream_128 :: proc(s: io.Stream) -> ([16]byte, bool) {
hash: [16]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_TIGER_128, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_128 will read the file provided by the given handle
// and compute a hash
hash_file_128 :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
if !load_at_once {
return hash_stream_128(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_128(buf[:]), ok
}
}
return [16]byte{}, false
}
hash_128 :: proc {
hash_stream_128,
hash_file_128,
hash_bytes_128,
hash_string_128,
}
// hash_string_160 will hash the given input and return the
// computed hash
hash_string_160 :: proc(data: string) -> [20]byte {
return hash_bytes_160(transmute([]byte)(data))
}
// hash_bytes_160 will hash the given input and return the
// computed hash
hash_bytes_160 :: proc(data: []byte) -> [20]byte {
hash: [20]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_TIGER_160, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_160 will read the stream in chunks and compute a
// hash from its contents
hash_stream_160 :: proc(s: io.Stream) -> ([20]byte, bool) {
hash: [20]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_TIGER_160, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_160 will read the file provided by the given handle
// and compute a hash
hash_file_160 :: proc(hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
if !load_at_once {
return hash_stream_160(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_160(buf[:]), ok
}
}
return [20]byte{}, false
}
hash_160 :: proc {
hash_stream_160,
hash_file_160,
hash_bytes_160,
hash_string_160,
}
// hash_string_192 will hash the given input and return the
// computed hash
hash_string_192 :: proc(data: string) -> [24]byte {
return hash_bytes_192(transmute([]byte)(data))
}
// hash_bytes_192 will hash the given input and return the
// computed hash
hash_bytes_192 :: proc(data: []byte) -> [24]byte {
hash: [24]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_TIGER_192, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream_192 will read the stream in chunks and compute a
// hash from its contents
hash_stream_192 :: proc(s: io.Stream) -> ([24]byte, bool) {
hash: [24]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_TIGER_192, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file_192 will read the file provided by the given handle
// and compute a hash
hash_file_192 :: proc(hd: os.Handle, load_at_once := false) -> ([24]byte, bool) {
if !load_at_once {
return hash_stream_192(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_192(buf[:]), ok
}
}
return [24]byte{}, false
}
hash_192 :: proc {
hash_stream_192,
hash_file_192,
hash_bytes_192,
hash_string_192,
}
/*
Low level API
*/
Tiger_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t, hash_size := 192) {
switch hash_size {
case 128: botan.hash_init(ctx, botan.HASH_TIGER_128, 0)
case 160: botan.hash_init(ctx, botan.HASH_TIGER_160, 0)
case 192: botan.hash_init(ctx, botan.HASH_TIGER_192, 0)
}
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+98
View File
@@ -0,0 +1,98 @@
package whirlpool
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog: Initial implementation.
Interface for the WHIRLPOOL hashing algorithm.
The hash will be computed via bindings to the Botan crypto library
*/
import "core:os"
import "core:io"
import botan "../bindings"
/*
High level API
*/
// hash_string will hash the given input and return the
// computed hash
hash_string :: proc "contextless" (data: string) -> [64]byte {
return hash_bytes(transmute([]byte)(data))
}
// hash_bytes will hash the given input and return the
// computed hash
hash_bytes :: proc "contextless" (data: []byte) -> [64]byte {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_WHIRLPOOL, 0)
botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash
}
// hash_stream will read the stream in chunks and compute a
// hash from its contents
hash_stream :: proc(s: io.Stream) -> ([64]byte, bool) {
hash: [64]byte
ctx: botan.hash_t
botan.hash_init(&ctx, botan.HASH_WHIRLPOOL, 0)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = s->impl_read(buf)
if i > 0 {
botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
}
}
botan.hash_final(ctx, &hash[0])
botan.hash_destroy(ctx)
return hash, true
}
// hash_file will read the file provided by the given handle
// and compute a hash
hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
if !load_at_once {
return hash_stream(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes(buf[:]), ok
}
}
return [64]byte{}, false
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
}
/*
Low level API
*/
Whirlpool_Context :: botan.hash_t
init :: proc "contextless" (ctx: ^botan.hash_t) {
botan.hash_init(ctx, botan.HASH_WHIRLPOOL, 0)
}
update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}