62 lines
1.5 KiB
C
62 lines
1.5 KiB
C
#include <assert.h>
|
|
|
|
#include "ed2k.h"
|
|
|
|
/* https://wiki.anidb.net/Ed2k-hash */
|
|
/* This is using the red method */
|
|
|
|
#define ED2K_CHUNK_SIZE 9728000
|
|
|
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
|
|
|
void ed2k_init(struct ed2k_ctx *ctx)
|
|
{
|
|
md4_init(&ctx->chunk_md4_ctx);
|
|
md4_init(&ctx->hash_md4_ctx);
|
|
ctx->byte_count = 0;
|
|
}
|
|
|
|
static void ed2k_hash_chunk(struct ed2k_ctx *ctx)
|
|
{
|
|
unsigned char chunk_hash[MD4_DIGEST_SIZE];
|
|
|
|
md4_final(&ctx->chunk_md4_ctx, chunk_hash);
|
|
md4_update(&ctx->hash_md4_ctx, chunk_hash, sizeof(chunk_hash));
|
|
md4_init(&ctx->chunk_md4_ctx);
|
|
}
|
|
|
|
void ed2k_update(struct ed2k_ctx *ctx, const void *data, size_t data_len)
|
|
{
|
|
const char *bytes = (const char*)data;
|
|
|
|
while (data_len) {
|
|
size_t hdata_size = MIN(ED2K_CHUNK_SIZE -
|
|
(ctx->byte_count % ED2K_CHUNK_SIZE), data_len);
|
|
|
|
md4_update(&ctx->chunk_md4_ctx, bytes, hdata_size);
|
|
ctx->byte_count += hdata_size;
|
|
|
|
if (ctx->byte_count % ED2K_CHUNK_SIZE == 0)
|
|
ed2k_hash_chunk(ctx);
|
|
|
|
data_len -= hdata_size;
|
|
bytes += hdata_size;
|
|
}
|
|
}
|
|
|
|
void ed2k_final(struct ed2k_ctx *ctx, unsigned char *out_hash)
|
|
{
|
|
struct md4_ctx *md_ctx;
|
|
if (ctx->byte_count < ED2K_CHUNK_SIZE) {
|
|
/* File has only 1 chunk, so return the md4 hash of that chunk */
|
|
md_ctx = &ctx->chunk_md4_ctx;
|
|
} else {
|
|
/* Else hash the md4 hashes, and return that hash */
|
|
ed2k_hash_chunk(ctx); /* Hash the last partial chunk here */
|
|
md_ctx = &ctx->hash_md4_ctx;
|
|
}
|
|
|
|
md4_final(md_ctx, out_hash);
|
|
}
|
|
|