mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-05 23:14:53 -06:00
shunf4 cherry-picking hash related commits from zstd. The following commits from 7-zip-zstd repository (https://github.com/mcmilk/7-Zip-zstd) is picked:
commitadd56b5aedAuthor: Tino Reichardt <milky-7zip@mcmilk.de> Date: Thu Nov 1 23:08:00 2018 +0100 Add MD5 hash function commit36a17a5184Author: Tino Reichardt <milky-7zip@mcmilk.de> Date: Sat Nov 3 00:18:33 2018 +0100 Add some hash functions - new: md2, md4, md5, sha384, sha512, xxhash-32, xxhash-64 - put Blake2sp hash stuff back to rar code - added the hashes to GUI and Explorer Menu code commit576c5df947Author: Tino Reichardt <milky-7zip@mcmilk.de> Date: Tue Apr 6 19:35:46 2021 +0200 Add BLAKE3 hash function commit6b2a151549Author: Tino Reichardt <milky-7zip@mcmilk.de> Date: Tue Apr 6 19:51:01 2021 +0200 Remove unneeded file HashesReg.cpp commitdddf507557Author: Tino Reichardt <milky-7zip@mcmilk.de> Date: Sun Jun 18 09:13:59 2023 +0200 Add SHA3 hashing - added these variants: SHA3-256, SHA3-384, SHA3-512 - reordered also the hashing id's - added some notes about them in DOC/Hashes.txt Signed-off-by: Tino Reichardt <milky-7zip@mcmilk.de> The cherry-picking was a chaos; they're not applied in order, and some commits even got cherry-picked twice (1->4->0->2->4->3). So subsequent fixes and adjustments were applied to make it build.
This commit is contained in:
778
C/hashes/blake3.c
Normal file
778
C/hashes/blake3.c
Normal file
@@ -0,0 +1,778 @@
|
||||
|
||||
/**
|
||||
* This work is released into the public domain with CC0 1.0.
|
||||
* Alternatively, it is licensed under the Apache License 2.0.
|
||||
*
|
||||
* Homepage: https://github.com/BLAKE3-team/BLAKE3
|
||||
*
|
||||
* Copyright (c) 2019-2020 Samuel Neves and Jack O'Connor
|
||||
* Copyright (c) 2021 Tino Reichardt
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "blake3.h"
|
||||
|
||||
const char *blake3_version(void) { return BLAKE3_VERSION_STRING; }
|
||||
|
||||
INLINE void chunk_state_init(blake3_chunk_state *self, const uint32_t key[8],
|
||||
uint8_t flags) {
|
||||
memcpy(self->cv, key, BLAKE3_KEY_LEN);
|
||||
self->chunk_counter = 0;
|
||||
memset(self->buf, 0, BLAKE3_BLOCK_LEN);
|
||||
self->buf_len = 0;
|
||||
self->blocks_compressed = 0;
|
||||
self->flags = flags;
|
||||
}
|
||||
|
||||
INLINE void chunk_state_reset(blake3_chunk_state *self, const uint32_t key[8],
|
||||
uint64_t chunk_counter) {
|
||||
memcpy(self->cv, key, BLAKE3_KEY_LEN);
|
||||
self->chunk_counter = chunk_counter;
|
||||
self->blocks_compressed = 0;
|
||||
memset(self->buf, 0, BLAKE3_BLOCK_LEN);
|
||||
self->buf_len = 0;
|
||||
}
|
||||
|
||||
INLINE size_t chunk_state_len(const blake3_chunk_state *self) {
|
||||
return (BLAKE3_BLOCK_LEN * (size_t)self->blocks_compressed) +
|
||||
((size_t)self->buf_len);
|
||||
}
|
||||
|
||||
INLINE size_t chunk_state_fill_buf(blake3_chunk_state *self,
|
||||
const uint8_t *input, size_t input_len) {
|
||||
size_t take = BLAKE3_BLOCK_LEN - ((size_t)self->buf_len);
|
||||
if (take > input_len) {
|
||||
take = input_len;
|
||||
}
|
||||
uint8_t *dest = self->buf + ((size_t)self->buf_len);
|
||||
memcpy(dest, input, take);
|
||||
self->buf_len += (uint8_t)take;
|
||||
return take;
|
||||
}
|
||||
|
||||
INLINE uint8_t chunk_state_maybe_start_flag(const blake3_chunk_state *self) {
|
||||
if (self->blocks_compressed == 0) {
|
||||
return CHUNK_START;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t input_cv[8];
|
||||
uint64_t counter;
|
||||
uint8_t block[BLAKE3_BLOCK_LEN];
|
||||
uint8_t block_len;
|
||||
uint8_t flags;
|
||||
} output_t;
|
||||
|
||||
INLINE output_t make_output(const uint32_t input_cv[8],
|
||||
const uint8_t block[BLAKE3_BLOCK_LEN],
|
||||
uint8_t block_len, uint64_t counter,
|
||||
uint8_t flags) {
|
||||
output_t ret;
|
||||
memcpy(ret.input_cv, input_cv, 32);
|
||||
memcpy(ret.block, block, BLAKE3_BLOCK_LEN);
|
||||
ret.block_len = block_len;
|
||||
ret.counter = counter;
|
||||
ret.flags = flags;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Chaining values within a given chunk (specifically the compress_in_place
|
||||
// interface) are represented as words. This avoids unnecessary bytes<->words
|
||||
// conversion overhead in the portable implementation. However, the hash_many
|
||||
// interface handles both user input and parent node blocks, so it accepts
|
||||
// bytes. For that reason, chaining values in the CV stack are represented as
|
||||
// bytes.
|
||||
INLINE void output_chaining_value(const output_t *self, uint8_t cv[32]) {
|
||||
uint32_t cv_words[8];
|
||||
memcpy(cv_words, self->input_cv, 32);
|
||||
blake3_compress_in_place(cv_words, self->block, self->block_len,
|
||||
self->counter, self->flags);
|
||||
store_cv_words(cv, cv_words);
|
||||
}
|
||||
|
||||
INLINE void output_root_bytes(const output_t *self, uint64_t seek, uint8_t *out,
|
||||
size_t out_len) {
|
||||
uint64_t output_block_counter = seek / 64;
|
||||
size_t offset_within_block = seek % 64;
|
||||
uint8_t wide_buf[64];
|
||||
while (out_len > 0) {
|
||||
blake3_compress_xof(self->input_cv, self->block, self->block_len,
|
||||
output_block_counter, self->flags | ROOT, wide_buf);
|
||||
size_t available_bytes = 64 - offset_within_block;
|
||||
size_t memcpy_len;
|
||||
if (out_len > available_bytes) {
|
||||
memcpy_len = available_bytes;
|
||||
} else {
|
||||
memcpy_len = out_len;
|
||||
}
|
||||
memcpy(out, wide_buf + offset_within_block, memcpy_len);
|
||||
out += memcpy_len;
|
||||
out_len -= memcpy_len;
|
||||
output_block_counter += 1;
|
||||
offset_within_block = 0;
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void chunk_state_update(blake3_chunk_state *self, const uint8_t *input,
|
||||
size_t input_len) {
|
||||
if (self->buf_len > 0) {
|
||||
size_t take = chunk_state_fill_buf(self, input, input_len);
|
||||
input += take;
|
||||
input_len -= take;
|
||||
if (input_len > 0) {
|
||||
blake3_compress_in_place(
|
||||
self->cv, self->buf, BLAKE3_BLOCK_LEN, self->chunk_counter,
|
||||
self->flags | chunk_state_maybe_start_flag(self));
|
||||
self->blocks_compressed += 1;
|
||||
self->buf_len = 0;
|
||||
memset(self->buf, 0, BLAKE3_BLOCK_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
while (input_len > BLAKE3_BLOCK_LEN) {
|
||||
blake3_compress_in_place(self->cv, input, BLAKE3_BLOCK_LEN,
|
||||
self->chunk_counter,
|
||||
self->flags | chunk_state_maybe_start_flag(self));
|
||||
self->blocks_compressed += 1;
|
||||
input += BLAKE3_BLOCK_LEN;
|
||||
input_len -= BLAKE3_BLOCK_LEN;
|
||||
}
|
||||
|
||||
size_t take = chunk_state_fill_buf(self, input, input_len);
|
||||
input += take;
|
||||
input_len -= take;
|
||||
}
|
||||
|
||||
INLINE output_t chunk_state_output(const blake3_chunk_state *self) {
|
||||
uint8_t block_flags =
|
||||
self->flags | chunk_state_maybe_start_flag(self) | CHUNK_END;
|
||||
return make_output(self->cv, self->buf, self->buf_len, self->chunk_counter,
|
||||
block_flags);
|
||||
}
|
||||
|
||||
INLINE output_t parent_output(const uint8_t block[BLAKE3_BLOCK_LEN],
|
||||
const uint32_t key[8], uint8_t flags) {
|
||||
return make_output(key, block, BLAKE3_BLOCK_LEN, 0, flags | PARENT);
|
||||
}
|
||||
|
||||
// Given some input larger than one chunk, return the number of bytes that
|
||||
// should go in the left subtree. This is the largest power-of-2 number of
|
||||
// chunks that leaves at least 1 byte for the right subtree.
|
||||
INLINE size_t left_len(size_t content_len) {
|
||||
// Subtract 1 to reserve at least one byte for the right side. content_len
|
||||
// should always be greater than BLAKE3_CHUNK_LEN.
|
||||
size_t full_chunks = (content_len - 1) / BLAKE3_CHUNK_LEN;
|
||||
return round_down_to_power_of_2(full_chunks) * BLAKE3_CHUNK_LEN;
|
||||
}
|
||||
|
||||
// Use SIMD parallelism to hash up to MAX_SIMD_DEGREE chunks at the same time
|
||||
// on a single thread. Write out the chunk chaining values and return the
|
||||
// number of chunks hashed. These chunks are never the root and never empty;
|
||||
// those cases use a different codepath.
|
||||
INLINE size_t compress_chunks_parallel(const uint8_t *input, size_t input_len,
|
||||
const uint32_t key[8],
|
||||
uint64_t chunk_counter, uint8_t flags,
|
||||
uint8_t *out) {
|
||||
#if defined(BLAKE3_TESTING)
|
||||
assert(0 < input_len);
|
||||
assert(input_len <= MAX_SIMD_DEGREE * BLAKE3_CHUNK_LEN);
|
||||
#endif
|
||||
|
||||
const uint8_t *chunks_array[MAX_SIMD_DEGREE];
|
||||
size_t input_position = 0;
|
||||
size_t chunks_array_len = 0;
|
||||
while (input_len - input_position >= BLAKE3_CHUNK_LEN) {
|
||||
chunks_array[chunks_array_len] = &input[input_position];
|
||||
input_position += BLAKE3_CHUNK_LEN;
|
||||
chunks_array_len += 1;
|
||||
}
|
||||
|
||||
blake3_hash_many(chunks_array, chunks_array_len,
|
||||
BLAKE3_CHUNK_LEN / BLAKE3_BLOCK_LEN, key, chunk_counter,
|
||||
true, flags, CHUNK_START, CHUNK_END, out);
|
||||
|
||||
// Hash the remaining partial chunk, if there is one. Note that the empty
|
||||
// chunk (meaning the empty message) is a different codepath.
|
||||
if (input_len > input_position) {
|
||||
uint64_t counter = chunk_counter + (uint64_t)chunks_array_len;
|
||||
blake3_chunk_state chunk_state;
|
||||
chunk_state_init(&chunk_state, key, flags);
|
||||
chunk_state.chunk_counter = counter;
|
||||
chunk_state_update(&chunk_state, &input[input_position],
|
||||
input_len - input_position);
|
||||
output_t output = chunk_state_output(&chunk_state);
|
||||
output_chaining_value(&output, &out[chunks_array_len * BLAKE3_OUT_LEN]);
|
||||
return chunks_array_len + 1;
|
||||
} else {
|
||||
return chunks_array_len;
|
||||
}
|
||||
}
|
||||
|
||||
// Use SIMD parallelism to hash up to MAX_SIMD_DEGREE parents at the same time
|
||||
// on a single thread. Write out the parent chaining values and return the
|
||||
// number of parents hashed. (If there's an odd input chaining value left over,
|
||||
// return it as an additional output.) These parents are never the root and
|
||||
// never empty; those cases use a different codepath.
|
||||
INLINE size_t compress_parents_parallel(const uint8_t *child_chaining_values,
|
||||
size_t num_chaining_values,
|
||||
const uint32_t key[8], uint8_t flags,
|
||||
uint8_t *out) {
|
||||
#if defined(BLAKE3_TESTING)
|
||||
assert(2 <= num_chaining_values);
|
||||
assert(num_chaining_values <= 2 * MAX_SIMD_DEGREE_OR_2);
|
||||
#endif
|
||||
|
||||
const uint8_t *parents_array[MAX_SIMD_DEGREE_OR_2];
|
||||
size_t parents_array_len = 0;
|
||||
while (num_chaining_values - (2 * parents_array_len) >= 2) {
|
||||
parents_array[parents_array_len] =
|
||||
&child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN];
|
||||
parents_array_len += 1;
|
||||
}
|
||||
|
||||
blake3_hash_many(parents_array, parents_array_len, 1, key,
|
||||
0, // Parents always use counter 0.
|
||||
false, flags | PARENT,
|
||||
0, // Parents have no start flags.
|
||||
0, // Parents have no end flags.
|
||||
out);
|
||||
|
||||
// If there's an odd child left over, it becomes an output.
|
||||
if (num_chaining_values > 2 * parents_array_len) {
|
||||
memcpy(&out[parents_array_len * BLAKE3_OUT_LEN],
|
||||
&child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN],
|
||||
BLAKE3_OUT_LEN);
|
||||
return parents_array_len + 1;
|
||||
} else {
|
||||
return parents_array_len;
|
||||
}
|
||||
}
|
||||
|
||||
// The wide helper function returns (writes out) an array of chaining values
|
||||
// and returns the length of that array. The number of chaining values returned
|
||||
// is the dyanmically detected SIMD degree, at most MAX_SIMD_DEGREE. Or fewer,
|
||||
// if the input is shorter than that many chunks. The reason for maintaining a
|
||||
// wide array of chaining values going back up the tree, is to allow the
|
||||
// implementation to hash as many parents in parallel as possible.
|
||||
//
|
||||
// As a special case when the SIMD degree is 1, this function will still return
|
||||
// at least 2 outputs. This guarantees that this function doesn't perform the
|
||||
// root compression. (If it did, it would use the wrong flags, and also we
|
||||
// wouldn't be able to implement exendable ouput.) Note that this function is
|
||||
// not used when the whole input is only 1 chunk long; that's a different
|
||||
// codepath.
|
||||
//
|
||||
// Why not just have the caller split the input on the first update(), instead
|
||||
// of implementing this special rule? Because we don't want to limit SIMD or
|
||||
// multi-threading parallelism for that update().
|
||||
static size_t blake3_compress_subtree_wide(const uint8_t *input,
|
||||
size_t input_len,
|
||||
const uint32_t key[8],
|
||||
uint64_t chunk_counter,
|
||||
uint8_t flags, uint8_t *out) {
|
||||
// Note that the single chunk case does *not* bump the SIMD degree up to 2
|
||||
// when it is 1. If this implementation adds multi-threading in the future,
|
||||
// this gives us the option of multi-threading even the 2-chunk case, which
|
||||
// can help performance on smaller platforms.
|
||||
if (input_len <= blake3_simd_degree() * BLAKE3_CHUNK_LEN) {
|
||||
return compress_chunks_parallel(input, input_len, key, chunk_counter, flags,
|
||||
out);
|
||||
}
|
||||
|
||||
// With more than simd_degree chunks, we need to recurse. Start by dividing
|
||||
// the input into left and right subtrees. (Note that this is only optimal
|
||||
// as long as the SIMD degree is a power of 2. If we ever get a SIMD degree
|
||||
// of 3 or something, we'll need a more complicated strategy.)
|
||||
size_t left_input_len = left_len(input_len);
|
||||
size_t right_input_len = input_len - left_input_len;
|
||||
const uint8_t *right_input = &input[left_input_len];
|
||||
uint64_t right_chunk_counter =
|
||||
chunk_counter + (uint64_t)(left_input_len / BLAKE3_CHUNK_LEN);
|
||||
|
||||
// Make space for the child outputs. Here we use MAX_SIMD_DEGREE_OR_2 to
|
||||
// account for the special case of returning 2 outputs when the SIMD degree
|
||||
// is 1.
|
||||
uint8_t cv_array[2 * MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN];
|
||||
size_t degree = blake3_simd_degree();
|
||||
if (left_input_len > BLAKE3_CHUNK_LEN && degree == 1) {
|
||||
// The special case: We always use a degree of at least two, to make
|
||||
// sure there are two outputs. Except, as noted above, at the chunk
|
||||
// level, where we allow degree=1. (Note that the 1-chunk-input case is
|
||||
// a different codepath.)
|
||||
degree = 2;
|
||||
}
|
||||
uint8_t *right_cvs = &cv_array[degree * BLAKE3_OUT_LEN];
|
||||
|
||||
// Recurse! If this implementation adds multi-threading support in the
|
||||
// future, this is where it will go.
|
||||
size_t left_n = blake3_compress_subtree_wide(input, left_input_len, key,
|
||||
chunk_counter, flags, cv_array);
|
||||
size_t right_n = blake3_compress_subtree_wide(
|
||||
right_input, right_input_len, key, right_chunk_counter, flags, right_cvs);
|
||||
|
||||
// The special case again. If simd_degree=1, then we'll have left_n=1 and
|
||||
// right_n=1. Rather than compressing them into a single output, return
|
||||
// them directly, to make sure we always have at least two outputs.
|
||||
if (left_n == 1) {
|
||||
memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Otherwise, do one layer of parent node compression.
|
||||
size_t num_chaining_values = left_n + right_n;
|
||||
return compress_parents_parallel(cv_array, num_chaining_values, key, flags,
|
||||
out);
|
||||
}
|
||||
|
||||
// Hash a subtree with compress_subtree_wide(), and then condense the resulting
|
||||
// list of chaining values down to a single parent node. Don't compress that
|
||||
// last parent node, however. Instead, return its message bytes (the
|
||||
// concatenated chaining values of its children). This is necessary when the
|
||||
// first call to update() supplies a complete subtree, because the topmost
|
||||
// parent node of that subtree could end up being the root. It's also necessary
|
||||
// for extended output in the general case.
|
||||
//
|
||||
// As with compress_subtree_wide(), this function is not used on inputs of 1
|
||||
// chunk or less. That's a different codepath.
|
||||
INLINE void compress_subtree_to_parent_node(
|
||||
const uint8_t *input, size_t input_len, const uint32_t key[8],
|
||||
uint64_t chunk_counter, uint8_t flags, uint8_t out[2 * BLAKE3_OUT_LEN]) {
|
||||
#if defined(BLAKE3_TESTING)
|
||||
assert(input_len > BLAKE3_CHUNK_LEN);
|
||||
#endif
|
||||
|
||||
uint8_t cv_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN];
|
||||
size_t num_cvs = blake3_compress_subtree_wide(input, input_len, key,
|
||||
chunk_counter, flags, cv_array);
|
||||
|
||||
// If MAX_SIMD_DEGREE is greater than 2 and there's enough input,
|
||||
// compress_subtree_wide() returns more than 2 chaining values. Condense
|
||||
// them into 2 by forming parent nodes repeatedly.
|
||||
uint8_t out_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN / 2];
|
||||
while (num_cvs > 2) {
|
||||
num_cvs =
|
||||
compress_parents_parallel(cv_array, num_cvs, key, flags, out_array);
|
||||
memcpy(cv_array, out_array, num_cvs * BLAKE3_OUT_LEN);
|
||||
}
|
||||
memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN);
|
||||
}
|
||||
|
||||
INLINE void hasher_init_base(blake3_hasher *self, const uint32_t key[8],
|
||||
uint8_t flags) {
|
||||
memcpy(self->key, key, BLAKE3_KEY_LEN);
|
||||
chunk_state_init(&self->chunk, key, flags);
|
||||
self->cv_stack_len = 0;
|
||||
}
|
||||
|
||||
void blake3_hasher_init(blake3_hasher *self) { hasher_init_base(self, IV, 0); }
|
||||
|
||||
void blake3_hasher_init_keyed(blake3_hasher *self,
|
||||
const uint8_t key[BLAKE3_KEY_LEN]) {
|
||||
uint32_t key_words[8];
|
||||
load_key_words(key, key_words);
|
||||
hasher_init_base(self, key_words, KEYED_HASH);
|
||||
}
|
||||
|
||||
void blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context,
|
||||
size_t context_len) {
|
||||
blake3_hasher context_hasher;
|
||||
hasher_init_base(&context_hasher, IV, DERIVE_KEY_CONTEXT);
|
||||
blake3_hasher_update(&context_hasher, context, context_len);
|
||||
uint8_t context_key[BLAKE3_KEY_LEN];
|
||||
blake3_hasher_finalize(&context_hasher, context_key, BLAKE3_KEY_LEN);
|
||||
uint32_t context_key_words[8];
|
||||
load_key_words(context_key, context_key_words);
|
||||
hasher_init_base(self, context_key_words, DERIVE_KEY_MATERIAL);
|
||||
}
|
||||
|
||||
void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context) {
|
||||
blake3_hasher_init_derive_key_raw(self, context, strlen(context));
|
||||
}
|
||||
|
||||
// As described in hasher_push_cv() below, we do "lazy merging", delaying
|
||||
// merges until right before the next CV is about to be added. This is
|
||||
// different from the reference implementation. Another difference is that we
|
||||
// aren't always merging 1 chunk at a time. Instead, each CV might represent
|
||||
// any power-of-two number of chunks, as long as the smaller-above-larger stack
|
||||
// order is maintained. Instead of the "count the trailing 0-bits" algorithm
|
||||
// described in the spec, we use a "count the total number of 1-bits" variant
|
||||
// that doesn't require us to retain the subtree size of the CV on top of the
|
||||
// stack. The principle is the same: each CV that should remain in the stack is
|
||||
// represented by a 1-bit in the total number of chunks (or bytes) so far.
|
||||
INLINE void hasher_merge_cv_stack(blake3_hasher *self, uint64_t total_len) {
|
||||
size_t post_merge_stack_len = (size_t)popcnt(total_len);
|
||||
while (self->cv_stack_len > post_merge_stack_len) {
|
||||
uint8_t *parent_node =
|
||||
&self->cv_stack[(self->cv_stack_len - 2) * BLAKE3_OUT_LEN];
|
||||
output_t output = parent_output(parent_node, self->key, self->chunk.flags);
|
||||
output_chaining_value(&output, parent_node);
|
||||
self->cv_stack_len -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// In reference_impl.rs, we merge the new CV with existing CVs from the stack
|
||||
// before pushing it. We can do that because we know more input is coming, so
|
||||
// we know none of the merges are root.
|
||||
//
|
||||
// This setting is different. We want to feed as much input as possible to
|
||||
// compress_subtree_wide(), without setting aside anything for the chunk_state.
|
||||
// If the user gives us 64 KiB, we want to parallelize over all 64 KiB at once
|
||||
// as a single subtree, if at all possible.
|
||||
//
|
||||
// This leads to two problems:
|
||||
// 1) This 64 KiB input might be the only call that ever gets made to update.
|
||||
// In this case, the root node of the 64 KiB subtree would be the root node
|
||||
// of the whole tree, and it would need to be ROOT finalized. We can't
|
||||
// compress it until we know.
|
||||
// 2) This 64 KiB input might complete a larger tree, whose root node is
|
||||
// similarly going to be the the root of the whole tree. For example, maybe
|
||||
// we have 196 KiB (that is, 128 + 64) hashed so far. We can't compress the
|
||||
// node at the root of the 256 KiB subtree until we know how to finalize it.
|
||||
//
|
||||
// The second problem is solved with "lazy merging". That is, when we're about
|
||||
// to add a CV to the stack, we don't merge it with anything first, as the
|
||||
// reference impl does. Instead we do merges using the *previous* CV that was
|
||||
// added, which is sitting on top of the stack, and we put the new CV
|
||||
// (unmerged) on top of the stack afterwards. This guarantees that we never
|
||||
// merge the root node until finalize().
|
||||
//
|
||||
// Solving the first problem requires an additional tool,
|
||||
// compress_subtree_to_parent_node(). That function always returns the top
|
||||
// *two* chaining values of the subtree it's compressing. We then do lazy
|
||||
// merging with each of them separately, so that the second CV will always
|
||||
// remain unmerged. (That also helps us support extendable output when we're
|
||||
// hashing an input all-at-once.)
|
||||
INLINE void hasher_push_cv(blake3_hasher *self, uint8_t new_cv[BLAKE3_OUT_LEN],
|
||||
uint64_t chunk_counter) {
|
||||
hasher_merge_cv_stack(self, chunk_counter);
|
||||
memcpy(&self->cv_stack[self->cv_stack_len * BLAKE3_OUT_LEN], new_cv,
|
||||
BLAKE3_OUT_LEN);
|
||||
self->cv_stack_len += 1;
|
||||
}
|
||||
|
||||
void blake3_hasher_update(blake3_hasher *self, const void *input,
|
||||
size_t input_len) {
|
||||
// Explicitly checking for zero avoids causing UB by passing a null pointer
|
||||
// to memcpy. This comes up in practice with things like:
|
||||
// std::vector<uint8_t> v;
|
||||
// blake3_hasher_update(&hasher, v.data(), v.size());
|
||||
if (input_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t *input_bytes = (const uint8_t *)input;
|
||||
|
||||
// If we have some partial chunk bytes in the internal chunk_state, we need
|
||||
// to finish that chunk first.
|
||||
if (chunk_state_len(&self->chunk) > 0) {
|
||||
size_t take = BLAKE3_CHUNK_LEN - chunk_state_len(&self->chunk);
|
||||
if (take > input_len) {
|
||||
take = input_len;
|
||||
}
|
||||
chunk_state_update(&self->chunk, input_bytes, take);
|
||||
input_bytes += take;
|
||||
input_len -= take;
|
||||
// If we've filled the current chunk and there's more coming, finalize this
|
||||
// chunk and proceed. In this case we know it's not the root.
|
||||
if (input_len > 0) {
|
||||
output_t output = chunk_state_output(&self->chunk);
|
||||
uint8_t chunk_cv[32];
|
||||
output_chaining_value(&output, chunk_cv);
|
||||
hasher_push_cv(self, chunk_cv, self->chunk.chunk_counter);
|
||||
chunk_state_reset(&self->chunk, self->key, self->chunk.chunk_counter + 1);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Now the chunk_state is clear, and we have more input. If there's more than
|
||||
// a single chunk (so, definitely not the root chunk), hash the largest whole
|
||||
// subtree we can, with the full benefits of SIMD (and maybe in the future,
|
||||
// multi-threading) parallelism. Two restrictions:
|
||||
// - The subtree has to be a power-of-2 number of chunks. Only subtrees along
|
||||
// the right edge can be incomplete, and we don't know where the right edge
|
||||
// is going to be until we get to finalize().
|
||||
// - The subtree must evenly divide the total number of chunks up until this
|
||||
// point (if total is not 0). If the current incomplete subtree is only
|
||||
// waiting for 1 more chunk, we can't hash a subtree of 4 chunks. We have
|
||||
// to complete the current subtree first.
|
||||
// Because we might need to break up the input to form powers of 2, or to
|
||||
// evenly divide what we already have, this part runs in a loop.
|
||||
while (input_len > BLAKE3_CHUNK_LEN) {
|
||||
size_t subtree_len = round_down_to_power_of_2(input_len);
|
||||
uint64_t count_so_far = self->chunk.chunk_counter * BLAKE3_CHUNK_LEN;
|
||||
// Shrink the subtree_len until it evenly divides the count so far. We know
|
||||
// that subtree_len itself is a power of 2, so we can use a bitmasking
|
||||
// trick instead of an actual remainder operation. (Note that if the caller
|
||||
// consistently passes power-of-2 inputs of the same size, as is hopefully
|
||||
// typical, this loop condition will always fail, and subtree_len will
|
||||
// always be the full length of the input.)
|
||||
//
|
||||
// An aside: We don't have to shrink subtree_len quite this much. For
|
||||
// example, if count_so_far is 1, we could pass 2 chunks to
|
||||
// compress_subtree_to_parent_node. Since we'll get 2 CVs back, we'll still
|
||||
// get the right answer in the end, and we might get to use 2-way SIMD
|
||||
// parallelism. The problem with this optimization, is that it gets us
|
||||
// stuck always hashing 2 chunks. The total number of chunks will remain
|
||||
// odd, and we'll never graduate to higher degrees of parallelism. See
|
||||
// https://github.com/BLAKE3-team/BLAKE3/issues/69.
|
||||
while ((((uint64_t)(subtree_len - 1)) & count_so_far) != 0) {
|
||||
subtree_len /= 2;
|
||||
}
|
||||
// The shrunken subtree_len might now be 1 chunk long. If so, hash that one
|
||||
// chunk by itself. Otherwise, compress the subtree into a pair of CVs.
|
||||
uint64_t subtree_chunks = subtree_len / BLAKE3_CHUNK_LEN;
|
||||
if (subtree_len <= BLAKE3_CHUNK_LEN) {
|
||||
blake3_chunk_state chunk_state;
|
||||
chunk_state_init(&chunk_state, self->key, self->chunk.flags);
|
||||
chunk_state.chunk_counter = self->chunk.chunk_counter;
|
||||
chunk_state_update(&chunk_state, input_bytes, subtree_len);
|
||||
output_t output = chunk_state_output(&chunk_state);
|
||||
uint8_t cv[BLAKE3_OUT_LEN];
|
||||
output_chaining_value(&output, cv);
|
||||
hasher_push_cv(self, cv, chunk_state.chunk_counter);
|
||||
} else {
|
||||
// This is the high-performance happy path, though getting here depends
|
||||
// on the caller giving us a long enough input.
|
||||
uint8_t cv_pair[2 * BLAKE3_OUT_LEN];
|
||||
compress_subtree_to_parent_node(input_bytes, subtree_len, self->key,
|
||||
self->chunk.chunk_counter,
|
||||
self->chunk.flags, cv_pair);
|
||||
hasher_push_cv(self, cv_pair, self->chunk.chunk_counter);
|
||||
hasher_push_cv(self, &cv_pair[BLAKE3_OUT_LEN],
|
||||
self->chunk.chunk_counter + (subtree_chunks / 2));
|
||||
}
|
||||
self->chunk.chunk_counter += subtree_chunks;
|
||||
input_bytes += subtree_len;
|
||||
input_len -= subtree_len;
|
||||
}
|
||||
|
||||
// If there's any remaining input less than a full chunk, add it to the chunk
|
||||
// state. In that case, also do a final merge loop to make sure the subtree
|
||||
// stack doesn't contain any unmerged pairs. The remaining input means we
|
||||
// know these merges are non-root. This merge loop isn't strictly necessary
|
||||
// here, because hasher_push_chunk_cv already does its own merge loop, but it
|
||||
// simplifies blake3_hasher_finalize below.
|
||||
if (input_len > 0) {
|
||||
chunk_state_update(&self->chunk, input_bytes, input_len);
|
||||
hasher_merge_cv_stack(self, self->chunk.chunk_counter);
|
||||
}
|
||||
}
|
||||
|
||||
void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out,
|
||||
size_t out_len) {
|
||||
blake3_hasher_finalize_seek(self, 0, out, out_len);
|
||||
}
|
||||
|
||||
void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek,
|
||||
uint8_t *out, size_t out_len) {
|
||||
// Explicitly checking for zero avoids causing UB by passing a null pointer
|
||||
// to memcpy. This comes up in practice with things like:
|
||||
// std::vector<uint8_t> v;
|
||||
// blake3_hasher_finalize(&hasher, v.data(), v.size());
|
||||
if (out_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the subtree stack is empty, then the current chunk is the root.
|
||||
if (self->cv_stack_len == 0) {
|
||||
output_t output = chunk_state_output(&self->chunk);
|
||||
output_root_bytes(&output, seek, out, out_len);
|
||||
return;
|
||||
}
|
||||
// If there are any bytes in the chunk state, finalize that chunk and do a
|
||||
// roll-up merge between that chunk hash and every subtree in the stack. In
|
||||
// this case, the extra merge loop at the end of blake3_hasher_update
|
||||
// guarantees that none of the subtrees in the stack need to be merged with
|
||||
// each other first. Otherwise, if there are no bytes in the chunk state,
|
||||
// then the top of the stack is a chunk hash, and we start the merge from
|
||||
// that.
|
||||
output_t output;
|
||||
size_t cvs_remaining;
|
||||
if (chunk_state_len(&self->chunk) > 0) {
|
||||
cvs_remaining = self->cv_stack_len;
|
||||
output = chunk_state_output(&self->chunk);
|
||||
} else {
|
||||
// There are always at least 2 CVs in the stack in this case.
|
||||
cvs_remaining = self->cv_stack_len - 2;
|
||||
output = parent_output(&self->cv_stack[cvs_remaining * 32], self->key,
|
||||
self->chunk.flags);
|
||||
}
|
||||
while (cvs_remaining > 0) {
|
||||
cvs_remaining -= 1;
|
||||
uint8_t parent_block[BLAKE3_BLOCK_LEN];
|
||||
memcpy(parent_block, &self->cv_stack[cvs_remaining * 32], 32);
|
||||
output_chaining_value(&output, &parent_block[32]);
|
||||
output = parent_output(parent_block, self->key, self->chunk.flags);
|
||||
}
|
||||
output_root_bytes(&output, seek, out, out_len);
|
||||
}
|
||||
|
||||
INLINE uint32_t rotr32(uint32_t w, uint32_t c) {
|
||||
return (w >> c) | (w << (32 - c));
|
||||
}
|
||||
|
||||
INLINE void g(uint32_t *state, size_t a, size_t b, size_t c, size_t d,
|
||||
uint32_t x, uint32_t y) {
|
||||
state[a] = state[a] + state[b] + x;
|
||||
state[d] = rotr32(state[d] ^ state[a], 16);
|
||||
state[c] = state[c] + state[d];
|
||||
state[b] = rotr32(state[b] ^ state[c], 12);
|
||||
state[a] = state[a] + state[b] + y;
|
||||
state[d] = rotr32(state[d] ^ state[a], 8);
|
||||
state[c] = state[c] + state[d];
|
||||
state[b] = rotr32(state[b] ^ state[c], 7);
|
||||
}
|
||||
|
||||
INLINE void round_fn(uint32_t state[16], const uint32_t *msg, size_t round) {
|
||||
// Select the message schedule based on the round.
|
||||
const uint8_t *schedule = MSG_SCHEDULE[round];
|
||||
|
||||
// Mix the columns.
|
||||
g(state, 0, 4, 8, 12, msg[schedule[0]], msg[schedule[1]]);
|
||||
g(state, 1, 5, 9, 13, msg[schedule[2]], msg[schedule[3]]);
|
||||
g(state, 2, 6, 10, 14, msg[schedule[4]], msg[schedule[5]]);
|
||||
g(state, 3, 7, 11, 15, msg[schedule[6]], msg[schedule[7]]);
|
||||
|
||||
// Mix the rows.
|
||||
g(state, 0, 5, 10, 15, msg[schedule[8]], msg[schedule[9]]);
|
||||
g(state, 1, 6, 11, 12, msg[schedule[10]], msg[schedule[11]]);
|
||||
g(state, 2, 7, 8, 13, msg[schedule[12]], msg[schedule[13]]);
|
||||
g(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]]);
|
||||
}
|
||||
|
||||
INLINE void compress_pre(uint32_t state[16], const uint32_t cv[8],
|
||||
const uint8_t block[BLAKE3_BLOCK_LEN],
|
||||
uint8_t block_len, uint64_t counter, uint8_t flags) {
|
||||
uint32_t block_words[16];
|
||||
block_words[0] = load32(block + 4 * 0);
|
||||
block_words[1] = load32(block + 4 * 1);
|
||||
block_words[2] = load32(block + 4 * 2);
|
||||
block_words[3] = load32(block + 4 * 3);
|
||||
block_words[4] = load32(block + 4 * 4);
|
||||
block_words[5] = load32(block + 4 * 5);
|
||||
block_words[6] = load32(block + 4 * 6);
|
||||
block_words[7] = load32(block + 4 * 7);
|
||||
block_words[8] = load32(block + 4 * 8);
|
||||
block_words[9] = load32(block + 4 * 9);
|
||||
block_words[10] = load32(block + 4 * 10);
|
||||
block_words[11] = load32(block + 4 * 11);
|
||||
block_words[12] = load32(block + 4 * 12);
|
||||
block_words[13] = load32(block + 4 * 13);
|
||||
block_words[14] = load32(block + 4 * 14);
|
||||
block_words[15] = load32(block + 4 * 15);
|
||||
|
||||
state[0] = cv[0];
|
||||
state[1] = cv[1];
|
||||
state[2] = cv[2];
|
||||
state[3] = cv[3];
|
||||
state[4] = cv[4];
|
||||
state[5] = cv[5];
|
||||
state[6] = cv[6];
|
||||
state[7] = cv[7];
|
||||
state[8] = IV[0];
|
||||
state[9] = IV[1];
|
||||
state[10] = IV[2];
|
||||
state[11] = IV[3];
|
||||
state[12] = counter_low(counter);
|
||||
state[13] = counter_high(counter);
|
||||
state[14] = (uint32_t)block_len;
|
||||
state[15] = (uint32_t)flags;
|
||||
|
||||
round_fn(state, &block_words[0], 0);
|
||||
round_fn(state, &block_words[0], 1);
|
||||
round_fn(state, &block_words[0], 2);
|
||||
round_fn(state, &block_words[0], 3);
|
||||
round_fn(state, &block_words[0], 4);
|
||||
round_fn(state, &block_words[0], 5);
|
||||
round_fn(state, &block_words[0], 6);
|
||||
}
|
||||
|
||||
void blake3_compress_in_place(uint32_t cv[8],
|
||||
const uint8_t block[BLAKE3_BLOCK_LEN],
|
||||
uint8_t block_len, uint64_t counter,
|
||||
uint8_t flags) {
|
||||
uint32_t state[16];
|
||||
compress_pre(state, cv, block, block_len, counter, flags);
|
||||
cv[0] = state[0] ^ state[8];
|
||||
cv[1] = state[1] ^ state[9];
|
||||
cv[2] = state[2] ^ state[10];
|
||||
cv[3] = state[3] ^ state[11];
|
||||
cv[4] = state[4] ^ state[12];
|
||||
cv[5] = state[5] ^ state[13];
|
||||
cv[6] = state[6] ^ state[14];
|
||||
cv[7] = state[7] ^ state[15];
|
||||
}
|
||||
|
||||
void blake3_compress_xof(const uint32_t cv[8],
|
||||
const uint8_t block[BLAKE3_BLOCK_LEN],
|
||||
uint8_t block_len, uint64_t counter,
|
||||
uint8_t flags, uint8_t out[64]) {
|
||||
uint32_t state[16];
|
||||
compress_pre(state, cv, block, block_len, counter, flags);
|
||||
|
||||
store32(&out[0 * 4], state[0] ^ state[8]);
|
||||
store32(&out[1 * 4], state[1] ^ state[9]);
|
||||
store32(&out[2 * 4], state[2] ^ state[10]);
|
||||
store32(&out[3 * 4], state[3] ^ state[11]);
|
||||
store32(&out[4 * 4], state[4] ^ state[12]);
|
||||
store32(&out[5 * 4], state[5] ^ state[13]);
|
||||
store32(&out[6 * 4], state[6] ^ state[14]);
|
||||
store32(&out[7 * 4], state[7] ^ state[15]);
|
||||
store32(&out[8 * 4], state[8] ^ cv[0]);
|
||||
store32(&out[9 * 4], state[9] ^ cv[1]);
|
||||
store32(&out[10 * 4], state[10] ^ cv[2]);
|
||||
store32(&out[11 * 4], state[11] ^ cv[3]);
|
||||
store32(&out[12 * 4], state[12] ^ cv[4]);
|
||||
store32(&out[13 * 4], state[13] ^ cv[5]);
|
||||
store32(&out[14 * 4], state[14] ^ cv[6]);
|
||||
store32(&out[15 * 4], state[15] ^ cv[7]);
|
||||
}
|
||||
|
||||
INLINE void hash_one(const uint8_t *input, size_t blocks,
|
||||
const uint32_t key[8], uint64_t counter,
|
||||
uint8_t flags, uint8_t flags_start,
|
||||
uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) {
|
||||
uint32_t cv[8];
|
||||
memcpy(cv, key, BLAKE3_KEY_LEN);
|
||||
uint8_t block_flags = flags | flags_start;
|
||||
while (blocks > 0) {
|
||||
if (blocks == 1) {
|
||||
block_flags |= flags_end;
|
||||
}
|
||||
blake3_compress_in_place(cv, input, BLAKE3_BLOCK_LEN, counter,
|
||||
block_flags);
|
||||
input = &input[BLAKE3_BLOCK_LEN];
|
||||
blocks -= 1;
|
||||
block_flags = flags;
|
||||
}
|
||||
store_cv_words(out, cv);
|
||||
}
|
||||
|
||||
void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs,
|
||||
size_t blocks, const uint32_t key[8],
|
||||
uint64_t counter, bool increment_counter,
|
||||
uint8_t flags, uint8_t flags_start,
|
||||
uint8_t flags_end, uint8_t *out) {
|
||||
while (num_inputs > 0) {
|
||||
hash_one(inputs[0], blocks, key, counter, flags, flags_start,
|
||||
flags_end, out);
|
||||
if (increment_counter) {
|
||||
counter += 1;
|
||||
}
|
||||
inputs += 1;
|
||||
num_inputs -= 1;
|
||||
out = &out[BLAKE3_OUT_LEN];
|
||||
}
|
||||
}
|
||||
|
||||
// The dynamically detected SIMD degree of the current platform.
|
||||
size_t blake3_simd_degree(void) {
|
||||
return 1;
|
||||
}
|
||||
272
C/hashes/blake3.h
Normal file
272
C/hashes/blake3.h
Normal file
@@ -0,0 +1,272 @@
|
||||
|
||||
/**
|
||||
* This work is released into the public domain with CC0 1.0.
|
||||
* Alternatively, it is licensed under the Apache License 2.0.
|
||||
*
|
||||
* Homepage: https://github.com/BLAKE3-team/BLAKE3
|
||||
*
|
||||
* Copyright (c) 2019-2020 Samuel Neves and Jack O'Connor
|
||||
* Copyright (c) 2021 Tino Reichardt
|
||||
*/
|
||||
|
||||
#ifndef BLAKE3_H
|
||||
#define BLAKE3_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#pragma warning(disable : 4464)
|
||||
#pragma warning(disable : 4820)
|
||||
#pragma warning(disable : 4711)
|
||||
#pragma warning(disable : 5045)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLAKE3_VERSION_STRING "0.3.7"
|
||||
#define BLAKE3_KEY_LEN 32
|
||||
#define BLAKE3_OUT_LEN 32
|
||||
#define BLAKE3_BLOCK_LEN 64
|
||||
#define BLAKE3_CHUNK_LEN 1024
|
||||
#define BLAKE3_MAX_DEPTH 54
|
||||
|
||||
/* disable some warnings /TR */
|
||||
#pragma warning(disable : 4244)
|
||||
|
||||
// This struct is a private implementation detail. It has to be here because
|
||||
// it's part of blake3_hasher below.
|
||||
typedef struct {
|
||||
uint32_t cv[8];
|
||||
uint64_t chunk_counter;
|
||||
uint8_t buf[BLAKE3_BLOCK_LEN];
|
||||
uint8_t buf_len;
|
||||
uint8_t blocks_compressed;
|
||||
uint8_t flags;
|
||||
} blake3_chunk_state;
|
||||
|
||||
typedef struct {
|
||||
uint32_t key[8];
|
||||
blake3_chunk_state chunk;
|
||||
uint8_t cv_stack_len;
|
||||
// The stack size is MAX_DEPTH + 1 because we do lazy merging. For example,
|
||||
// with 7 chunks, we have 3 entries in the stack. Adding an 8th chunk
|
||||
// requires a 4th entry, rather than merging everything down to 1, because we
|
||||
// don't know whether more input is coming. This is different from how the
|
||||
// reference implementation does things.
|
||||
uint8_t cv_stack[(BLAKE3_MAX_DEPTH + 1) * BLAKE3_OUT_LEN];
|
||||
} blake3_hasher;
|
||||
|
||||
const char *blake3_version(void);
|
||||
void blake3_hasher_init(blake3_hasher *self);
|
||||
void blake3_hasher_init_keyed(blake3_hasher *self,
|
||||
const uint8_t key[BLAKE3_KEY_LEN]);
|
||||
void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context);
|
||||
void blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context,
|
||||
size_t context_len);
|
||||
void blake3_hasher_update(blake3_hasher *self, const void *input,
|
||||
size_t input_len);
|
||||
void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out,
|
||||
size_t out_len);
|
||||
void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek,
|
||||
uint8_t *out, size_t out_len);
|
||||
|
||||
// internal flags
|
||||
enum blake3_flags {
|
||||
CHUNK_START = 1 << 0,
|
||||
CHUNK_END = 1 << 1,
|
||||
PARENT = 1 << 2,
|
||||
ROOT = 1 << 3,
|
||||
KEYED_HASH = 1 << 4,
|
||||
DERIVE_KEY_CONTEXT = 1 << 5,
|
||||
DERIVE_KEY_MATERIAL = 1 << 6,
|
||||
};
|
||||
|
||||
// This C implementation tries to support recent versions of GCC, Clang, and
|
||||
// MSVC.
|
||||
#if defined(_MSC_VER)
|
||||
#define INLINE static __forceinline
|
||||
#else
|
||||
#define INLINE static inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
#define IS_X86
|
||||
#define IS_X86_64
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(_M_IX86)
|
||||
#define IS_X86
|
||||
#define IS_X86_32
|
||||
#endif
|
||||
|
||||
#if defined(IS_X86)
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(IS_X86)
|
||||
#define MAX_SIMD_DEGREE 16
|
||||
#elif defined(BLAKE3_USE_NEON)
|
||||
#define MAX_SIMD_DEGREE 4
|
||||
#else
|
||||
#define MAX_SIMD_DEGREE 1
|
||||
#endif
|
||||
|
||||
// There are some places where we want a static size that's equal to the
|
||||
// MAX_SIMD_DEGREE, but also at least 2.
|
||||
#define MAX_SIMD_DEGREE_OR_2 (MAX_SIMD_DEGREE > 2 ? MAX_SIMD_DEGREE : 2)
|
||||
|
||||
static const uint32_t IV[8] = {0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL,
|
||||
0xA54FF53AUL, 0x510E527FUL, 0x9B05688CUL,
|
||||
0x1F83D9ABUL, 0x5BE0CD19UL};
|
||||
|
||||
static const uint8_t MSG_SCHEDULE[7][16] = {
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
||||
{2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8},
|
||||
{3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1},
|
||||
{10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6},
|
||||
{12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4},
|
||||
{9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7},
|
||||
{11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13},
|
||||
};
|
||||
|
||||
/* Find index of the highest set bit */
|
||||
/* x is assumed to be nonzero. */
|
||||
static unsigned int highest_one(uint64_t x) {
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
return 63 ^ __builtin_clzll(x);
|
||||
#elif defined(_MSC_VER) && defined(IS_X86_64)
|
||||
unsigned long index;
|
||||
_BitScanReverse64(&index, x);
|
||||
return index;
|
||||
#elif defined(_MSC_VER) && defined(IS_X86_32)
|
||||
if(x >> 32) {
|
||||
unsigned long index;
|
||||
_BitScanReverse(&index, x >> 32);
|
||||
return 32 + index;
|
||||
} else {
|
||||
unsigned long index;
|
||||
_BitScanReverse(&index, x);
|
||||
return index;
|
||||
}
|
||||
#else
|
||||
unsigned int c = 0;
|
||||
if(x & 0xffffffff00000000ULL) { x >>= 32; c += 32; }
|
||||
if(x & 0x00000000ffff0000ULL) { x >>= 16; c += 16; }
|
||||
if(x & 0x000000000000ff00ULL) { x >>= 8; c += 8; }
|
||||
if(x & 0x00000000000000f0ULL) { x >>= 4; c += 4; }
|
||||
if(x & 0x000000000000000cULL) { x >>= 2; c += 2; }
|
||||
if(x & 0x0000000000000002ULL) { c += 1; }
|
||||
return c;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Count the number of 1 bits.
|
||||
INLINE unsigned int popcnt(uint64_t x) {
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
return __builtin_popcountll(x);
|
||||
#else
|
||||
unsigned int count = 0;
|
||||
while (x != 0) {
|
||||
count += 1;
|
||||
x &= x - 1;
|
||||
}
|
||||
return count;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Largest power of two less than or equal to x. As a special case, returns 1
|
||||
// when x is 0.
|
||||
INLINE uint64_t round_down_to_power_of_2(uint64_t x) {
|
||||
return 1ULL << highest_one(x | 1);
|
||||
}
|
||||
|
||||
INLINE uint32_t counter_low(uint64_t counter) { return (uint32_t)counter; }
|
||||
|
||||
INLINE uint32_t counter_high(uint64_t counter) {
|
||||
return (uint32_t)(counter >> 32);
|
||||
}
|
||||
|
||||
INLINE uint32_t load32(const void *src) {
|
||||
const uint8_t *p = (const uint8_t *)src;
|
||||
return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |
|
||||
((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24);
|
||||
}
|
||||
|
||||
INLINE void load_key_words(const uint8_t key[BLAKE3_KEY_LEN],
|
||||
uint32_t key_words[8]) {
|
||||
key_words[0] = load32(&key[0 * 4]);
|
||||
key_words[1] = load32(&key[1 * 4]);
|
||||
key_words[2] = load32(&key[2 * 4]);
|
||||
key_words[3] = load32(&key[3 * 4]);
|
||||
key_words[4] = load32(&key[4 * 4]);
|
||||
key_words[5] = load32(&key[5 * 4]);
|
||||
key_words[6] = load32(&key[6 * 4]);
|
||||
key_words[7] = load32(&key[7 * 4]);
|
||||
}
|
||||
|
||||
INLINE void store32(void *dst, uint32_t w) {
|
||||
uint8_t *p = (uint8_t *)dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
}
|
||||
|
||||
INLINE void store_cv_words(uint8_t bytes_out[32], uint32_t cv_words[8]) {
|
||||
store32(&bytes_out[0 * 4], cv_words[0]);
|
||||
store32(&bytes_out[1 * 4], cv_words[1]);
|
||||
store32(&bytes_out[2 * 4], cv_words[2]);
|
||||
store32(&bytes_out[3 * 4], cv_words[3]);
|
||||
store32(&bytes_out[4 * 4], cv_words[4]);
|
||||
store32(&bytes_out[5 * 4], cv_words[5]);
|
||||
store32(&bytes_out[6 * 4], cv_words[6]);
|
||||
store32(&bytes_out[7 * 4], cv_words[7]);
|
||||
}
|
||||
|
||||
void blake3_compress_in_place(uint32_t cv[8],
|
||||
const uint8_t block[BLAKE3_BLOCK_LEN],
|
||||
uint8_t block_len, uint64_t counter,
|
||||
uint8_t flags);
|
||||
|
||||
void blake3_compress_xof(const uint32_t cv[8],
|
||||
const uint8_t block[BLAKE3_BLOCK_LEN],
|
||||
uint8_t block_len, uint64_t counter, uint8_t flags,
|
||||
uint8_t out[64]);
|
||||
|
||||
void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs,
|
||||
size_t blocks, const uint32_t key[8], uint64_t counter,
|
||||
bool increment_counter, uint8_t flags,
|
||||
uint8_t flags_start, uint8_t flags_end, uint8_t *out);
|
||||
|
||||
size_t blake3_simd_degree(void);
|
||||
|
||||
|
||||
// Declarations for implementation-specific functions.
|
||||
void blake3_compress_in_place_portable(uint32_t cv[8],
|
||||
const uint8_t block[BLAKE3_BLOCK_LEN],
|
||||
uint8_t block_len, uint64_t counter,
|
||||
uint8_t flags);
|
||||
|
||||
void blake3_compress_xof_portable(const uint32_t cv[8],
|
||||
const uint8_t block[BLAKE3_BLOCK_LEN],
|
||||
uint8_t block_len, uint64_t counter,
|
||||
uint8_t flags, uint8_t out[64]);
|
||||
|
||||
void blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs,
|
||||
size_t blocks, const uint32_t key[8],
|
||||
uint64_t counter, bool increment_counter,
|
||||
uint8_t flags, uint8_t flags_start,
|
||||
uint8_t flags_end, uint8_t *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BLAKE3_H */
|
||||
60
C/hashes/hash.h
Normal file
60
C/hashes/hash.h
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of KTH nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* stuff in common between md4, md5, and sha1 */
|
||||
|
||||
#ifndef __hash_h__
|
||||
#define __hash_h__
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#pragma warning(disable : 4464)
|
||||
#pragma warning(disable : 4820)
|
||||
#pragma warning(disable : 4711)
|
||||
#include "../7zTypes.h"
|
||||
|
||||
#ifndef uint32_t
|
||||
typedef UInt32 uint32_t;
|
||||
#endif
|
||||
|
||||
#ifndef uint64_t
|
||||
typedef UInt64 uint64_t;
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) (((a)>(b))?(b):(a))
|
||||
#endif
|
||||
|
||||
#endif /* __hash_h__ */
|
||||
135
C/hashes/md2.c
Normal file
135
C/hashes/md2.c
Normal file
@@ -0,0 +1,135 @@
|
||||
|
||||
/*
|
||||
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
|
||||
*
|
||||
* Copyright (c) 2006 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "hash.h"
|
||||
#include "md2.h"
|
||||
|
||||
static const unsigned char subst[256] = {
|
||||
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
|
||||
19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
|
||||
76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
|
||||
138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
|
||||
245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
|
||||
148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
|
||||
39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
|
||||
181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
|
||||
150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
|
||||
112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
|
||||
96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
|
||||
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
|
||||
234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
|
||||
129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
|
||||
8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
|
||||
203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
|
||||
166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
|
||||
31, 26, 219, 153, 141, 51, 159, 17, 131, 20
|
||||
};
|
||||
|
||||
void
|
||||
MD2_Init (struct md2 *m)
|
||||
{
|
||||
memset(m, 0, sizeof(*m));
|
||||
}
|
||||
|
||||
static void
|
||||
calc(struct md2 *m, const void *v)
|
||||
{
|
||||
unsigned char x[48], L;
|
||||
const unsigned char *p = v;
|
||||
int i, j, t;
|
||||
|
||||
L = m->checksum[15];
|
||||
for (i = 0; i < 16; i++)
|
||||
L = m->checksum[i] ^= subst[p[i] ^ L];
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
x[i] = m->state[i];
|
||||
x[i + 16] = p[i];
|
||||
x[i + 32] = x[i] ^ p[i];
|
||||
}
|
||||
|
||||
t = 0;
|
||||
for (i = 0; i < 18; i++) {
|
||||
for (j = 0; j < 48; j++)
|
||||
t = x[j] ^= subst[t];
|
||||
t = (t + i) & 0xff;
|
||||
}
|
||||
|
||||
memcpy(m->state, x, 16);
|
||||
memset(x, 0, sizeof(x));
|
||||
}
|
||||
|
||||
void
|
||||
MD2_Update (struct md2 *m, const void *v, size_t len)
|
||||
{
|
||||
size_t idx = m->len & 0xf;
|
||||
const unsigned char *p = v;
|
||||
|
||||
m->len += len;
|
||||
if (len + idx >= 16) {
|
||||
if (idx) {
|
||||
memcpy(m->data + idx, p, 16 - idx);
|
||||
calc(m, m->data);
|
||||
p += 16;
|
||||
len -= 16 - idx;
|
||||
}
|
||||
while (len >= 16) {
|
||||
calc(m, p);
|
||||
p += 16;
|
||||
len -= 16;
|
||||
}
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
memcpy(m->data + idx, p, len);
|
||||
}
|
||||
|
||||
void
|
||||
MD2_Final (void *res, struct md2 *m)
|
||||
{
|
||||
unsigned char pad[16];
|
||||
size_t padlen;
|
||||
|
||||
padlen = 16 - (m->len % 16);
|
||||
memset(pad, (int)padlen, padlen);
|
||||
|
||||
MD2_Update(m, pad, padlen);
|
||||
memcpy(pad, m->checksum, 16);
|
||||
MD2_Update(m, pad, 16);
|
||||
|
||||
memcpy(res, m->state, MD2_DIGEST_LENGTH);
|
||||
memset(m, 0, sizeof(*m));
|
||||
}
|
||||
59
C/hashes/md2.h
Normal file
59
C/hashes/md2.h
Normal file
@@ -0,0 +1,59 @@
|
||||
|
||||
/*
|
||||
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
|
||||
*
|
||||
* Copyright (c) 2006 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef HEIM_MD2_H
|
||||
#define HEIM_MD2_H 1
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#define MD2_DIGEST_LENGTH 16
|
||||
|
||||
struct md2 {
|
||||
size_t len;
|
||||
unsigned char data[16]; /* stored unalligned data between Update's */
|
||||
unsigned char checksum[16];
|
||||
unsigned char state[16]; /* lower 16 bytes of X */
|
||||
};
|
||||
|
||||
typedef struct md2 MD2_CTX;
|
||||
|
||||
void MD2_Init (struct md2 *m);
|
||||
void MD2_Update (struct md2 *m, const void *p, size_t len);
|
||||
void MD2_Final (void *res, struct md2 *m);
|
||||
|
||||
#endif /* HEIM_MD2_H */
|
||||
266
C/hashes/md4.c
Normal file
266
C/hashes/md4.c
Normal file
@@ -0,0 +1,266 @@
|
||||
|
||||
/*
|
||||
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
|
||||
*
|
||||
* Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "hash.h"
|
||||
#include "md4.h"
|
||||
|
||||
#define A m->counter[0]
|
||||
#define B m->counter[1]
|
||||
#define C m->counter[2]
|
||||
#define D m->counter[3]
|
||||
#define X data
|
||||
|
||||
/* Vector Crays doesn't have a good 32-bit type, or more precisely,
|
||||
int32_t as defined by <bind/bitypes.h> isn't 32 bits, and we don't
|
||||
want to depend in being able to redefine this type. To cope with
|
||||
this we have to clamp the result in some places to [0,2^32); no
|
||||
need to do this on other machines. Did I say this was a mess?
|
||||
*/
|
||||
|
||||
#ifdef _CRAY
|
||||
#define CRAYFIX(X) ((X) & 0xffffffff)
|
||||
#else
|
||||
#define CRAYFIX(X) (X)
|
||||
#endif
|
||||
|
||||
static uint32_t cshift (uint32_t x, unsigned int n)
|
||||
{
|
||||
x = CRAYFIX(x);
|
||||
return CRAYFIX((x << n) | (x >> (32 - n)));
|
||||
}
|
||||
|
||||
void
|
||||
MD4_Init (struct md4 *m)
|
||||
{
|
||||
m->sz[0] = 0;
|
||||
m->sz[1] = 0;
|
||||
D = 0x10325476;
|
||||
C = 0x98badcfe;
|
||||
B = 0xefcdab89;
|
||||
A = 0x67452301;
|
||||
}
|
||||
|
||||
#define F(x,y,z) CRAYFIX((x & y) | (~x & z))
|
||||
#define G(x,y,z) ((x & y) | (x & z) | (y & z))
|
||||
#define H(x,y,z) (x ^ y ^ z)
|
||||
|
||||
#define DOIT(a,b,c,d,k,s,i,OP) \
|
||||
a = cshift(a + OP(b,c,d) + X[k] + i, s)
|
||||
|
||||
#define DO1(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,F)
|
||||
#define DO2(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,G)
|
||||
#define DO3(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,H)
|
||||
|
||||
static void
|
||||
calc (struct md4 *m, uint32_t *data)
|
||||
{
|
||||
uint32_t AA, BB, CC, DD;
|
||||
|
||||
AA = A;
|
||||
BB = B;
|
||||
CC = C;
|
||||
DD = D;
|
||||
|
||||
/* Round 1 */
|
||||
|
||||
DO1(A,B,C,D,0,3,0);
|
||||
DO1(D,A,B,C,1,7,0);
|
||||
DO1(C,D,A,B,2,11,0);
|
||||
DO1(B,C,D,A,3,19,0);
|
||||
|
||||
DO1(A,B,C,D,4,3,0);
|
||||
DO1(D,A,B,C,5,7,0);
|
||||
DO1(C,D,A,B,6,11,0);
|
||||
DO1(B,C,D,A,7,19,0);
|
||||
|
||||
DO1(A,B,C,D,8,3,0);
|
||||
DO1(D,A,B,C,9,7,0);
|
||||
DO1(C,D,A,B,10,11,0);
|
||||
DO1(B,C,D,A,11,19,0);
|
||||
|
||||
DO1(A,B,C,D,12,3,0);
|
||||
DO1(D,A,B,C,13,7,0);
|
||||
DO1(C,D,A,B,14,11,0);
|
||||
DO1(B,C,D,A,15,19,0);
|
||||
|
||||
/* Round 2 */
|
||||
|
||||
DO2(A,B,C,D,0,3,0x5A827999);
|
||||
DO2(D,A,B,C,4,5,0x5A827999);
|
||||
DO2(C,D,A,B,8,9,0x5A827999);
|
||||
DO2(B,C,D,A,12,13,0x5A827999);
|
||||
|
||||
DO2(A,B,C,D,1,3,0x5A827999);
|
||||
DO2(D,A,B,C,5,5,0x5A827999);
|
||||
DO2(C,D,A,B,9,9,0x5A827999);
|
||||
DO2(B,C,D,A,13,13,0x5A827999);
|
||||
|
||||
DO2(A,B,C,D,2,3,0x5A827999);
|
||||
DO2(D,A,B,C,6,5,0x5A827999);
|
||||
DO2(C,D,A,B,10,9,0x5A827999);
|
||||
DO2(B,C,D,A,14,13,0x5A827999);
|
||||
|
||||
DO2(A,B,C,D,3,3,0x5A827999);
|
||||
DO2(D,A,B,C,7,5,0x5A827999);
|
||||
DO2(C,D,A,B,11,9,0x5A827999);
|
||||
DO2(B,C,D,A,15,13,0x5A827999);
|
||||
|
||||
/* Round 3 */
|
||||
|
||||
DO3(A,B,C,D,0,3,0x6ED9EBA1);
|
||||
DO3(D,A,B,C,8,9,0x6ED9EBA1);
|
||||
DO3(C,D,A,B,4,11,0x6ED9EBA1);
|
||||
DO3(B,C,D,A,12,15,0x6ED9EBA1);
|
||||
|
||||
DO3(A,B,C,D,2,3,0x6ED9EBA1);
|
||||
DO3(D,A,B,C,10,9,0x6ED9EBA1);
|
||||
DO3(C,D,A,B,6,11,0x6ED9EBA1);
|
||||
DO3(B,C,D,A,14,15,0x6ED9EBA1);
|
||||
|
||||
DO3(A,B,C,D,1,3,0x6ED9EBA1);
|
||||
DO3(D,A,B,C,9,9,0x6ED9EBA1);
|
||||
DO3(C,D,A,B,5,11,0x6ED9EBA1);
|
||||
DO3(B,C,D,A,13,15,0x6ED9EBA1);
|
||||
|
||||
DO3(A,B,C,D,3,3,0x6ED9EBA1);
|
||||
DO3(D,A,B,C,11,9,0x6ED9EBA1);
|
||||
DO3(C,D,A,B,7,11,0x6ED9EBA1);
|
||||
DO3(B,C,D,A,15,15,0x6ED9EBA1);
|
||||
|
||||
A += AA;
|
||||
B += BB;
|
||||
C += CC;
|
||||
D += DD;
|
||||
}
|
||||
|
||||
/*
|
||||
* From `Performance analysis of MD5' by Joseph D. Touch <touch@isi.edu>
|
||||
*/
|
||||
|
||||
#if defined(WORDS_BIGENDIAN)
|
||||
static uint32_t
|
||||
swap_uint32_t (uint32_t t)
|
||||
{
|
||||
uint32_t temp1, temp2;
|
||||
|
||||
temp1 = cshift(t, 16);
|
||||
temp2 = temp1 >> 8;
|
||||
temp1 &= 0x00ff00ff;
|
||||
temp2 &= 0x00ff00ff;
|
||||
temp1 <<= 8;
|
||||
return temp1 | temp2;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct x32{
|
||||
unsigned int a:32;
|
||||
unsigned int b:32;
|
||||
};
|
||||
|
||||
void
|
||||
MD4_Update (struct md4 *m, const void *v, size_t len)
|
||||
{
|
||||
const unsigned char *p = v;
|
||||
size_t old_sz = m->sz[0];
|
||||
size_t offset;
|
||||
|
||||
m->sz[0] += (unsigned int)len * 8;
|
||||
if (m->sz[0] < old_sz)
|
||||
++m->sz[1];
|
||||
offset = (old_sz / 8) % 64;
|
||||
while(len > 0) {
|
||||
size_t l = min(len, 64 - offset);
|
||||
memcpy(m->save + offset, p, l);
|
||||
offset += l;
|
||||
p += l;
|
||||
len -= l;
|
||||
if(offset == 64) {
|
||||
#if defined(WORDS_BIGENDIAN)
|
||||
int i;
|
||||
uint32_t current[16];
|
||||
struct x32 *us = (struct x32*)m->save;
|
||||
for(i = 0; i < 8; i++){
|
||||
current[2*i+0] = swap_uint32_t(us[i].a);
|
||||
current[2*i+1] = swap_uint32_t(us[i].b);
|
||||
}
|
||||
calc(m, current);
|
||||
#else
|
||||
calc(m, (uint32_t*)m->save);
|
||||
#endif
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MD4_Final (void *res, struct md4 *m)
|
||||
{
|
||||
unsigned char zeros[72];
|
||||
unsigned offset = (m->sz[0] / 8) % 64;
|
||||
unsigned int dstart = (120 - offset - 1) % 64 + 1;
|
||||
|
||||
*zeros = 0x80;
|
||||
memset (zeros + 1, 0, sizeof(zeros) - 1);
|
||||
zeros[dstart+0] = (m->sz[0] >> 0) & 0xff;
|
||||
zeros[dstart+1] = (m->sz[0] >> 8) & 0xff;
|
||||
zeros[dstart+2] = (m->sz[0] >> 16) & 0xff;
|
||||
zeros[dstart+3] = (m->sz[0] >> 24) & 0xff;
|
||||
zeros[dstart+4] = (m->sz[1] >> 0) & 0xff;
|
||||
zeros[dstart+5] = (m->sz[1] >> 8) & 0xff;
|
||||
zeros[dstart+6] = (m->sz[1] >> 16) & 0xff;
|
||||
zeros[dstart+7] = (m->sz[1] >> 24) & 0xff;
|
||||
MD4_Update (m, zeros, dstart + 8);
|
||||
{
|
||||
int i;
|
||||
unsigned char *r = (unsigned char *)res;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
r[4*i] = m->counter[i] & 0xFF;
|
||||
r[4*i+1] = (m->counter[i] >> 8) & 0xFF;
|
||||
r[4*i+2] = (m->counter[i] >> 16) & 0xFF;
|
||||
r[4*i+3] = (m->counter[i] >> 24) & 0xFF;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
uint32_t *r = (uint32_t *)res;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
r[i] = swap_uint32_t (m->counter[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
64
C/hashes/md4.h
Normal file
64
C/hashes/md4.h
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
/*
|
||||
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
|
||||
*
|
||||
* Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef HEIM_MD4_H
|
||||
#define HEIM_MD4_H 1
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#define MD4_DIGEST_LENGTH 16
|
||||
|
||||
struct md4 {
|
||||
unsigned int sz[2];
|
||||
uint32_t counter[4];
|
||||
unsigned char save[64];
|
||||
};
|
||||
|
||||
typedef struct md4 MD4_CTX;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" void MD4_Init (struct md4 *m);
|
||||
extern "C" void MD4_Update (struct md4 *m, const void *p, size_t len);
|
||||
extern "C" void MD4_Final (void *res, struct md4 *m);
|
||||
#else
|
||||
void MD4_Init (struct md4 *m);
|
||||
void MD4_Update (struct md4 *m, const void *p, size_t len);
|
||||
void MD4_Final (void *res, struct md4 *m);
|
||||
#endif
|
||||
|
||||
#endif /* HEIM_MD4_H */
|
||||
290
C/hashes/md5.c
Normal file
290
C/hashes/md5.c
Normal file
@@ -0,0 +1,290 @@
|
||||
|
||||
/*
|
||||
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
|
||||
*
|
||||
* Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "hash.h"
|
||||
#include "md5.h"
|
||||
|
||||
#define A m->counter[0]
|
||||
#define B m->counter[1]
|
||||
#define C m->counter[2]
|
||||
#define D m->counter[3]
|
||||
#define X data
|
||||
|
||||
/* Vector Crays doesn't have a good 32-bit type, or more precisely,
|
||||
int32_t as defined by <bind/bitypes.h> isn't 32 bits, and we don't
|
||||
want to depend in being able to redefine this type. To cope with
|
||||
this we have to clamp the result in some places to [0,2^32); no
|
||||
need to do this on other machines. Did I say this was a mess?
|
||||
*/
|
||||
|
||||
#ifdef _CRAY
|
||||
#define CRAYFIX(X) ((X) & 0xffffffff)
|
||||
#else
|
||||
#define CRAYFIX(X) (X)
|
||||
#endif
|
||||
|
||||
static uint32_t cshift (uint32_t x, unsigned int n)
|
||||
{
|
||||
x = CRAYFIX(x);
|
||||
return CRAYFIX((x << n) | (x >> (32 - n)));
|
||||
}
|
||||
|
||||
void
|
||||
MD5_Init (struct md5 *m)
|
||||
{
|
||||
m->sz[0] = 0;
|
||||
m->sz[1] = 0;
|
||||
D = 0x10325476;
|
||||
C = 0x98badcfe;
|
||||
B = 0xefcdab89;
|
||||
A = 0x67452301;
|
||||
}
|
||||
|
||||
#define F(x,y,z) CRAYFIX((x & y) | (~x & z))
|
||||
#define G(x,y,z) CRAYFIX((x & z) | (y & ~z))
|
||||
#define H(x,y,z) (x ^ y ^ z)
|
||||
#define I(x,y,z) CRAYFIX(y ^ (x | ~z))
|
||||
|
||||
#define DOIT(a,b,c,d,k,s,i,OP) \
|
||||
a = b + cshift(a + OP(b,c,d) + X[k] + (i), s)
|
||||
|
||||
#define DO1(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,F)
|
||||
#define DO2(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,G)
|
||||
#define DO3(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,H)
|
||||
#define DO4(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,I)
|
||||
|
||||
static void
|
||||
calc (struct md5 *m, uint32_t *data)
|
||||
{
|
||||
uint32_t AA, BB, CC, DD;
|
||||
|
||||
AA = A;
|
||||
BB = B;
|
||||
CC = C;
|
||||
DD = D;
|
||||
|
||||
/* Round 1 */
|
||||
|
||||
DO1(A,B,C,D,0,7,0xd76aa478);
|
||||
DO1(D,A,B,C,1,12,0xe8c7b756);
|
||||
DO1(C,D,A,B,2,17,0x242070db);
|
||||
DO1(B,C,D,A,3,22,0xc1bdceee);
|
||||
|
||||
DO1(A,B,C,D,4,7,0xf57c0faf);
|
||||
DO1(D,A,B,C,5,12,0x4787c62a);
|
||||
DO1(C,D,A,B,6,17,0xa8304613);
|
||||
DO1(B,C,D,A,7,22,0xfd469501);
|
||||
|
||||
DO1(A,B,C,D,8,7,0x698098d8);
|
||||
DO1(D,A,B,C,9,12,0x8b44f7af);
|
||||
DO1(C,D,A,B,10,17,0xffff5bb1);
|
||||
DO1(B,C,D,A,11,22,0x895cd7be);
|
||||
|
||||
DO1(A,B,C,D,12,7,0x6b901122);
|
||||
DO1(D,A,B,C,13,12,0xfd987193);
|
||||
DO1(C,D,A,B,14,17,0xa679438e);
|
||||
DO1(B,C,D,A,15,22,0x49b40821);
|
||||
|
||||
/* Round 2 */
|
||||
|
||||
DO2(A,B,C,D,1,5,0xf61e2562);
|
||||
DO2(D,A,B,C,6,9,0xc040b340);
|
||||
DO2(C,D,A,B,11,14,0x265e5a51);
|
||||
DO2(B,C,D,A,0,20,0xe9b6c7aa);
|
||||
|
||||
DO2(A,B,C,D,5,5,0xd62f105d);
|
||||
DO2(D,A,B,C,10,9,0x2441453);
|
||||
DO2(C,D,A,B,15,14,0xd8a1e681);
|
||||
DO2(B,C,D,A,4,20,0xe7d3fbc8);
|
||||
|
||||
DO2(A,B,C,D,9,5,0x21e1cde6);
|
||||
DO2(D,A,B,C,14,9,0xc33707d6);
|
||||
DO2(C,D,A,B,3,14,0xf4d50d87);
|
||||
DO2(B,C,D,A,8,20,0x455a14ed);
|
||||
|
||||
DO2(A,B,C,D,13,5,0xa9e3e905);
|
||||
DO2(D,A,B,C,2,9,0xfcefa3f8);
|
||||
DO2(C,D,A,B,7,14,0x676f02d9);
|
||||
DO2(B,C,D,A,12,20,0x8d2a4c8a);
|
||||
|
||||
/* Round 3 */
|
||||
|
||||
DO3(A,B,C,D,5,4,0xfffa3942);
|
||||
DO3(D,A,B,C,8,11,0x8771f681);
|
||||
DO3(C,D,A,B,11,16,0x6d9d6122);
|
||||
DO3(B,C,D,A,14,23,0xfde5380c);
|
||||
|
||||
DO3(A,B,C,D,1,4,0xa4beea44);
|
||||
DO3(D,A,B,C,4,11,0x4bdecfa9);
|
||||
DO3(C,D,A,B,7,16,0xf6bb4b60);
|
||||
DO3(B,C,D,A,10,23,0xbebfbc70);
|
||||
|
||||
DO3(A,B,C,D,13,4,0x289b7ec6);
|
||||
DO3(D,A,B,C,0,11,0xeaa127fa);
|
||||
DO3(C,D,A,B,3,16,0xd4ef3085);
|
||||
DO3(B,C,D,A,6,23,0x4881d05);
|
||||
|
||||
DO3(A,B,C,D,9,4,0xd9d4d039);
|
||||
DO3(D,A,B,C,12,11,0xe6db99e5);
|
||||
DO3(C,D,A,B,15,16,0x1fa27cf8);
|
||||
DO3(B,C,D,A,2,23,0xc4ac5665);
|
||||
|
||||
/* Round 4 */
|
||||
|
||||
DO4(A,B,C,D,0,6,0xf4292244);
|
||||
DO4(D,A,B,C,7,10,0x432aff97);
|
||||
DO4(C,D,A,B,14,15,0xab9423a7);
|
||||
DO4(B,C,D,A,5,21,0xfc93a039);
|
||||
|
||||
DO4(A,B,C,D,12,6,0x655b59c3);
|
||||
DO4(D,A,B,C,3,10,0x8f0ccc92);
|
||||
DO4(C,D,A,B,10,15,0xffeff47d);
|
||||
DO4(B,C,D,A,1,21,0x85845dd1);
|
||||
|
||||
DO4(A,B,C,D,8,6,0x6fa87e4f);
|
||||
DO4(D,A,B,C,15,10,0xfe2ce6e0);
|
||||
DO4(C,D,A,B,6,15,0xa3014314);
|
||||
DO4(B,C,D,A,13,21,0x4e0811a1);
|
||||
|
||||
DO4(A,B,C,D,4,6,0xf7537e82);
|
||||
DO4(D,A,B,C,11,10,0xbd3af235);
|
||||
DO4(C,D,A,B,2,15,0x2ad7d2bb);
|
||||
DO4(B,C,D,A,9,21,0xeb86d391);
|
||||
|
||||
A += AA;
|
||||
B += BB;
|
||||
C += CC;
|
||||
D += DD;
|
||||
}
|
||||
|
||||
/*
|
||||
* From `Performance analysis of MD5' by Joseph D. Touch <touch@isi.edu>
|
||||
*/
|
||||
|
||||
#if defined(WORDS_BIGENDIAN)
|
||||
static uint32_t
|
||||
swap_uint32_t (uint32_t t)
|
||||
{
|
||||
uint32_t temp1, temp2;
|
||||
|
||||
temp1 = cshift(t, 16);
|
||||
temp2 = temp1 >> 8;
|
||||
temp1 &= 0x00ff00ff;
|
||||
temp2 &= 0x00ff00ff;
|
||||
temp1 <<= 8;
|
||||
return temp1 | temp2;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct x32{
|
||||
unsigned int a:32;
|
||||
unsigned int b:32;
|
||||
};
|
||||
|
||||
void
|
||||
MD5_Update (struct md5 *m, const void *v, size_t len)
|
||||
{
|
||||
const unsigned char *p = v;
|
||||
size_t old_sz = m->sz[0];
|
||||
size_t offset;
|
||||
|
||||
m->sz[0] += (unsigned int)len * 8;
|
||||
if (m->sz[0] < old_sz)
|
||||
++m->sz[1];
|
||||
offset = (old_sz / 8) % 64;
|
||||
while(len > 0){
|
||||
size_t l = min(len, 64 - offset);
|
||||
memcpy(m->save + offset, p, l);
|
||||
offset += l;
|
||||
p += l;
|
||||
len -= l;
|
||||
if(offset == 64){
|
||||
#if defined(WORDS_BIGENDIAN)
|
||||
int i;
|
||||
uint32_t current[16];
|
||||
struct x32 *us = (struct x32*)m->save;
|
||||
for(i = 0; i < 8; i++){
|
||||
current[2*i+0] = swap_uint32_t(us[i].a);
|
||||
current[2*i+1] = swap_uint32_t(us[i].b);
|
||||
}
|
||||
calc(m, current);
|
||||
#else
|
||||
calc(m, (uint32_t*)m->save);
|
||||
#endif
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MD5_Final (void *res, struct md5 *m)
|
||||
{
|
||||
unsigned char zeros[72];
|
||||
unsigned offset = (m->sz[0] / 8) % 64;
|
||||
unsigned int dstart = (120 - offset - 1) % 64 + 1;
|
||||
|
||||
*zeros = 0x80;
|
||||
memset (zeros + 1, 0, sizeof(zeros) - 1);
|
||||
zeros[dstart+0] = (m->sz[0] >> 0) & 0xff;
|
||||
zeros[dstart+1] = (m->sz[0] >> 8) & 0xff;
|
||||
zeros[dstart+2] = (m->sz[0] >> 16) & 0xff;
|
||||
zeros[dstart+3] = (m->sz[0] >> 24) & 0xff;
|
||||
zeros[dstart+4] = (m->sz[1] >> 0) & 0xff;
|
||||
zeros[dstart+5] = (m->sz[1] >> 8) & 0xff;
|
||||
zeros[dstart+6] = (m->sz[1] >> 16) & 0xff;
|
||||
zeros[dstart+7] = (m->sz[1] >> 24) & 0xff;
|
||||
MD5_Update (m, zeros, dstart + 8);
|
||||
{
|
||||
int i;
|
||||
unsigned char *r = (unsigned char *)res;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
r[4*i] = m->counter[i] & 0xFF;
|
||||
r[4*i+1] = (m->counter[i] >> 8) & 0xFF;
|
||||
r[4*i+2] = (m->counter[i] >> 16) & 0xFF;
|
||||
r[4*i+3] = (m->counter[i] >> 24) & 0xFF;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
uint32_t *r = (uint32_t *)res;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
r[i] = swap_uint32_t (m->counter[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
56
C/hashes/md5.h
Normal file
56
C/hashes/md5.h
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef HEIM_MD5_H
|
||||
#define HEIM_MD5_H 1
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#define MD5_DIGEST_LENGTH 16
|
||||
|
||||
struct md5 {
|
||||
unsigned int sz[2];
|
||||
uint32_t counter[4];
|
||||
unsigned char save[64];
|
||||
};
|
||||
|
||||
typedef struct md5 MD5_CTX;
|
||||
|
||||
void MD5_Init (struct md5 *m);
|
||||
void MD5_Update (struct md5 *m, const void *p, size_t len);
|
||||
void MD5_Final (void *res, struct md5 *m); /* uint32_t res[4] */
|
||||
|
||||
#endif /* HEIM_MD5_H */
|
||||
239
C/hashes/sha3.c
Normal file
239
C/hashes/sha3.c
Normal file
@@ -0,0 +1,239 @@
|
||||
|
||||
/**
|
||||
* Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
|
||||
* Based on code from https://github.com/brainhub/SHA3IUF/
|
||||
*
|
||||
* This work is released into the public domain with CC0 1.0.
|
||||
*
|
||||
* Copyright (c) 2015. Andrey Jivsov <crypto@brainhub.org>
|
||||
* Copyright (c) 2023 Tino Reichardt <milky-7zip@mcmilk.de>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha3.h"
|
||||
|
||||
#define SHA3_ASSERT( x )
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define SHA3_CONST(x) x
|
||||
#else
|
||||
#define SHA3_CONST(x) x##L
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This flag is used to configure "pure" Keccak, as opposed to NIST SHA3.
|
||||
*/
|
||||
#define SHA3_USE_KECCAK_FLAG 0x80000000
|
||||
#define SHA3_CW(x) ((x) & (~SHA3_USE_KECCAK_FLAG))
|
||||
|
||||
#ifndef SHA3_ROTL64
|
||||
#define SHA3_ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
|
||||
#endif
|
||||
|
||||
static const uint64_t keccakf_rndc[24] = {
|
||||
SHA3_CONST(0x0000000000000001UL), SHA3_CONST(0x0000000000008082UL),
|
||||
SHA3_CONST(0x800000000000808aUL), SHA3_CONST(0x8000000080008000UL),
|
||||
SHA3_CONST(0x000000000000808bUL), SHA3_CONST(0x0000000080000001UL),
|
||||
SHA3_CONST(0x8000000080008081UL), SHA3_CONST(0x8000000000008009UL),
|
||||
SHA3_CONST(0x000000000000008aUL), SHA3_CONST(0x0000000000000088UL),
|
||||
SHA3_CONST(0x0000000080008009UL), SHA3_CONST(0x000000008000000aUL),
|
||||
SHA3_CONST(0x000000008000808bUL), SHA3_CONST(0x800000000000008bUL),
|
||||
SHA3_CONST(0x8000000000008089UL), SHA3_CONST(0x8000000000008003UL),
|
||||
SHA3_CONST(0x8000000000008002UL), SHA3_CONST(0x8000000000000080UL),
|
||||
SHA3_CONST(0x000000000000800aUL), SHA3_CONST(0x800000008000000aUL),
|
||||
SHA3_CONST(0x8000000080008081UL), SHA3_CONST(0x8000000000008080UL),
|
||||
SHA3_CONST(0x0000000080000001UL), SHA3_CONST(0x8000000080008008UL)
|
||||
};
|
||||
|
||||
static const unsigned keccakf_rotc[24] = {
|
||||
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62,
|
||||
18, 39, 61, 20, 44
|
||||
};
|
||||
|
||||
static const unsigned keccakf_piln[24] = {
|
||||
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20,
|
||||
14, 22, 9, 6, 1
|
||||
};
|
||||
|
||||
/* generally called after SHA3_KECCAK_SPONGE_WORDS-ctx->capacityWords words
|
||||
* are XORed into the state s
|
||||
*/
|
||||
static void keccakf(uint64_t s[25])
|
||||
{
|
||||
int i, j, round;
|
||||
uint64_t t, bc[5];
|
||||
#define KECCAK_ROUNDS 24
|
||||
|
||||
for (round = 0; round < KECCAK_ROUNDS; round++) {
|
||||
|
||||
/* Theta */
|
||||
for (i = 0; i < 5; i++)
|
||||
bc[i] =
|
||||
s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
t = bc[(i + 4) % 5] ^ SHA3_ROTL64(bc[(i + 1) % 5], 1);
|
||||
for (j = 0; j < 25; j += 5)
|
||||
s[j + i] ^= t;
|
||||
}
|
||||
|
||||
/* Rho Pi */
|
||||
t = s[1];
|
||||
for (i = 0; i < 24; i++) {
|
||||
j = keccakf_piln[i];
|
||||
bc[0] = s[j];
|
||||
s[j] = SHA3_ROTL64(t, keccakf_rotc[i]);
|
||||
t = bc[0];
|
||||
}
|
||||
|
||||
/* Chi */
|
||||
for (j = 0; j < 25; j += 5) {
|
||||
for (i = 0; i < 5; i++)
|
||||
bc[i] = s[j + i];
|
||||
for (i = 0; i < 5; i++)
|
||||
s[j + i] ^=
|
||||
(~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
|
||||
}
|
||||
|
||||
/* Iota */
|
||||
s[0] ^= keccakf_rndc[round];
|
||||
}
|
||||
}
|
||||
|
||||
/* *************************** Public Inteface ************************ */
|
||||
|
||||
void SHA3_Init(SHA3_CTX * ctx, unsigned bitSize)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
ctx->digest_length = bitSize;
|
||||
ctx->capacityWords = 2 * bitSize / (8 * sizeof(uint64_t));
|
||||
}
|
||||
|
||||
void SHA3_Update(SHA3_CTX * ctx, void const *bufIn, size_t len)
|
||||
{
|
||||
/* 0...7 -- how much is needed to have a word */
|
||||
unsigned old_tail = (8 - ctx->byteIndex) & 7;
|
||||
|
||||
size_t words;
|
||||
size_t tail;
|
||||
size_t i;
|
||||
|
||||
const uint8_t *buf = bufIn;
|
||||
|
||||
SHA3_ASSERT(ctx->byteIndex < 8);
|
||||
SHA3_ASSERT(ctx->wordIndex < sizeof(ctx->u.s) / sizeof(ctx->u.s[0]));
|
||||
|
||||
if (len < old_tail) { /* have no complete word or haven't started
|
||||
* the word yet */
|
||||
/* endian-independent code follows: */
|
||||
while (len--)
|
||||
ctx->saved |=
|
||||
(uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8);
|
||||
SHA3_ASSERT(ctx->byteIndex < 8);
|
||||
return;
|
||||
}
|
||||
|
||||
if (old_tail) { /* will have one word to process */
|
||||
/* endian-independent code follows: */
|
||||
len -= old_tail;
|
||||
while (old_tail--)
|
||||
ctx->saved |=
|
||||
(uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8);
|
||||
|
||||
/* now ready to add saved to the sponge */
|
||||
ctx->u.s[ctx->wordIndex] ^= ctx->saved;
|
||||
SHA3_ASSERT(ctx->byteIndex == 8);
|
||||
ctx->byteIndex = 0;
|
||||
ctx->saved = 0;
|
||||
if (++ctx->wordIndex ==
|
||||
(SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords))) {
|
||||
keccakf(ctx->u.s);
|
||||
ctx->wordIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* now work in full words directly from input */
|
||||
|
||||
SHA3_ASSERT(ctx->byteIndex == 0);
|
||||
|
||||
words = len / sizeof(uint64_t);
|
||||
tail = len - words * sizeof(uint64_t);
|
||||
|
||||
for (i = 0; i < words; i++, buf += sizeof(uint64_t)) {
|
||||
const uint64_t t = (uint64_t) (buf[0]) |
|
||||
((uint64_t) (buf[1]) << 8 * 1) |
|
||||
((uint64_t) (buf[2]) << 8 * 2) |
|
||||
((uint64_t) (buf[3]) << 8 * 3) |
|
||||
((uint64_t) (buf[4]) << 8 * 4) |
|
||||
((uint64_t) (buf[5]) << 8 * 5) |
|
||||
((uint64_t) (buf[6]) << 8 * 6) |
|
||||
((uint64_t) (buf[7]) << 8 * 7);
|
||||
#if defined(__x86_64__ ) || defined(__i386__)
|
||||
SHA3_ASSERT(memcmp(&t, buf, 8) == 0);
|
||||
#endif
|
||||
ctx->u.s[ctx->wordIndex] ^= t;
|
||||
if (++ctx->wordIndex ==
|
||||
(SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords))) {
|
||||
keccakf(ctx->u.s);
|
||||
ctx->wordIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* finally, save the partial word */
|
||||
SHA3_ASSERT(ctx->byteIndex == 0 && tail < 8);
|
||||
while (tail--) {
|
||||
ctx->saved |= (uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8);
|
||||
}
|
||||
SHA3_ASSERT(ctx->byteIndex < 8);
|
||||
}
|
||||
|
||||
/* This is simply the 'update' with the padding block.
|
||||
* The padding block is 0x01 || 0x00* || 0x80. First 0x01 and last 0x80
|
||||
* bytes are always present, but they can be the same byte.
|
||||
*/
|
||||
void SHA3_Final(void *res, SHA3_CTX * ctx)
|
||||
{
|
||||
/* Append 2-bit suffix 01, per SHA-3 spec. Instead of 1 for padding we
|
||||
* use 1<<2 below. The 0x02 below corresponds to the suffix 01.
|
||||
* Overall, we feed 0, then 1, and finally 1 to start padding. Without
|
||||
* M || 01, we would simply use 1 to start padding. */
|
||||
|
||||
uint64_t t;
|
||||
|
||||
/* SHA3 version */
|
||||
t = (uint64_t) (((uint64_t) (0x02 | (1 << 2))) <<
|
||||
((ctx->byteIndex) * 8));
|
||||
|
||||
ctx->u.s[ctx->wordIndex] ^= ctx->saved ^ t;
|
||||
|
||||
ctx->u.s[SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords) - 1] ^=
|
||||
SHA3_CONST(0x8000000000000000UL);
|
||||
keccakf(ctx->u.s);
|
||||
|
||||
/* Return first bytes of the ctx->s. This conversion is not needed for
|
||||
* little-endian platforms e.g. wrap with #if !defined(__BYTE_ORDER__)
|
||||
* || !defined(__ORDER_LITTLE_ENDIAN__) || __BYTE_ORDER__!=__ORDER_LITTLE_ENDIAN__
|
||||
* ... the conversion below ...
|
||||
* #endif */
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
|
||||
const unsigned t1 = (uint32_t) ctx->u.s[i];
|
||||
const unsigned t2 =
|
||||
(uint32_t) ((ctx->u.s[i] >> 16) >> 16);
|
||||
ctx->u.sb[i * 8 + 0] = (uint8_t) (t1);
|
||||
ctx->u.sb[i * 8 + 1] = (uint8_t) (t1 >> 8);
|
||||
ctx->u.sb[i * 8 + 2] = (uint8_t) (t1 >> 16);
|
||||
ctx->u.sb[i * 8 + 3] = (uint8_t) (t1 >> 24);
|
||||
ctx->u.sb[i * 8 + 4] = (uint8_t) (t2);
|
||||
ctx->u.sb[i * 8 + 5] = (uint8_t) (t2 >> 8);
|
||||
ctx->u.sb[i * 8 + 6] = (uint8_t) (t2 >> 16);
|
||||
ctx->u.sb[i * 8 + 7] = (uint8_t) (t2 >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(res, ctx->u.sb, ctx->digest_length/8);
|
||||
}
|
||||
47
C/hashes/sha3.h
Normal file
47
C/hashes/sha3.h
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
/**
|
||||
* Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
|
||||
* Based on code from https://github.com/brainhub/SHA3IUF/
|
||||
*
|
||||
* This work is released into the public domain with CC0 1.0.
|
||||
*
|
||||
* Copyright (c) 2015. Andrey Jivsov <crypto@brainhub.org>
|
||||
* Copyright (c) 2023 Tino Reichardt <milky-7zip@mcmilk.de>
|
||||
*/
|
||||
|
||||
#ifndef SHA3_H
|
||||
#define SHA3_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma warning(disable : 4464)
|
||||
#pragma warning(disable : 4820)
|
||||
#pragma warning(disable : 4711)
|
||||
|
||||
#define SHA3_256_DIGEST_LENGTH 32
|
||||
#define SHA3_384_DIGEST_LENGTH 48
|
||||
#define SHA3_512_DIGEST_LENGTH 64
|
||||
|
||||
/* 'Words' here refers to uint64_t */
|
||||
#define SHA3_KECCAK_SPONGE_WORDS (200 / sizeof(uint64_t))
|
||||
typedef struct sha3_context_ {
|
||||
/* the portion of the input message that we didn't consume yet */
|
||||
uint64_t saved;
|
||||
uint64_t byteIndex; /* 0..7--the next byte after the set one */
|
||||
uint64_t wordIndex; /* 0..24--the next word to integrate input */
|
||||
uint64_t capacityWords; /* the double size of the hash output in words */
|
||||
|
||||
/* Keccak's state */
|
||||
union {
|
||||
uint64_t s[SHA3_KECCAK_SPONGE_WORDS];
|
||||
uint8_t sb[SHA3_KECCAK_SPONGE_WORDS * 8];
|
||||
} u;
|
||||
|
||||
unsigned digest_length;
|
||||
} SHA3_CTX;
|
||||
|
||||
void SHA3_Init(SHA3_CTX * ctx, unsigned bitSize);
|
||||
void SHA3_Update(SHA3_CTX * ctx, void const *bufIn, size_t len);
|
||||
void SHA3_Final(void *, SHA3_CTX * ctx);
|
||||
|
||||
#endif
|
||||
298
C/hashes/sha512.c
Normal file
298
C/hashes/sha512.c
Normal file
@@ -0,0 +1,298 @@
|
||||
|
||||
/*
|
||||
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
|
||||
*
|
||||
* Copyright (c) 2006, 2010 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "sha512.h"
|
||||
|
||||
#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
|
||||
#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
|
||||
#define ROTR(x,n) (((x)>>(n)) | ((x) << (64 - (n))))
|
||||
|
||||
#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
|
||||
#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
|
||||
#define sigma0(x) (ROTR(x,1) ^ ROTR(x,8) ^ ((x)>>7))
|
||||
#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ ((x)>>6))
|
||||
|
||||
#define A m->counter[0]
|
||||
#define B m->counter[1]
|
||||
#define C m->counter[2]
|
||||
#define D m->counter[3]
|
||||
#define E m->counter[4]
|
||||
#define F m->counter[5]
|
||||
#define G m->counter[6]
|
||||
#define H m->counter[7]
|
||||
|
||||
static uint64_t cshift64 (uint64_t x, unsigned int n)
|
||||
{
|
||||
return ((uint64_t)x << (uint64_t)n) | ((uint64_t)x >> ((uint64_t)64 - (uint64_t)n));
|
||||
}
|
||||
|
||||
static const uint64_t constant_512[80] = {
|
||||
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
|
||||
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
|
||||
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
|
||||
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
|
||||
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
|
||||
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
|
||||
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
|
||||
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
|
||||
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
|
||||
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
|
||||
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
|
||||
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
|
||||
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
|
||||
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
|
||||
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
||||
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
|
||||
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
|
||||
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
|
||||
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
|
||||
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
|
||||
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
|
||||
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
|
||||
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
|
||||
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
|
||||
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
|
||||
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
|
||||
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
|
||||
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
|
||||
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
|
||||
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
||||
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
|
||||
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
|
||||
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
|
||||
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
|
||||
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
|
||||
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
|
||||
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
|
||||
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
|
||||
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
||||
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
|
||||
};
|
||||
|
||||
void
|
||||
SHA512_Init (SHA512_CTX *m)
|
||||
{
|
||||
m->sz[0] = 0;
|
||||
m->sz[1] = 0;
|
||||
A = 0x6a09e667f3bcc908ULL;
|
||||
B = 0xbb67ae8584caa73bULL;
|
||||
C = 0x3c6ef372fe94f82bULL;
|
||||
D = 0xa54ff53a5f1d36f1ULL;
|
||||
E = 0x510e527fade682d1ULL;
|
||||
F = 0x9b05688c2b3e6c1fULL;
|
||||
G = 0x1f83d9abfb41bd6bULL;
|
||||
H = 0x5be0cd19137e2179ULL;
|
||||
}
|
||||
|
||||
static void
|
||||
calc (SHA512_CTX *m, uint64_t *in)
|
||||
{
|
||||
uint64_t AA, BB, CC, DD, EE, FF, GG, HH;
|
||||
uint64_t data[80];
|
||||
int i;
|
||||
|
||||
AA = A;
|
||||
BB = B;
|
||||
CC = C;
|
||||
DD = D;
|
||||
EE = E;
|
||||
FF = F;
|
||||
GG = G;
|
||||
HH = H;
|
||||
|
||||
for (i = 0; i < 16; ++i)
|
||||
data[i] = in[i];
|
||||
for (i = 16; i < 80; ++i)
|
||||
data[i] = sigma1(data[i-2]) + data[i-7] +
|
||||
sigma0(data[i-15]) + data[i - 16];
|
||||
|
||||
for (i = 0; i < 80; i++) {
|
||||
uint64_t T1, T2;
|
||||
|
||||
T1 = HH + Sigma1(EE) + Ch(EE, FF, GG) + constant_512[i] + data[i];
|
||||
T2 = Sigma0(AA) + Maj(AA,BB,CC);
|
||||
|
||||
HH = GG;
|
||||
GG = FF;
|
||||
FF = EE;
|
||||
EE = DD + T1;
|
||||
DD = CC;
|
||||
CC = BB;
|
||||
BB = AA;
|
||||
AA = T1 + T2;
|
||||
}
|
||||
|
||||
A += AA;
|
||||
B += BB;
|
||||
C += CC;
|
||||
D += DD;
|
||||
E += EE;
|
||||
F += FF;
|
||||
G += GG;
|
||||
H += HH;
|
||||
}
|
||||
|
||||
/*
|
||||
* From `Performance analysis of MD5' by Joseph D. Touch <touch@isi.edu>
|
||||
*/
|
||||
|
||||
#if !defined(WORDS_BIGENDIAN) || defined(_CRAY)
|
||||
static uint64_t
|
||||
swap_uint64_t (uint64_t t)
|
||||
{
|
||||
uint64_t temp;
|
||||
|
||||
temp = cshift64(t, 32);
|
||||
temp = ((temp & 0xff00ff00ff00ff00ULL) >> 8) |
|
||||
((temp & 0x00ff00ff00ff00ffULL) << 8);
|
||||
return ((temp & 0xffff0000ffff0000ULL) >> 16) |
|
||||
((temp & 0x0000ffff0000ffffULL) << 16);
|
||||
}
|
||||
|
||||
struct x64{
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
};
|
||||
#endif
|
||||
|
||||
void
|
||||
SHA512_Update (SHA512_CTX *m, const void *v, size_t len)
|
||||
{
|
||||
const unsigned char *p = v;
|
||||
size_t old_sz = m->sz[0];
|
||||
size_t offset;
|
||||
|
||||
m->sz[0] += len * 8;
|
||||
if (m->sz[0] < old_sz)
|
||||
++m->sz[1];
|
||||
offset = (old_sz / 8) % 128;
|
||||
while(len > 0){
|
||||
size_t l = min(len, 128 - offset);
|
||||
memcpy(m->save + offset, p, l);
|
||||
offset += l;
|
||||
p += l;
|
||||
len -= l;
|
||||
if(offset == 128){
|
||||
#if !defined(WORDS_BIGENDIAN) || defined(_CRAY)
|
||||
int i;
|
||||
uint64_t current[16];
|
||||
struct x64 *us = (struct x64*)m->save;
|
||||
for(i = 0; i < 8; i++){
|
||||
current[2*i+0] = swap_uint64_t(us[i].a);
|
||||
current[2*i+1] = swap_uint64_t(us[i].b);
|
||||
}
|
||||
calc(m, current);
|
||||
#else
|
||||
calc(m, (uint64_t*)m->save);
|
||||
#endif
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SHA512_Final (void *res, SHA512_CTX *m)
|
||||
{
|
||||
unsigned char zeros[128 + 16];
|
||||
unsigned offset = (m->sz[0] / 8) % 128;
|
||||
unsigned int dstart = (240 - offset - 1) % 128 + 1;
|
||||
|
||||
*zeros = 0x80;
|
||||
memset (zeros + 1, 0, sizeof(zeros) - 1);
|
||||
zeros[dstart+15] = (m->sz[0] >> 0) & 0xff;
|
||||
zeros[dstart+14] = (m->sz[0] >> 8) & 0xff;
|
||||
zeros[dstart+13] = (m->sz[0] >> 16) & 0xff;
|
||||
zeros[dstart+12] = (m->sz[0] >> 24) & 0xff;
|
||||
zeros[dstart+11] = (m->sz[0] >> 32) & 0xff;
|
||||
zeros[dstart+10] = (m->sz[0] >> 40) & 0xff;
|
||||
zeros[dstart+9] = (m->sz[0] >> 48) & 0xff;
|
||||
zeros[dstart+8] = (m->sz[0] >> 56) & 0xff;
|
||||
|
||||
zeros[dstart+7] = (m->sz[1] >> 0) & 0xff;
|
||||
zeros[dstart+6] = (m->sz[1] >> 8) & 0xff;
|
||||
zeros[dstart+5] = (m->sz[1] >> 16) & 0xff;
|
||||
zeros[dstart+4] = (m->sz[1] >> 24) & 0xff;
|
||||
zeros[dstart+3] = (m->sz[1] >> 32) & 0xff;
|
||||
zeros[dstart+2] = (m->sz[1] >> 40) & 0xff;
|
||||
zeros[dstart+1] = (m->sz[1] >> 48) & 0xff;
|
||||
zeros[dstart+0] = (m->sz[1] >> 56) & 0xff;
|
||||
SHA512_Update (m, zeros, dstart + 16);
|
||||
{
|
||||
int i;
|
||||
unsigned char *r = (unsigned char*)res;
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
r[8*i+7] = m->counter[i] & 0xFF;
|
||||
r[8*i+6] = (m->counter[i] >> 8) & 0xFF;
|
||||
r[8*i+5] = (m->counter[i] >> 16) & 0xFF;
|
||||
r[8*i+4] = (m->counter[i] >> 24) & 0xFF;
|
||||
r[8*i+3] = (m->counter[i] >> 32) & 0XFF;
|
||||
r[8*i+2] = (m->counter[i] >> 40) & 0xFF;
|
||||
r[8*i+1] = (m->counter[i] >> 48) & 0xFF;
|
||||
r[8*i] = (m->counter[i] >> 56) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SHA384_Init(SHA384_CTX *m)
|
||||
{
|
||||
m->sz[0] = 0;
|
||||
m->sz[1] = 0;
|
||||
A = 0xcbbb9d5dc1059ed8ULL;
|
||||
B = 0x629a292a367cd507ULL;
|
||||
C = 0x9159015a3070dd17ULL;
|
||||
D = 0x152fecd8f70e5939ULL;
|
||||
E = 0x67332667ffc00b31ULL;
|
||||
F = 0x8eb44a8768581511ULL;
|
||||
G = 0xdb0c2e0d64f98fa7ULL;
|
||||
H = 0x47b5481dbefa4fa4ULL;
|
||||
}
|
||||
|
||||
void
|
||||
SHA384_Update (SHA384_CTX *m, const void *v, size_t len)
|
||||
{
|
||||
SHA512_Update(m, v, len);
|
||||
}
|
||||
|
||||
void
|
||||
SHA384_Final (void *res, SHA384_CTX *m)
|
||||
{
|
||||
unsigned char data[SHA512_DIGEST_LENGTH];
|
||||
SHA512_Final(data, m);
|
||||
memcpy(res, data, SHA384_DIGEST_LENGTH);
|
||||
}
|
||||
74
C/hashes/sha512.h
Normal file
74
C/hashes/sha512.h
Normal file
@@ -0,0 +1,74 @@
|
||||
|
||||
/*
|
||||
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
|
||||
*
|
||||
* Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef HEIM_SHA_H
|
||||
#define HEIM_SHA_H 1
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
/*
|
||||
* SHA-2 512
|
||||
*/
|
||||
|
||||
#define SHA512_DIGEST_LENGTH 64
|
||||
|
||||
struct hc_sha512state {
|
||||
uint64_t sz[2];
|
||||
uint64_t counter[8];
|
||||
unsigned char save[128];
|
||||
};
|
||||
|
||||
typedef struct hc_sha512state SHA512_CTX;
|
||||
|
||||
void SHA512_Init (SHA512_CTX *);
|
||||
void SHA512_Update (SHA512_CTX *, const void *, size_t);
|
||||
void SHA512_Final (void *, SHA512_CTX *);
|
||||
|
||||
/*
|
||||
* SHA-2 384
|
||||
*/
|
||||
|
||||
#define SHA384_DIGEST_LENGTH 48
|
||||
|
||||
typedef struct hc_sha512state SHA384_CTX;
|
||||
|
||||
void SHA384_Init (SHA384_CTX *);
|
||||
void SHA384_Update (SHA384_CTX *, const void *, size_t);
|
||||
void SHA384_Final (void *, SHA384_CTX *);
|
||||
|
||||
#endif /* HEIM_SHA_H */
|
||||
@@ -27,6 +27,7 @@ OBJS = \
|
||||
$(COMPRESS_OBJS) \
|
||||
$(CRYPTO_OBJS) \
|
||||
$(C_OBJS) \
|
||||
$(HASHES_OBJS) \
|
||||
$(ASM_OBJS) \
|
||||
$O\resource.res \
|
||||
|
||||
@@ -234,6 +235,8 @@ $(C_OBJS): ../../../../C/$(*B).c
|
||||
$(COMPLB_O2)
|
||||
{../../../../C}.c{$O}.obj::
|
||||
$(CCOMPLB)
|
||||
{../../../../C/hashes}.c{$O}.obj::
|
||||
$(COMPLB_O2)
|
||||
|
||||
!ENDIF
|
||||
|
||||
|
||||
@@ -2999,3 +2999,36 @@ Z7_COM7F_IMF2(void, CBlake2spHasher::Final(Byte *digest))
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CBlake2spHasher, 0x202, "BLAKE2sp", BLAKE2S_DIGEST_SIZE)
|
||||
|
||||
/*
|
||||
class CBlake2spHasher:
|
||||
public IHasher,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CBlake2sp _blake;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
CBlake2spHasher() { Init(); }
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
INTERFACE_IHasher(;)
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CBlake2spHasher::Init() throw()
|
||||
{
|
||||
Blake2sp_Init(&_blake);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CBlake2spHasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
Blake2sp_Update(&_blake, (const Byte *)data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CBlake2spHasher::Final(Byte *digest) throw()
|
||||
{
|
||||
Blake2sp_Final(&_blake, digest);
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CBlake2spHasher, 0x202, "BLAKE2sp", BLAKE2S_DIGEST_SIZE)
|
||||
*/
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
COMMON_OBJS = \
|
||||
$O\Blake3Reg.obj \
|
||||
$O\CRC.obj \
|
||||
$O\CrcReg.obj \
|
||||
$O\DynLimBuf.obj \
|
||||
$O\IntToString.obj \
|
||||
$O\Md2Reg.obj \
|
||||
$O\Md4Reg.obj \
|
||||
$O\Md5Reg.obj \
|
||||
$O\LzFindPrepare.obj \
|
||||
$O\MyMap.obj \
|
||||
$O\MyString.obj \
|
||||
@@ -11,10 +15,17 @@ COMMON_OBJS = \
|
||||
$O\NewHandler.obj \
|
||||
$O\Sha1Reg.obj \
|
||||
$O\Sha256Reg.obj \
|
||||
$O\Sha384Reg.obj \
|
||||
$O\Sha512Reg.obj \
|
||||
$O\Sha3-256Reg.obj \
|
||||
$O\Sha3-384Reg.obj \
|
||||
$O\Sha3-512Reg.obj \
|
||||
$O\StringConvert.obj \
|
||||
$O\StringToInt.obj \
|
||||
$O\UTFConvert.obj \
|
||||
$O\Wildcard.obj \
|
||||
$O\XXH32Reg.obj \
|
||||
$O\XXH64Reg.obj \
|
||||
$O\XzCrc64Init.obj \
|
||||
$O\XzCrc64Reg.obj \
|
||||
|
||||
@@ -250,6 +261,14 @@ CRYPTO_OBJS = \
|
||||
$O\ZipCrypto.obj \
|
||||
$O\ZipStrong.obj \
|
||||
|
||||
HASHES_OBJS = \
|
||||
$O\blake3.obj \
|
||||
$O\md2.obj \
|
||||
$O\md4.obj \
|
||||
$O\md5.obj \
|
||||
$O\sha3.obj \
|
||||
$O\sha512.obj \
|
||||
|
||||
C_OBJS = \
|
||||
$O\7zBuf2.obj \
|
||||
$O\7zStream.obj \
|
||||
|
||||
@@ -795,18 +795,10 @@ static const char *SkipWhite(const char *s)
|
||||
|
||||
static const char * const k_CsumMethodNames[] =
|
||||
{
|
||||
"sha256"
|
||||
, "sha224"
|
||||
// , "sha512/224"
|
||||
// , "sha512/256"
|
||||
, "sha512"
|
||||
, "sha384"
|
||||
, "sha1"
|
||||
, "md5"
|
||||
, "blake2b"
|
||||
, "crc64"
|
||||
, "crc32"
|
||||
, "cksum"
|
||||
"sha3-512", "sha3-384", "sha3-256",
|
||||
"sha512", "sha384", "sha256", "sha224",
|
||||
"sha1", "md5", "blake2b",
|
||||
"crc32", "crc64" , "cksum"
|
||||
};
|
||||
|
||||
static UString GetMethod_from_FileName(const UString &name)
|
||||
@@ -1409,7 +1401,8 @@ static bool CheckDigests(const Byte *a, const Byte *b, size_t size)
|
||||
static void AddDefaultMethod(UStringVector &methods, unsigned size)
|
||||
{
|
||||
const char *m = NULL;
|
||||
if (size == 32) m = "sha256";
|
||||
if (size == 64) m = "sha512";
|
||||
else if (size == 32) m = "sha256";
|
||||
else if (size == 20) m = "sha1";
|
||||
else if (size == 16) m = "md5";
|
||||
else if (size == 8) m = "crc64";
|
||||
@@ -2090,11 +2083,11 @@ void Codecs_AddHashArcHandler(CCodecs *codecs)
|
||||
|
||||
// ubuntu uses "SHA256SUMS" file
|
||||
item.AddExts(UString (
|
||||
"sha256 sha512 sha224 sha384 sha1 sha md5"
|
||||
// "b2sum"
|
||||
" crc32 crc64"
|
||||
" asc"
|
||||
" cksum"
|
||||
"sha3-512 sha3-384 sha3-256 "
|
||||
"sha512 sha384 sha256 sha224 "
|
||||
"sha1 sha md5 "
|
||||
"crc32 crc64 "
|
||||
"asc cksum"
|
||||
),
|
||||
UString());
|
||||
|
||||
|
||||
@@ -293,16 +293,30 @@ struct CHashCommand
|
||||
|
||||
static const CHashCommand g_HashCommands[] =
|
||||
{
|
||||
{ CZipContextMenu::kHash_CRC32, "CRC-32", "CRC32" },
|
||||
{ CZipContextMenu::kHash_CRC64, "CRC-64", "CRC64" },
|
||||
{ CZipContextMenu::kHash_SHA1, "SHA-1", "SHA1" },
|
||||
{ CZipContextMenu::kHash_SHA256, "SHA-256", "SHA256" },
|
||||
{ CZipContextMenu::kHash_CRC32, "CRC-32", "CRC32" },
|
||||
{ CZipContextMenu::kHash_CRC64, "CRC-64", "CRC64" },
|
||||
{ CZipContextMenu::kHash_XXH32, "XXH-32 (NOT WORKING)", "XXH32 (NOT WORKING)" },
|
||||
{ CZipContextMenu::kHash_XXH64, "XXH-64 (NOT WORKING)", "XXH64 (NOT WORKING)" },
|
||||
{ CZipContextMenu::kHash_MD5, "MD2", "MD2" },
|
||||
{ CZipContextMenu::kHash_MD5, "MD4", "MD4" },
|
||||
{ CZipContextMenu::kHash_MD5, "MD5", "MD5" },
|
||||
{ CZipContextMenu::kHash_SHA1, "SHA-1", "SHA1" },
|
||||
{ CZipContextMenu::kHash_SHA256, "SHA2-256", "SHA256" },
|
||||
{ CZipContextMenu::kHash_SHA384, "SHA2-384", "SHA384" },
|
||||
{ CZipContextMenu::kHash_SHA512, "SHA2-512", "SHA512" },
|
||||
{ CZipContextMenu::kHash_BLAKE2sp, "BLAKE2sp", "BLAKE2sp" },
|
||||
{ CZipContextMenu::kHash_SHA256, "SHA3-256", "SHA3-256" },
|
||||
{ CZipContextMenu::kHash_SHA384, "SHA3-384", "SHA3-384" },
|
||||
{ CZipContextMenu::kHash_SHA512, "SHA3-512", "SHA3-512" },
|
||||
{ CZipContextMenu::kHash_BLAKE3, "BLAKE3", "BLAKE3" },
|
||||
{ CZipContextMenu::kHash_SHA256, "SHA3-256", "SHA3-256" },
|
||||
{ CZipContextMenu::kHash_SHA384, "SHA3-384", "SHA3-384" },
|
||||
{ CZipContextMenu::kHash_SHA512, "SHA3-512", "SHA3-512" },
|
||||
{ CZipContextMenu::kHash_All, "*", "*" },
|
||||
{ CZipContextMenu::kHash_Generate_SHA256, "SHA-256 -> file.sha256", "SHA256" },
|
||||
{ CZipContextMenu::kHash_Generate_SHA256, "SHA2-256 -> file.sha256", "SHA256" },
|
||||
{ CZipContextMenu::kHash_TestArc, "Checksum : Test", "Hash" }
|
||||
};
|
||||
|
||||
|
||||
static int FindCommand(CZipContextMenu::enum_CommandInternalID &id)
|
||||
{
|
||||
for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Commands); i++)
|
||||
@@ -1104,7 +1118,7 @@ Z7_COMWF_B CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
|
||||
showName += ".sha256";
|
||||
cmi.Folder = fs2us(folderPrefix);
|
||||
cmi.ArcName = name;
|
||||
s = "SHA-256 -> ";
|
||||
s = "SHA2-256 -> ";
|
||||
s += showName;
|
||||
}
|
||||
else if (hc.CommandInternalID == kHash_TestArc)
|
||||
@@ -1332,8 +1346,20 @@ HRESULT CZipContextMenu::InvokeCommandCommon(const CCommandMapItem &cmi)
|
||||
|
||||
case kHash_CRC32:
|
||||
case kHash_CRC64:
|
||||
case kHash_XXH32:
|
||||
case kHash_XXH64:
|
||||
case kHash_MD2:
|
||||
case kHash_MD4:
|
||||
case kHash_MD5:
|
||||
case kHash_SHA1:
|
||||
case kHash_SHA256:
|
||||
case kHash_SHA384:
|
||||
case kHash_SHA512:
|
||||
case kHash_BLAKE2sp:
|
||||
case kHash_SHA3_256:
|
||||
case kHash_SHA3_384:
|
||||
case kHash_SHA3_512:
|
||||
case kHash_BLAKE3:
|
||||
case kHash_All:
|
||||
case kHash_Generate_SHA256:
|
||||
case kHash_TestArc:
|
||||
|
||||
@@ -87,8 +87,20 @@ public:
|
||||
kCompressToZipEmail,
|
||||
kHash_CRC32,
|
||||
kHash_CRC64,
|
||||
kHash_XXH32,
|
||||
kHash_XXH64,
|
||||
kHash_MD2,
|
||||
kHash_MD4,
|
||||
kHash_MD5,
|
||||
kHash_SHA1,
|
||||
kHash_SHA256,
|
||||
kHash_SHA384,
|
||||
kHash_SHA512,
|
||||
kHash_BLAKE2sp,
|
||||
kHash_BLAKE3,
|
||||
kHash_SHA3_256,
|
||||
kHash_SHA3_384,
|
||||
kHash_SHA3_512,
|
||||
kHash_All,
|
||||
kHash_Generate_SHA256,
|
||||
kHash_TestArc
|
||||
@@ -103,6 +115,8 @@ public:
|
||||
|
||||
void LoadItems(IShellItemArray *psiItemArray);
|
||||
|
||||
HRESULT InitContextMenu(const wchar_t *folder, const wchar_t * const *names, unsigned numFiles);
|
||||
|
||||
CZipContextMenu();
|
||||
~CZipContextMenu();
|
||||
|
||||
|
||||
@@ -742,8 +742,17 @@ bool ExecuteFileCommand(unsigned id)
|
||||
case IDM_HASH_ALL: g_App.CalculateCrc("*"); break;
|
||||
case IDM_CRC32: g_App.CalculateCrc("CRC32"); break;
|
||||
case IDM_CRC64: g_App.CalculateCrc("CRC64"); break;
|
||||
case IDM_SHA1: g_App.CalculateCrc("SHA1"); break;
|
||||
case IDM_XXH32: g_App.CalculateCrc("XXH32 (NOT WORKING)"); break;
|
||||
case IDM_XXH64: g_App.CalculateCrc("XXH64 (NOT WORKING)"); break;
|
||||
case IDM_MD2: g_App.CalculateCrc("MD2"); break;
|
||||
case IDM_MD4: g_App.CalculateCrc("MD4"); break;
|
||||
case IDM_MD5: g_App.CalculateCrc("MD5"); break;
|
||||
case IDM_SHA1: g_App.CalculateCrc("SHA1"); break;
|
||||
case IDM_SHA256: g_App.CalculateCrc("SHA256"); break;
|
||||
case IDM_SHA384: g_App.CalculateCrc("SHA384"); break;
|
||||
case IDM_SHA512: g_App.CalculateCrc("SHA512"); break;
|
||||
case IDM_BLAKE2sp: g_App.CalculateCrc("BLAKE2sp"); break;
|
||||
case IDM_BLAKE3: g_App.CalculateCrc("BLAKE3"); break;
|
||||
|
||||
case IDM_DIFF: g_App.DiffFiles(); break;
|
||||
|
||||
|
||||
@@ -23,8 +23,20 @@
|
||||
#define IDM_HASH_ALL 101
|
||||
#define IDM_CRC32 102
|
||||
#define IDM_CRC64 103
|
||||
#define IDM_SHA1 104
|
||||
#define IDM_SHA256 105
|
||||
#define IDM_XXH32 104
|
||||
#define IDM_XXH64 105
|
||||
#define IDM_MD2 106
|
||||
#define IDM_MD4 107
|
||||
#define IDM_MD5 108
|
||||
#define IDM_SHA1 109
|
||||
#define IDM_SHA256 110
|
||||
// orig
|
||||
// #define IDM_SHA1 104
|
||||
// #define IDM_SHA256 105
|
||||
#define IDM_SHA384 111
|
||||
#define IDM_SHA512 112
|
||||
#define IDM_BLAKE2sp 113
|
||||
#define IDM_BLAKE3 114
|
||||
|
||||
|
||||
#define IDM_FILE 500
|
||||
|
||||
@@ -57,8 +57,17 @@ BEGIN
|
||||
BEGIN
|
||||
MENUITEM "CRC-32", IDM_CRC32
|
||||
MENUITEM "CRC-64", IDM_CRC64
|
||||
MENUITEM "xxHash-32 (Not Working)", IDM_XXH32
|
||||
MENUITEM "xxHash-64 (Not Working)", IDM_XXH64
|
||||
MENUITEM "MD2", IDM_MD2
|
||||
MENUITEM "MD4", IDM_MD4
|
||||
MENUITEM "MD5", IDM_MD5
|
||||
MENUITEM "SHA-1", IDM_SHA1
|
||||
MENUITEM "SHA-256", IDM_SHA256
|
||||
MENUITEM "SHA-384", IDM_SHA384
|
||||
MENUITEM "SHA-512", IDM_SHA512
|
||||
MENUITEM "Blake2sp", IDM_BLAKE2sp
|
||||
MENUITEM "Blake3", IDM_BLAKE3
|
||||
MENUITEM "*", IDM_HASH_ALL
|
||||
END
|
||||
MENUITEM "Di&ff", IDM_DIFF
|
||||
|
||||
38
CPP/Common/Blake3Reg.cpp
Normal file
38
CPP/Common/Blake3Reg.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Blake3Reg.cpp /TR 2021-04-06
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
#include "../../C/hashes/blake3.h"
|
||||
EXTERN_C_END
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
// BLAKE3
|
||||
Z7_CLASS_IMP_COM_1(CBLAKE3Hasher, IHasher)
|
||||
blake3_hasher _ctx;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
CBLAKE3Hasher() { blake3_hasher_init(&_ctx); }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CBLAKE3Hasher::Init() throw()
|
||||
{
|
||||
blake3_hasher_init(&_ctx);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CBLAKE3Hasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
blake3_hasher_update(&_ctx, data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CBLAKE3Hasher::Final(Byte *digest) throw()
|
||||
{
|
||||
blake3_hasher_finalize(&_ctx, digest, BLAKE3_OUT_LEN);
|
||||
}
|
||||
REGISTER_HASHER(CBLAKE3Hasher, 0x204, "BLAKE3", BLAKE3_OUT_LEN)
|
||||
@@ -52,4 +52,4 @@ Z7_COM7F_IMF2(void, CCksumHasher::Final(Byte *digest))
|
||||
SetUi32(digest, val)
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CCksumHasher, 0x203, "CKSUM", 4)
|
||||
REGISTER_HASHER(CCksumHasher, 0x202, "CKSUM", 4)
|
||||
|
||||
38
CPP/Common/Md2Reg.cpp
Normal file
38
CPP/Common/Md2Reg.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Md2Reg.cpp /TR 2018-11-02
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
#include "../../C/hashes/md2.h"
|
||||
EXTERN_C_END
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
// MD2
|
||||
Z7_CLASS_IMP_COM_1(CMD2Hasher, IHasher)
|
||||
MD2_CTX _ctx;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
CMD2Hasher() { MD2_Init(&_ctx); }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CMD2Hasher::Init() throw()
|
||||
{
|
||||
MD2_Init(&_ctx);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CMD2Hasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
MD2_Update(&_ctx, (const Byte *)data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CMD2Hasher::Final(Byte *digest) throw()
|
||||
{
|
||||
MD2_Final(digest, &_ctx);
|
||||
}
|
||||
REGISTER_HASHER(CMD2Hasher, 0x205, "MD2", MD2_DIGEST_LENGTH)
|
||||
38
CPP/Common/Md4Reg.cpp
Normal file
38
CPP/Common/Md4Reg.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Md4Reg.cpp /TR 2018-11-02
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
#include "../../C/hashes/md4.h"
|
||||
EXTERN_C_END
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
// MD4
|
||||
Z7_CLASS_IMP_COM_1(CMD4Hasher, IHasher)
|
||||
MD4_CTX _ctx;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
CMD4Hasher() { MD4_Init(&_ctx); }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CMD4Hasher::Init() throw()
|
||||
{
|
||||
MD4_Init(&_ctx);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CMD4Hasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
MD4_Update(&_ctx, (const Byte *)data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CMD4Hasher::Final(Byte *digest) throw()
|
||||
{
|
||||
MD4_Final(digest, &_ctx);
|
||||
}
|
||||
REGISTER_HASHER(CMD4Hasher, 0x206, "MD4", MD4_DIGEST_LENGTH)
|
||||
39
CPP/Common/Md5Reg.cpp
Normal file
39
CPP/Common/Md5Reg.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// MD5Reg.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
#include "../../C/hashes/md5.h"
|
||||
EXTERN_C_END
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
// MD5
|
||||
Z7_CLASS_IMP_COM_1(CMD5Hasher, IHasher)
|
||||
MD5_CTX _ctx;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
CMD5Hasher() { MD5_Init(&_ctx); }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CMD5Hasher::Init() throw()
|
||||
{
|
||||
MD5_Init(&_ctx);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CMD5Hasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
MD5_Update(&_ctx, (const Byte *)data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CMD5Hasher::Final(Byte *digest) throw()
|
||||
{
|
||||
MD5_Final(digest, &_ctx);
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CMD5Hasher, 0x207, "MD5", MD5_DIGEST_LENGTH)
|
||||
38
CPP/Common/Sha3-256Reg.cpp
Normal file
38
CPP/Common/Sha3-256Reg.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Sha3-256Reg.cpp /TR 2023-06-18
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
#include "../../C/hashes/sha3.h"
|
||||
EXTERN_C_END
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
// SHA3-256
|
||||
Z7_CLASS_IMP_COM_1(CSHA3_256Hasher, IHasher)
|
||||
SHA3_CTX _ctx;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
CSHA3_256Hasher() { SHA3_Init(&_ctx, 256); }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CSHA3_256Hasher::Init() throw()
|
||||
{
|
||||
SHA3_Init(&_ctx, 256);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CSHA3_256Hasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
SHA3_Update(&_ctx, (const Byte *)data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CSHA3_256Hasher::Final(Byte *digest) throw()
|
||||
{
|
||||
SHA3_Final(digest, &_ctx);
|
||||
}
|
||||
REGISTER_HASHER(CSHA3_256Hasher, 0x20a, "SHA3-256", SHA3_256_DIGEST_LENGTH)
|
||||
38
CPP/Common/Sha3-384Reg.cpp
Normal file
38
CPP/Common/Sha3-384Reg.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Sha3-384Reg.cpp /TR 2023-06-18
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
#include "../../C/hashes/sha3.h"
|
||||
EXTERN_C_END
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
// SHA3-384
|
||||
Z7_CLASS_IMP_COM_1(CSHA3_384Hasher, IHasher)
|
||||
SHA3_CTX _ctx;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
CSHA3_384Hasher() { SHA3_Init(&_ctx, 384); }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CSHA3_384Hasher::Init() throw()
|
||||
{
|
||||
SHA3_Init(&_ctx, 384);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CSHA3_384Hasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
SHA3_Update(&_ctx, (const Byte *)data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CSHA3_384Hasher::Final(Byte *digest) throw()
|
||||
{
|
||||
SHA3_Final(digest, &_ctx);
|
||||
}
|
||||
REGISTER_HASHER(CSHA3_384Hasher, 0x20b, "SHA3-384", SHA3_384_DIGEST_LENGTH)
|
||||
38
CPP/Common/Sha3-512Reg.cpp
Normal file
38
CPP/Common/Sha3-512Reg.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Sha3-512Reg.cpp /TR 2023-06-18
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
#include "../../C/hashes/sha3.h"
|
||||
EXTERN_C_END
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
// SHA3-512
|
||||
Z7_CLASS_IMP_COM_1(CSHA3_512Hasher, IHasher)
|
||||
SHA3_CTX _ctx;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
CSHA3_512Hasher() { SHA3_Init(&_ctx, 512); }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CSHA3_512Hasher::Init() throw()
|
||||
{
|
||||
SHA3_Init(&_ctx, 512);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CSHA3_512Hasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
SHA3_Update(&_ctx, (const Byte *)data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CSHA3_512Hasher::Final(Byte *digest) throw()
|
||||
{
|
||||
SHA3_Final(digest, &_ctx);
|
||||
}
|
||||
REGISTER_HASHER(CSHA3_512Hasher, 0x20c, "SHA3-512", SHA3_512_DIGEST_LENGTH)
|
||||
38
CPP/Common/Sha384Reg.cpp
Normal file
38
CPP/Common/Sha384Reg.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Sha384Reg.cpp /TR 2018-11-02
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
#include "../../C/hashes/sha512.h"
|
||||
EXTERN_C_END
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
// SHA384
|
||||
Z7_CLASS_IMP_COM_1(CSHA384Hasher, IHasher)
|
||||
SHA384_CTX _ctx;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
CSHA384Hasher() { SHA384_Init(&_ctx); }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CSHA384Hasher::Init() throw()
|
||||
{
|
||||
SHA384_Init(&_ctx);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CSHA384Hasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
SHA384_Update(&_ctx, (const Byte *)data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CSHA384Hasher::Final(Byte *digest) throw()
|
||||
{
|
||||
SHA384_Final(digest, &_ctx);
|
||||
}
|
||||
REGISTER_HASHER(CSHA384Hasher, 0x208, "SHA384", SHA384_DIGEST_LENGTH)
|
||||
38
CPP/Common/Sha512Reg.cpp
Normal file
38
CPP/Common/Sha512Reg.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Sha512Reg.cpp /TR 2018-11-02
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
#include "../../C/hashes/sha512.h"
|
||||
EXTERN_C_END
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
// SHA512
|
||||
Z7_CLASS_IMP_COM_1(CSHA512Hasher, IHasher)
|
||||
SHA512_CTX _ctx;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
CSHA512Hasher() { SHA512_Init(&_ctx); }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CSHA512Hasher::Init() throw()
|
||||
{
|
||||
SHA512_Init(&_ctx);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CSHA512Hasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
SHA512_Update(&_ctx, (const Byte *)data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CSHA512Hasher::Final(Byte *digest) throw()
|
||||
{
|
||||
SHA512_Final(digest, &_ctx);
|
||||
}
|
||||
REGISTER_HASHER(CSHA512Hasher, 0x209, "SHA512", SHA512_DIGEST_LENGTH)
|
||||
47
CPP/Common/XXH32Reg.cpp
Normal file
47
CPP/Common/XXH32Reg.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
// XXH32Reg.cpp /TR 2018-11-02
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
#define XXH_STATIC_LINKING_ONLY
|
||||
// shunf4: no zstd, comment for now
|
||||
// #include "../../C/zstd/xxhash.h"
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
// XXH32
|
||||
Z7_CLASS_IMP_COM_1(CXXH32Hasher, IHasher)
|
||||
// XXH32_state_t *_ctx;
|
||||
void *_ctx;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
// CXXH32Hasher() { _ctx = XXH32_createState(); }
|
||||
CXXH32Hasher() { _ctx = NULL; }
|
||||
// ~CXXH32Hasher() { XXH32_freeState(_ctx); }
|
||||
~CXXH32Hasher() { }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CXXH32Hasher::Init() throw()
|
||||
{
|
||||
// XXH32_reset(_ctx, 0);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CXXH32Hasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
(void)(data);
|
||||
(void)(size);
|
||||
// XXH32_update(_ctx, data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CXXH32Hasher::Final(Byte *digest) throw()
|
||||
{
|
||||
(void)(digest);
|
||||
// UInt32 val = XXH32_digest(_ctx);
|
||||
// SetUi32(digest, val);
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CXXH32Hasher, 0x20d, "XXH32 (NOT WORKING)", 4)
|
||||
45
CPP/Common/XXH64Reg.cpp
Normal file
45
CPP/Common/XXH64Reg.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// XXH64Reg.cpp /TR 2018-11-02
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
#define XXH_STATIC_LINKING_ONLY
|
||||
// #include "../../C/zstd/xxhash.h"
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
// XXH64
|
||||
Z7_CLASS_IMP_COM_1(CXXH64Hasher, IHasher)
|
||||
// XXH64_state_t *_ctx;
|
||||
void *_ctx;
|
||||
Byte mtDummy[1 << 7];
|
||||
|
||||
public:
|
||||
// CXXH64Hasher() { _ctx = XXH64_createState(); }
|
||||
// ~CXXH64Hasher() { XXH64_freeState(_ctx); }
|
||||
CXXH64Hasher() { _ctx = NULL; }
|
||||
~CXXH64Hasher() { }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP_(void) CXXH64Hasher::Init() throw()
|
||||
{
|
||||
// XXH64_reset(_ctx, 0);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CXXH64Hasher::Update(const void *data, UInt32 size) throw()
|
||||
{
|
||||
(void)(data);
|
||||
(void)(size);
|
||||
// XXH64_update(_ctx, data, size);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) CXXH64Hasher::Final(Byte *digest) throw()
|
||||
{
|
||||
(void)(digest);
|
||||
// UInt64 val = XXH64_digest(_ctx);
|
||||
// SetUi64(digest, val);
|
||||
}
|
||||
REGISTER_HASHER(CXXH64Hasher, 0x20e, "XXH64 (NOT WORKING)", 8)
|
||||
29
DOC/Hashes.txt
Normal file
29
DOC/Hashes.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
7-Zip Standard
|
||||
REGISTER_HASHER(CCrcHasher, 0x1, "CRC32", 4)
|
||||
REGISTER_HASHER(CXzCrc64Hasher, 0x4, "CRC64", 8)
|
||||
REGISTER_HASHER(CSha256Hasher, 0xA, "SHA256", SHA256_DIGEST_SIZE)
|
||||
REGISTER_HASHER(CSha1Hasher, 0x201, "SHA1", SHA1_DIGEST_SIZE)
|
||||
REGISTER_HASHER(CBlake2spHasher, 0x202, "BLAKE2sp", BLAKE2S_DIGEST_SIZE)
|
||||
REGISTER_HASHER(CCksumHasher, 0x203, "CKSUM", 4)
|
||||
|
||||
|
||||
7-Zip ZS
|
||||
REGISTER_HASHER(CCrcHasher, 0x1, "CRC32", 4)
|
||||
REGISTER_HASHER(CXzCrc64Hasher, 0x4, "CRC64", 8)
|
||||
REGISTER_HASHER(CSha256Hasher, 0xA, "SHA256", SHA256_DIGEST_SIZE)
|
||||
REGISTER_HASHER(CSha1Hasher, 0x201, "SHA1", SHA1_DIGEST_SIZE)
|
||||
REGISTER_HASHER(CBlake2spHasher, 0x202, "BLAKE2sp", BLAKE2S_DIGEST_SIZE)
|
||||
REGISTER_HASHER(CCksumHasher, 0x203, "CKSUM", 4)
|
||||
|
||||
REGISTER_HASHER(CBLAKE3Hasher, 0x204, "BLAKE3", BLAKE3_OUT_LEN)
|
||||
REGISTER_HASHER(CMD2Hasher, 0x205, "MD2", MD2_DIGEST_LENGTH)
|
||||
REGISTER_HASHER(CMD4Hasher, 0x206, "MD4", MD4_DIGEST_LENGTH)
|
||||
REGISTER_HASHER(CMD5Hasher, 0x207, "MD5", MD5_DIGEST_LENGTH)
|
||||
REGISTER_HASHER(CSHA384Hasher, 0x208, "SHA384", SHA384_DIGEST_LENGTH)
|
||||
REGISTER_HASHER(CSHA512Hasher, 0x209, "SHA512", SHA512_DIGEST_LENGTH)
|
||||
REGISTER_HASHER(CSHA3_256Hasher, 0x20a, "SHA3-256", SHA3_256_DIGEST_LENGTH)
|
||||
REGISTER_HASHER(CSHA3_384Hasher, 0x20b, "SHA3-384", SHA3_384_DIGEST_LENGTH)
|
||||
REGISTER_HASHER(CSHA3_512Hasher, 0x20c, "SHA3-512", SHA3_512_DIGEST_LENGTH)
|
||||
REGISTER_HASHER(CXXH32Hasher, 0x20d, "XXH32 (NOT WORKING)", 4)
|
||||
REGISTER_HASHER(CXXH64Hasher, 0x20e, "XXH64 (NOT WORKING)", 8)
|
||||
Reference in New Issue
Block a user