Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SHA512/t variants (t = 256 & t = 224) #42

Merged
merged 2 commits into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src/cryptokit.ml
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,13 @@ external sha256_final: bytes -> string = "caml_sha256_final"
external sha224_final: bytes -> string = "caml_sha224_final"
external sha512_init: unit -> bytes = "caml_sha512_init"
external sha384_init: unit -> bytes = "caml_sha384_init"
external sha512_256_init: unit -> bytes = "caml_sha512_256_init"
external sha512_224_init: unit -> bytes = "caml_sha512_224_init"
external sha512_update: bytes -> bytes -> int -> int -> unit = "caml_sha512_update"
external sha512_final: bytes -> string = "caml_sha512_final"
external sha384_final: bytes -> string = "caml_sha384_final"
external sha512_256_final: bytes -> string = "caml_sha512_256_final"
external sha512_224_final: bytes -> string = "caml_sha512_224_final"
type sha3_context
external sha3_init: int -> sha3_context = "caml_sha3_init"
external sha3_absorb: sha3_context -> bytes -> int -> int -> unit = "caml_sha3_absorb"
Expand Down Expand Up @@ -1183,6 +1187,50 @@ class sha512 =

let sha512 () = new sha512

class sha512_256 =
object(self)
val context = sha512_256_init()
method hash_size = 32
method add_substring src ofs len =
if ofs < 0 || len < 0 || ofs > Bytes.length src - len
then invalid_arg "sha512_256#add_substring";
sha512_update context src ofs len
method add_string src =
sha512_update context (Bytes.unsafe_of_string src) 0 (String.length src)
method add_char c =
self#add_string (String.make 1 c)
method add_byte b =
self#add_char (Char.unsafe_chr b)
method result =
sha512_256_final context
method wipe =
wipe_bytes context
end

let sha512_256 () = new sha512_256

class sha512_224 =
object(self)
val context = sha512_224_init()
method hash_size = 28
method add_substring src ofs len =
if ofs < 0 || len < 0 || ofs > Bytes.length src - len
then invalid_arg "sha512_224#add_substring";
sha512_update context src ofs len
method add_string src =
sha512_update context (Bytes.unsafe_of_string src) 0 (String.length src)
method add_char c =
self#add_string (String.make 1 c)
method add_byte b =
self#add_char (Char.unsafe_chr b)
method result =
sha512_224_final context
method wipe =
wipe_bytes context
end

let sha512_224 () = new sha512_224

let sha2 sz =
match sz with
| 224 -> new sha224
Expand Down
6 changes: 6 additions & 0 deletions src/cryptokit.mli
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,12 @@ module Hash : sig
val sha512: unit -> hash
(** SHA-512 is SHA-2 specialized to 512 bit hashes (64 bytes). *)

val sha512_256: unit -> hash
(** SHA-512/256 is a truncated version of SHA-512 (32 bytes) with a different IV. *)

val sha512_224: unit -> hash
(** SHA-512/224 is a truncated version of SHA-512 (24 bytes) with a different IV. *)

val blake2b: int -> hash
(** The BLAKE2b hash function produces hashes of length 1 to 64 bytes.
The parameter is the desired size of the hash, in bits.
Expand Down
34 changes: 34 additions & 0 deletions src/sha512.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,26 @@ EXPORT void SHA512_init(struct SHA512Context * ctx, int bitsize)
ctx->state[6] = UINT64_C(0xdb0c2e0d64f98fa7);
ctx->state[7] = UINT64_C(0x47b5481dbefa4fa4);
break;
case 256:
ctx->state[0] = UINT64_C(0x22312194fc2bf72c);
ctx->state[1] = UINT64_C(0x9f555fa3c84c64c2);
ctx->state[2] = UINT64_C(0x2393b86b6f53b151);
ctx->state[3] = UINT64_C(0x963877195940eabd );
ctx->state[4] = UINT64_C(0x96283ee2a88effe3);
ctx->state[5] = UINT64_C(0xbe5e1e2553863992);
ctx->state[6] = UINT64_C(0x2b0199fc2c85b8aa);
ctx->state[7] = UINT64_C(0x0eb72ddC81c52ca2);
break;
case 224:
ctx->state[0] = UINT64_C(0x8c3d37c819544da2);
ctx->state[1] = UINT64_C(0x73e1996689dcd4d6);
ctx->state[2] = UINT64_C(0x1dfab7ae32ff9c82);
ctx->state[3] = UINT64_C(0x679dd514582f9fcf );
ctx->state[4] = UINT64_C(0x0f6d2b697bd44da8);
ctx->state[5] = UINT64_C(0x77e36f7304C48942);
ctx->state[6] = UINT64_C(0x3f9d85a86a1d36C8);
ctx->state[7] = UINT64_C(0x1112e6ad91d692a1);
break;
default:
/* The bit size is wrong. Just zero the state to produce
incorrect hashes. */
Expand Down Expand Up @@ -295,6 +315,20 @@ EXPORT void SHA512_finish(struct SHA512Context * ctx, int bitsize,
case 384:
SHA512_copy_and_swap(ctx->state, output, 6);
break;
case 256:
SHA512_copy_and_swap(ctx->state, output, 4);
break;
case 224:
SHA512_copy_and_swap(ctx->state, output, 3);
#ifdef ARCH_BIG_ENDIAN
memcpy(&ctx->state[24], &output[24], 4);
#else
output[24] = (ctx->state[3] >> (8*7)) & 0xff;
output[25] = (ctx->state[3] >> (8*6)) & 0xff;
output[26] = (ctx->state[3] >> (8*5)) & 0xff;
output[27] = (ctx->state[3] >> (8*4)) & 0xff;
#endif
break;
/* default: The bit size is wrong. Produce no output. */
}
}
33 changes: 33 additions & 0 deletions src/stubs-sha512.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ CAMLprim value caml_sha384_init(value unit)
return ctx;
}

