/*************************************************************************** * Copyright (C) 2007 by SukkoPera * * sukkopera@sukkology.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ /* As Wikipedia (http://en.wikipedia.org/wiki/Ed2k_link) says: * The ed2k hash function is a MD4 root hash of a MD4 hash list, and gives a * different result than simply MD4: The file data is divided into full * chunks of 9728000 bytes plus a remainder chunk, and a separate 128-bit * MD4 checksum is computed for each. The ed2k hash is computed by * concatenating the chunks' MD4 checksums in order and hashing the result *using MD4. */ #include #include "edonkey.h" #include "md4.h" void ed2khash_starts (ed2khash_context *ctx) { md4_starts (&(ctx -> md4cur)); md4_starts (&(ctx -> md4final)); ctx -> bytes_processed = 0; ctx -> chunks = 0; return; } void ed2khash_update (ed2khash_context *ctx, unsigned char *input, int ilen) { unsigned long x; while (ilen > 0) { if (ctx -> bytes_processed + ilen >= ED2KHASH_CHUNKSIZE) x = ED2KHASH_CHUNKSIZE - ctx -> bytes_processed; else x = ilen; md4_update (&(ctx -> md4cur), input, x); if ((ctx -> bytes_processed += x) % ED2KHASH_CHUNKSIZE == 0) { /* End of a chunk, save current MD4 and start a new one */ md4_finish (&(ctx -> md4cur), ctx -> lastmd4); md4_starts (&(ctx -> md4cur)); ctx -> bytes_processed = 0; ctx -> chunks++; md4_update (&(ctx -> md4final), ctx -> lastmd4, MD4_DIGESTSIZE); } ilen -= x; input += x; } return; } void ed2khash_finish (ed2khash_context *ctx, unsigned char *output) { if (ctx -> chunks > 0) { md4_finish (&(ctx -> md4cur), ctx -> lastmd4); md4_update (&(ctx -> md4final), ctx -> lastmd4, MD4_DIGESTSIZE); md4_finish (&(ctx -> md4final), output); } else { /* If we have a single chunk, use its MD4 straight away */ md4_finish (&(ctx -> md4cur), output); } return; }