core/crypto: Exile keccak, md5 and sha1 to legacy

In an perfect world these would just be removed, but the world is
imperfect, and people are forced to interact/interface with things
that are broken.
This commit is contained in:
Yawning Angel
2023-11-17 19:32:11 +09:00
parent 4587a55486
commit 59950bcad6
14 changed files with 42 additions and 22 deletions
+10
View File
@@ -0,0 +1,10 @@
# crypto/legacy
These are algorithms that are shipped solely for the purpose of
interoperability with legacy systems. The use of these packages in
any other capacity is discouraged, especially those that are known
to be broken.
- keccak - The draft version of the algorithm that became SHA-3
- MD5 - Broken (https://eprint.iacr.org/2005/075)
- SHA-1 - Broken (https://eprint.iacr.org/2017/190)
+118
View File
@@ -0,0 +1,118 @@
package vendor_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
*/
DIGEST_SIZE_512 :: 64
// hash_string_512 will hash the given input and return the
// computed hash
hash_string_512 :: proc(data: string) -> [DIGEST_SIZE_512]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) -> [DIGEST_SIZE_512]byte {
hash: [DIGEST_SIZE_512]byte
ctx: Context
init(&ctx)
update(&ctx, data)
final(&ctx, hash[:])
return hash
}
// hash_string_to_buffer_512 will hash the given input and assign the
// 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 will hash the given input and write the
// computed hash into the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_bytes_to_buffer_512 :: proc(data, hash: []byte) {
assert(len(hash) >= DIGEST_SIZE_512, "Size of destination buffer is smaller than the digest size")
ctx: Context
init(&ctx)
update(&ctx, data)
final(&ctx, hash[:])
}
// hash_stream_512 will read the stream in chunks and compute a
// hash from its contents
hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
hash: [DIGEST_SIZE_512]byte
ctx: Context
init(&ctx)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = io.read(s, buf)
if i > 0 {
update(&ctx, buf[:i])
}
}
final(&ctx, hash[:])
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) -> ([DIGEST_SIZE_512]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 [DIGEST_SIZE_512]byte{}, false
}
hash_512 :: proc {
hash_stream_512,
hash_file_512,
hash_bytes_512,
hash_string_512,
hash_bytes_to_buffer_512,
hash_string_to_buffer_512,
}
/*
Low level API
*/
Context :: botan.hash_t
init :: proc "contextless" (ctx: ^Context) {
botan.hash_init(ctx, botan.HASH_KECCAK_512, 0)
}
update :: proc "contextless" (ctx: ^Context, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^Context, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+118
View File
@@ -0,0 +1,118 @@
package vendor_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
*/
DIGEST_SIZE :: 16
// hash_string will hash the given input and return the
// computed hash
hash_string :: proc "contextless" (data: string) -> [DIGEST_SIZE]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) -> [DIGEST_SIZE]byte {
hash: [DIGEST_SIZE]byte
ctx: Context
init(&ctx)
update(&ctx, data)
final(&ctx, hash[:])
return hash
}
// hash_string_to_buffer will hash the given input and assign the
// 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 will hash the given input and write the
// computed hash into the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_bytes_to_buffer :: proc(data, hash: []byte) {
assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size")
ctx: Context
init(&ctx)
update(&ctx, data)
final(&ctx, hash[:])
}
// hash_stream will read the stream in chunks and compute a
// hash from its contents
hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
hash: [DIGEST_SIZE]byte
ctx: Context
init(&ctx)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = io.read(s, buf)
if i > 0 {
update(&ctx, buf[:i])
}
}
final(&ctx, hash[:])
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) -> ([DIGEST_SIZE]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 [DIGEST_SIZE]byte{}, false
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
hash_bytes_to_buffer,
hash_string_to_buffer,
}
/*
Low level API
*/
Context :: botan.hash_t
init :: proc "contextless" (ctx: ^Context) {
botan.hash_init(ctx, botan.HASH_MD5, 0)
}
update :: proc "contextless" (ctx: ^Context, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^Context, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}
+118
View File
@@ -0,0 +1,118 @@
package vendor_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
*/
DIGEST_SIZE :: 20
// hash_string will hash the given input and return the
// computed hash
hash_string :: proc "contextless" (data: string) -> [DIGEST_SIZE]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) -> [DIGEST_SIZE]byte {
hash: [DIGEST_SIZE]byte
ctx: Context
init(&ctx)
update(&ctx, data)
final(&ctx, hash[:])
return hash
}
// hash_string_to_buffer will hash the given input and assign the
// 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 will hash the given input and write the
// computed hash into the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_bytes_to_buffer :: proc(data, hash: []byte) {
assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size")
ctx: Context
init(&ctx)
update(&ctx, data)
final(&ctx, hash[:])
}
// hash_stream will read the stream in chunks and compute a
// hash from its contents
hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
hash: [DIGEST_SIZE]byte
ctx: Context
init(&ctx)
buf := make([]byte, 512)
defer delete(buf)
i := 1
for i > 0 {
i, _ = io.read(s, buf)
if i > 0 {
update(&ctx, buf[:i])
}
}
final(&ctx, hash[:])
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) -> ([DIGEST_SIZE]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 [DIGEST_SIZE]byte{}, false
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
hash_bytes_to_buffer,
hash_string_to_buffer,
}
/*
Low level API
*/
Context :: botan.hash_t
init :: proc "contextless" (ctx: ^Context) {
botan.hash_init(ctx, botan.HASH_SHA1, 0)
}
update :: proc "contextless" (ctx: ^Context, data: []byte) {
botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
}
final :: proc "contextless" (ctx: ^Context, hash: []byte) {
botan.hash_final(ctx^, &hash[0])
botan.hash_destroy(ctx^)
}