CAMLprim value caml_sha512_256_init(value unit)
{
value ctx = caml_alloc_string(sizeof(struct SHA512Context));
SHA512_init(Context_val(ctx), 256);
return ctx;
}

CAMLprim value caml_sha512_224_init(value unit)
{
value ctx = caml_alloc_string(sizeof(struct SHA512Context));
SHA512_init(Context_val(ctx), 224);
return ctx;
}

CAMLprim value caml_sha512_update(value ctx, value src, value ofs, value len)
{
SHA512_add_data(Context_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len));
Expand All @@ -58,3 +72,22 @@ CAMLprim value caml_sha384_final(value ctx)
CAMLreturn(res);
}

CAMLprim value caml_sha512_256_final(value ctx)
{
CAMLparam1(ctx);
CAMLlocal1(res);

res = caml_alloc_string(32);
SHA512_finish(Context_val(ctx), 256, &Byte_u(res, 0));
CAMLreturn(res);
}

CAMLprim value caml_sha512_224_final(value ctx)
{
CAMLparam1(ctx);
CAMLlocal1(res);

res = caml_alloc_string(28);
SHA512_finish(Context_val(ctx), 224, &Byte_u(res, 0));
CAMLreturn(res);
}
4 changes: 4 additions & 0 deletions test/speedtest.ml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ let _ =
(hash (Hash.sha256()) 4000000 16);
time_fn "SHA-512, 64_000_000 bytes, 16-byte chunks"
(hash (Hash.sha512()) 4000000 16);
time_fn "SHA-512/256, 64_000_000 bytes, 16-byte chunks"
(hash (Hash.sha512_256()) 4000000 16);
time_fn "SHA-512/224, 64_000_000 bytes, 16-byte chunks"
(hash (Hash.sha512_224()) 4000000 16);
time_fn "SHA-3 256, 64_000_000 bytes, 16-byte chunks"
(hash (Hash.sha3 256) 4000000 16);
time_fn "SHA-3 512, 64_000_000 bytes, 16-byte chunks"
Expand Down
36 changes: 36 additions & 0 deletions test/test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,42 @@ let _ =
test 99 (hash_extremely_long (Hash.sha2 512))
(hex "b47c933421ea2db1 49ad6e10fce6c7f9 3d0752380180ffd7 f4629a712134831d 77be6091b819ed35 2c2967a2e2d4fa50 50723c9630691f1a 05a7281dbe6c1086")

(* SHA-512/256 *)
let _ =
testing_function "SHA-2 512/256";
let hash s = hash_string (Hash.sha512_256 ()) s in
test 1 (hash "abc")
(hex "53048e2681941ef9 9b2e29b76b4c7dab e4c2d0c634fc6d46 e0e2f13107e7af23");
test 2 (hash "")
(hex "c672b8d1ef56ed28 ab87c3622c511406 9bdd3ad7b8f97374 98d0c01ecef0967a");
test 3 (hash "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
(hex "bde8e1f9f19bb9fd 3406c90ec6bc47bd 36d8ada9f11880db c8a22a7078b6a461");
test 4 (hash "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
(hex "3928e184fb8690f8 40da3988121d31be 65cb9d3ef83ee614 6feac861e19b563a");
test 5 (hash_million_a (Hash.sha512_256 ()))
(hex "9a59a052930187a9 7038cae692f30708 aa6491923ef51943 94dc68d56c74fb21");
if !long_tests then
test 99 (hash_extremely_long (Hash.sha512_256 ()))
(hex "b5855a6179802ce 567cbf43888284c6 ac7c3f6c48b08c5b c1e8ad75d12782c9e")

(* SHA-512/224 *)
let _ =
testing_function "SHA-2 512/224";
let hash s = hash_string (Hash.sha512_224 ()) s in
test 1 (hash "abc")
(hex "4634270f707b6a54 daae7530460842e2 0e37ed265ceee9a4 3e8924aa");
test 2 (hash "")
(hex "6ed0dd02806fa89e 25de060c19d3ac86 cabb87d6a0ddd05c 333b84f4");
test 3 (hash "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
(hex "e5302d6d54bb2422 75d1e7622d68df6e b02dedd13f564c13 dbda2174");
test 4 (hash "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
(hex "23fec5bb94d60b23 308192640b0c4533 35d664734fe40e72 68674af9");
test 5 (hash_million_a (Hash.sha512_224 ()))
(hex "37ab331d76f0d36d e422bd0edeb22a28 accd487b7a8453ae 965dd287");
if !long_tests then
test 99 (hash_extremely_long (Hash.sha512_224 ()))
(hex "9a7f86727c3be140 3d6702617646b155 89b8c5a92c70f170 3cd25b52")

(* SHA-3 *)
let _ =
testing_function "SHA-3";
Expand Down
Loading