
From: levill_r <levill_r@4aad255d-cdde-0310-9447-f3009e2ae8c0> * libmd5/: New directory. * libmd5/driver.cc, * libmd5/md5.cc, * libmd5/md5.hh, * libmd5/README, * libmd5/test-suite: New. Imported from http://userpages.umbc.edu/~mabzug1/cs/md5/md5.html. * libmd5/Makefile.am: New. * Makefile.am (SUBDIRS): Add libmd5. * configure.ac: Configure libmd5/Makefile. git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@4656 4aad255d-cdde-0310-9447-f3009e2ae8c0 --- dynamic-use-of-static-c++/ChangeLog | 16 + dynamic-use-of-static-c++/Makefile.am | 2 +- dynamic-use-of-static-c++/configure.ac | 1 + dynamic-use-of-static-c++/libmd5/Makefile.am | 33 ++ dynamic-use-of-static-c++/libmd5/README | 102 +++++ dynamic-use-of-static-c++/libmd5/driver.cc | 200 ++++++++++ dynamic-use-of-static-c++/libmd5/md5.cc | 544 ++++++++++++++++++++++++++ dynamic-use-of-static-c++/libmd5/md5.hh | 109 +++++ dynamic-use-of-static-c++/libmd5/test-suite | 34 ++ 9 files changed, 1040 insertions(+), 1 deletions(-) create mode 100644 dynamic-use-of-static-c++/libmd5/Makefile.am create mode 100644 dynamic-use-of-static-c++/libmd5/README create mode 100644 dynamic-use-of-static-c++/libmd5/driver.cc create mode 100644 dynamic-use-of-static-c++/libmd5/md5.cc create mode 100644 dynamic-use-of-static-c++/libmd5/md5.hh create mode 100644 dynamic-use-of-static-c++/libmd5/test-suite diff --git a/dynamic-use-of-static-c++/ChangeLog b/dynamic-use-of-static-c++/ChangeLog index b768669..38756f3 100644 --- a/dynamic-use-of-static-c++/ChangeLog +++ b/dynamic-use-of-static-c++/ChangeLog @@ -1,5 +1,21 @@ 2009-10-20 Roland Levillain <roland@lrde.epita.fr> + Import a C++ implementation of the MD5 algorithm. + + * libmd5/: New directory. + * libmd5/driver.cc, + * libmd5/md5.cc, + * libmd5/md5.hh, + * libmd5/README, + * libmd5/test-suite: + New. + Imported from http://userpages.umbc.edu/~mabzug1/cs/md5/md5.html. + * libmd5/Makefile.am: New. + * Makefile.am (SUBDIRS): Add libmd5. + * configure.ac: Configure libmd5/Makefile. + +2009-10-20 Roland Levillain <roland@lrde.epita.fr> + Typos. * src/function_loader.cc, diff --git a/dynamic-use-of-static-c++/Makefile.am b/dynamic-use-of-static-c++/Makefile.am index 61eb925..55d40c3 100644 --- a/dynamic-use-of-static-c++/Makefile.am +++ b/dynamic-use-of-static-c++/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = libltdl bin src config data test +SUBDIRS = libltdl libmd5 bin src config data test ACLOCAL_AMFLAGS = -I config -I libltdl diff --git a/dynamic-use-of-static-c++/configure.ac b/dynamic-use-of-static-c++/configure.ac index 1ecd36c..facd01c 100644 --- a/dynamic-use-of-static-c++/configure.ac +++ b/dynamic-use-of-static-c++/configure.ac @@ -142,6 +142,7 @@ AC_CONFIG_FILES([ Makefile bin/Makefile bin/dyn-config + libmd5/Makefile src/Makefile src/config.hh data/Makefile diff --git a/dynamic-use-of-static-c++/libmd5/Makefile.am b/dynamic-use-of-static-c++/libmd5/Makefile.am new file mode 100644 index 0000000..300b0ba --- /dev/null +++ b/dynamic-use-of-static-c++/libmd5/Makefile.am @@ -0,0 +1,33 @@ +# A C++ implementation of the MD5 algorithm adapted from RSA Data +# Security's implementation. +# +# http://userpages.umbc.edu/~mabzug1/cs/md5/md5.html +# http://userpages.umbc.edu/~mabzug1/cs/md5/md5-cc-102.tar.gz + +# FIXME: Check that types are wide enough. From README: +# +# MD5 assumes that an unsigned char is at least a byte long, that an +# unsigned short int is at least two bytes long, and that an unsigned +# int is at least four bytes long. If your system is different, you +# should modify md5.hh accordingly. +# +# We should have `configure' check this. + +# FIXME: I (Roland) think that there is no legal problem to include +# this code in Olena. Still, we should check this thoroughly. +# +# We might want to depend on Crypto++ (http://www.cryptopp.com/) +# instead, which is both available from Debian GNU/Linux +# (http://packages.debian.org/lenny/libcrypto++-dev) and the MacPorts +# (http://trac.macports.org/browser/trunk/dports/devel/libcryptopp/Portfile). +# Crypto++ should also work on Cygwin (http://www.cryptopp.com/ +# mentions patches to have Crypto++ compile on Cygwin). + +noinst_LTLIBRARIES = libmd5.la +libmd5_la_SOURCES = md5.hh md5.cc + +check_PROGRAMS = md5 +md5_SOURCES = driver.cc +md5_LDADD = libmd5.la + +EXTRA_DIST = README test-suite diff --git a/dynamic-use-of-static-c++/libmd5/README b/dynamic-use-of-static-c++/libmd5/README new file mode 100644 index 0000000..9d92af3 --- /dev/null +++ b/dynamic-use-of-static-c++/libmd5/README @@ -0,0 +1,102 @@ +C++/object oriented translation and modification of MD5. + +Version: 1.00 (28 Aug 95) +Version: 1.02 (22 Sep 97) + + Translation and modification (c) 1995 by Mordechai T. Abzug + Thanks to Martin Cleaver for for making it happy on Windows NT and Solaris. + + This translation/ modification is provided "as is," without express or + implied warranty of any kind. + + The translator/ modifier does not claim (1) that MD5 will do what you think + it does; (2) that this translation/ modification is accurate; or (3) that + this software is "merchantible." (Language for this disclaimer partially + copied from the disclaimer below). + +Based on: + + MD5.H - header file for MD5C.C + MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + MDDRIVER.C - test driver for MD2, MD4 and MD5 + + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + +------------------------------------------------------------------------------- + +A note on compilation: + + MD5 assumes that an unsigned char is at least a byte long, that an + unsigned short int is at least two bytes long, and that an unsigned + int is at least four bytes long. If your system is different, you + should modify md5.hh accordingly. + + +HOW TO USE: + +(1) standalone: + + Driver.cc provides a nice interface for simple uses of md5. The + included makefile will do fine. However, if this is the limit of your + md5 use, you may as well use the original C source, which is somewhat + smaller. + +(2) as an object-oriented module: + + The MD5 objects in this module are MD5 contexts that are initialized, + then updated zero or more times, then finalized, and then have their + digest accessed zero or more times. Note that they *must* be + "finalized" between initialization and the availability of the digest; + this is part of the definition of MD5. + + The updating is done with a message, either with a stdio file opened + for reading (it is the user's responsibility to make sure that the file + is open), with an ifstream (again, the user's responsibility), with an + istream, or with an unsigned char string (typecast if you're using + normal char strings). If you initialized with the default contructor + (see later), you can update a single MD5 object multiple times, even + with different types of objects (say, a file and then a string). Note + that a stdio file is closed after an update, and the streams must no + longer be "good". Example: "context.update(file);". + + Initialization of the object depends on the type of updating you + intend to do (which is why it's here). If you want a general-purpose + MD5 object capable of being updated multiple times, with any object + type, use the default constructor (ie. "MD5 context;"). If you only + want to use the MD5 object for one update, you can initialize with + that object; this does an implicit finalization Example: "MD5 context + (cin);". + + Finalization must be done explicitly on object initialized with the + default constructor (see above); finalization is implicit with all + other contrsuctors. Once finalization has occurred, update is an + error. Example: "context.finalize();" + + After finalizing, you can look at the digest. MD5::raw_digest() + returns an 16-member array of unsigned chars (bytes). + MD5::hex_digest() returns a 33-byte long character string that is a + hex representation of the raw digest. There is also a << operator for + ostreams. Example: "unsigned char *digest=context.hex_digest();". + Example: 'cout << "Digest is: " << context << endl;'. + + See driver.cc for more examples. + diff --git a/dynamic-use-of-static-c++/libmd5/driver.cc b/dynamic-use-of-static-c++/libmd5/driver.cc new file mode 100644 index 0000000..3624a7d --- /dev/null +++ b/dynamic-use-of-static-c++/libmd5/driver.cc @@ -0,0 +1,200 @@ +// DRIVER.CC - test driver for the C++/object oriented translation and +// modification of MD5. + +// Translation and modification (c) 1995 by Mordechai T. Abzug + +// This translation/ modification is provided "as is," without express or +// implied warranty of any kind. + +// The translator/ modifier does not claim (1) that MD5 will do what you think +// it does; (2) that this translation/ modification is accurate; or (3) that +// this software is "merchantible." (Language for this disclaimer partially +// copied from the disclaimer below). + +/* based on: + + MDDRIVER.C - test driver for MD2, MD4 and MD5 + + Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All +rights reserved. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <string.h> + +#include "md5.hh" + + +// Length of test block, number of test blocks. + +#define TEST_BLOCK_LEN 1000 +#define TEST_BLOCK_COUNT 1000 + +static void MD5_timeTrial (void); +static void MD5_testSuite (void); +static void MD5_file (char *); +static void MD5_filter (void); +static void MD5_string (unsigned char *string); +static char *MD5_usage (void); + +// Main driver. + +int main (int argc, char *argv[]){ + + int i; + + if (argc > 1) + for (i = 1; i < argc; i++) + if (argv[i][0] == '-' && argv[i][1] == 's') + MD5_string ( (unsigned char *) argv[i] + 2); + else if (strcmp (argv[i], "-t") == 0) + MD5_timeTrial (); + else if (strcmp (argv[i], "-x") == 0) + MD5_testSuite (); + else if (strcmp (argv[i], "-h") == 0) + cout << MD5_usage()<< flush; + else if (strcmp (argv[i], "-help")==0) + cout << MD5_usage()<< flush; + else if (argv[i][0] == '-'){ + cerr << argv[i] << " is an unknown option.\n" << MD5_usage()<< flush; + exit (1); + } + else + MD5_file (argv[i]); + else + MD5_filter (); + + return (0); +} + + +// Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks. + +static void MD5_timeTrial () +{ + MD5 context; + time_t endTime, startTime; + unsigned char block[TEST_BLOCK_LEN]; + unsigned int i; + + + cout << "MD5 time trial. Digesting "<< TEST_BLOCK_LEN << " "; + cout << TEST_BLOCK_COUNT << "-byte blocks ..."; + + // Initialize block + for (i = 0; i < TEST_BLOCK_LEN; i++) + block[i] = (unsigned char)(i & 0xff); + + // Start timer + time (&startTime); + + // Digest blocks + for (i = 0; i < TEST_BLOCK_COUNT; i++) + context.update (block, TEST_BLOCK_LEN); + + context.finalize(); + + // Stop timer + time (&endTime); + + cout << " done" << endl; + + cout << "Digest = " << context << endl; + + cout << "Time = "<< (long)(endTime-startTime) << " seconds" << endl; + + cout << "Speed = "; + cout << (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime); + cout << "bytes/second" <<endl; + +} + +// Digests a reference suite of strings and prints the results. + +static void MD5_testSuite () +{ + cout << "MD5 test suite:" << endl; + + MD5_string ( (unsigned char*) ""); + MD5_string ( (unsigned char*) "a"); + MD5_string ( (unsigned char*) "abc"); + MD5_string ( (unsigned char*) "message digest"); + MD5_string ( (unsigned char*) "abcdefghijklmnopqrstuvwxyz"); + MD5_string + ( (unsigned char*) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); + MD5_string + ( (unsigned char*) "1234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890"); +} + + +// Digests a file and prints the result. + +static void MD5_file (char *filename){ + + ifstream file(filename); + + if (!file) + cerr << filename <<" can't be opened" << endl; + else { + MD5 context(file); + cout << "MD5 (" << filename << ") = " << context << endl; + } +} + +// Digests the standard input and prints the result. + +static void MD5_filter () +{ + + MD5 context(cin); // ie. run istream version of MD5 on cin. + // Could also run file version of MD5 on stdin. + + cout << context << endl; +} + + + +// Digests a string and prints the result. + +void MD5_string (unsigned char *string){ + + MD5 context; + unsigned int len = strlen ( (char *)string); + + context.update (string, len); + context.finalize (); + + cout << "MD5 (\"" << (char *)string << "\") = " << context <<endl; +} + + + +static char *MD5_usage(){ + + return "\n\ + MD5\n\n\ +USAGE:\n\n\ + MD5 [-sstring] [-t] [-x] [-h] [-help] [filename]\n\n\ +Arguments (may be any combination):\n\ + -sstring - digests string\n\ + -t - runs time trial\n\ + -x - runs test script\n\ + -h - displays this message\n\ + -help - displays this message\n\ + filename - digests file\n\ + (none) - digests standard input\n\n"; +} + + + diff --git a/dynamic-use-of-static-c++/libmd5/md5.cc b/dynamic-use-of-static-c++/libmd5/md5.cc new file mode 100644 index 0000000..8a547bd --- /dev/null +++ b/dynamic-use-of-static-c++/libmd5/md5.cc @@ -0,0 +1,544 @@ +// MD5.CC - source code for the C++/object oriented translation and +// modification of MD5. + +// Translation and modification (c) 1995 by Mordechai T. Abzug + +// This translation/ modification is provided "as is," without express or +// implied warranty of any kind. + +// The translator/ modifier does not claim (1) that MD5 will do what you think +// it does; (2) that this translation/ modification is accurate; or (3) that +// this software is "merchantible." (Language for this disclaimer partially +// copied from the disclaimer below). + +/* based on: + + MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + MDDRIVER.C - test driver for MD2, MD4 and MD5 + + + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + + */ + + + + + + +#include "md5.hh" + +#include <assert.h> +#include <strings.h> +#include <iostream.h> + + + + +// MD5 simple initialization method + +MD5::MD5(){ + + init(); + +} + + + + +// MD5 block update operation. Continues an MD5 message-digest +// operation, processing another message block, and updating the +// context. + +void MD5::update (uint1 *input, uint4 input_length) { + + uint4 input_index, buffer_index; + uint4 buffer_space; // how much space is left in buffer + + if (finalized){ // so we can't update! + cerr << "MD5::update: Can't update a finalized digest!" << endl; + return; + } + + // Compute number of bytes mod 64 + buffer_index = (unsigned int)((count[0] >> 3) & 0x3F); + + // Update number of bits + if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) ) + count[1]++; + + count[1] += ((uint4)input_length >> 29); + + + buffer_space = 64 - buffer_index; // how much space is left in buffer + + // Transform as many times as possible. + if (input_length >= buffer_space) { // ie. we have enough to fill the buffer + // fill the rest of the buffer and transform + memcpy (buffer + buffer_index, input, buffer_space); + transform (buffer); + + // now, transform each 64-byte piece of the input, bypassing the buffer + for (input_index = buffer_space; input_index + 63 < input_length; + input_index += 64) + transform (input+input_index); + + buffer_index = 0; // so we can buffer remaining + } + else + input_index=0; // so we can buffer the whole input + + + // and here we do the buffering: + memcpy(buffer+buffer_index, input+input_index, input_length-input_index); +} + + + +// MD5 update for files. +// Like above, except that it works on files (and uses above as a primitive.) + +void MD5::update(FILE *file){ + + unsigned char buffer[1024]; + int len; + + while (len=fread(buffer, 1, 1024, file)) + update(buffer, len); + + fclose (file); + +} + + + + + + +// MD5 update for istreams. +// Like update for files; see above. + +void MD5::update(istream& stream){ + + unsigned char buffer[1024]; + int len; + + while (stream.good()){ + stream.read(buffer, 1024); // note that return value of read is unusable. + len=stream.gcount(); + update(buffer, len); + } + +} + + + + + + +// MD5 update for ifstreams. +// Like update for files; see above. + +void MD5::update(ifstream& stream){ + + unsigned char buffer[1024]; + int len; + + while (stream.good()){ + stream.read(buffer, 1024); // note that return value of read is unusable. + len=stream.gcount(); + update(buffer, len); + } + +} + + + + + + +// MD5 finalization. Ends an MD5 message-digest operation, writing the +// the message digest and zeroizing the context. + + +void MD5::finalize (){ + + unsigned char bits[8]; + unsigned int index, padLen; + static uint1 PADDING[64]={ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (finalized){ + cerr << "MD5::finalize: Already finalized this digest!" << endl; + return; + } + + // Save number of bits + encode (bits, count, 8); + + // Pad out to 56 mod 64. + index = (uint4) ((count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + update (PADDING, padLen); + + // Append length (before padding) + update (bits, 8); + + // Store state in digest + encode (digest, state, 16); + + // Zeroize sensitive information + memset (buffer, 0, sizeof(*buffer)); + + finalized=1; + +} + + + + +MD5::MD5(FILE *file){ + + init(); // must be called be all constructors + update(file); + finalize (); +} + + + + +MD5::MD5(istream& stream){ + + init(); // must called by all constructors + update (stream); + finalize(); +} + + + +MD5::MD5(ifstream& stream){ + + init(); // must called by all constructors + update (stream); + finalize(); +} + + + +unsigned char *MD5::raw_digest(){ + + uint1 *s = new uint1[16]; + + if (!finalized){ + cerr << "MD5::raw_digest: Can't get digest if you haven't "<< + "finalized the digest!" <<endl; + return ( (unsigned char*) ""); + } + + memcpy(s, digest, 16); + return s; +} + + + +char *MD5::hex_digest(){ + + int i; + char *s= new char[33]; + + if (!finalized){ + cerr << "MD5::hex_digest: Can't get digest if you haven't "<< + "finalized the digest!" <<endl; + return ""; + } + + for (i=0; i<16; i++) + sprintf(s+i*2, "%02x", digest[i]); + + s[32]='\0'; + + return s; +} + + + + + +ostream& operator<<(ostream &stream, MD5 context){ + + stream << context.hex_digest(); + return stream; +} + + + + +// PRIVATE METHODS: + + + +void MD5::init(){ + finalized=0; // we just started! + + // Nothing counted, so count=0 + count[0] = 0; + count[1] = 0; + + // Load magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; +} + + + +// Constants for MD5Transform routine. +// Although we could use C++ style constants, defines are actually better, +// since they let us easily evade scope clashes. + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + + + + +// MD5 basic transformation. Transforms state based on block. +void MD5::transform (uint1 block[64]){ + + uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + decode (x, block, 64); + + assert(!finalized); // not just a user error, since the method is private + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset ( (uint1 *) x, 0, sizeof(x)); + +} + + + +// Encodes input (UINT4) into output (unsigned char). Assumes len is +// a multiple of 4. +void MD5::encode (uint1 *output, uint4 *input, uint4 len) { + + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (uint1) (input[i] & 0xff); + output[j+1] = (uint1) ((input[i] >> 8) & 0xff); + output[j+2] = (uint1) ((input[i] >> 16) & 0xff); + output[j+3] = (uint1) ((input[i] >> 24) & 0xff); + } +} + + + + +// Decodes input (unsigned char) into output (UINT4). Assumes len is +// a multiple of 4. +void MD5::decode (uint4 *output, uint1 *input, uint4 len){ + + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | + (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); +} + + + + + +// Note: Replace "for loop" with standard memcpy if possible. +void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){ + + unsigned int i; + + for (i = 0; i < len; i++) + output[i] = input[i]; +} + + + +// Note: Replace "for loop" with standard memset if possible. +void MD5::memset (uint1 *output, uint1 value, uint4 len){ + + unsigned int i; + + for (i = 0; i < len; i++) + output[i] = value; +} + + + +// ROTATE_LEFT rotates x left n bits. + +inline unsigned int MD5::rotate_left (uint4 x, uint4 n){ + return (x << n) | (x >> (32-n)) ; +} + + + + +// F, G, H and I are basic MD5 functions. + +inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){ + return (x & y) | (~x & z); +} + +inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){ + return (x & z) | (y & ~z); +} + +inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){ + return x ^ y ^ z; +} + +inline unsigned int MD5::I (uint4 x, uint4 y, uint4 z){ + return y ^ (x | ~z); +} + + + +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +// Rotation is separate from addition to prevent recomputation. + + +inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac){ + a += F(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac){ + a += G(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac){ + a += H(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac){ + a += I(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} diff --git a/dynamic-use-of-static-c++/libmd5/md5.hh b/dynamic-use-of-static-c++/libmd5/md5.hh new file mode 100644 index 0000000..b8bc075 --- /dev/null +++ b/dynamic-use-of-static-c++/libmd5/md5.hh @@ -0,0 +1,109 @@ +// MD5.CC - source code for the C++/object oriented translation and +// modification of MD5. + +// Translation and modification (c) 1995 by Mordechai T. Abzug + +// This translation/ modification is provided "as is," without express or +// implied warranty of any kind. + +// The translator/ modifier does not claim (1) that MD5 will do what you think +// it does; (2) that this translation/ modification is accurate; or (3) that +// this software is "merchantible." (Language for this disclaimer partially +// copied from the disclaimer below). + +/* based on: + + MD5.H - header file for MD5C.C + MDDRIVER.C - test driver for MD2, MD4 and MD5 + + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + +*/ + +#include <stdio.h> +#include <fstream.h> +#include <iostream.h> + +class MD5 { + +public: +// methods for controlled operation: + MD5 (); // simple initializer + void update (unsigned char *input, unsigned int input_length); + void update (istream& stream); + void update (FILE *file); + void update (ifstream& stream); + void finalize (); + +// constructors for special circumstances. All these constructors finalize +// the MD5 context. + MD5 (unsigned char *string); // digest string, finalize + MD5 (istream& stream); // digest stream, finalize + MD5 (FILE *file); // digest file, close, finalize + MD5 (ifstream& stream); // digest stream, close, finalize + +// methods to acquire finalized result + unsigned char *raw_digest (); // digest as a 16-byte binary array + char * hex_digest (); // digest as a 33-byte ascii-hex string + friend ostream& operator<< (ostream&, MD5 context); + + + +private: + +// first, some types: + typedef unsigned int uint4; // assumes integer is 4 words long + typedef unsigned short int uint2; // assumes short integer is 2 words long + typedef unsigned char uint1; // assumes char is 1 word long + +// next, the private data: + uint4 state[4]; + uint4 count[2]; // number of *bits*, mod 2^64 + uint1 buffer[64]; // input buffer + uint1 digest[16]; + uint1 finalized; + +// last, the private methods, mostly static: + void init (); // called by all constructors + void transform (uint1 *buffer); // does the real update work. Note + // that length is implied to be 64. + + static void encode (uint1 *dest, uint4 *src, uint4 length); + static void decode (uint4 *dest, uint1 *src, uint4 length); + static void memcpy (uint1 *dest, uint1 *src, uint4 length); + static void memset (uint1 *start, uint1 val, uint4 length); + + static inline uint4 rotate_left (uint4 x, uint4 n); + static inline uint4 F (uint4 x, uint4 y, uint4 z); + static inline uint4 G (uint4 x, uint4 y, uint4 z); + static inline uint4 H (uint4 x, uint4 y, uint4 z); + static inline uint4 I (uint4 x, uint4 y, uint4 z); + static inline void FF (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac); + static inline void GG (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac); + static inline void HH (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac); + static inline void II (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac); + +}; diff --git a/dynamic-use-of-static-c++/libmd5/test-suite b/dynamic-use-of-static-c++/libmd5/test-suite new file mode 100644 index 0000000..ea034e4 --- /dev/null +++ b/dynamic-use-of-static-c++/libmd5/test-suite @@ -0,0 +1,34 @@ + + The MD5 test suite (driver option "-x") should print the following + results: + +MD5 test suite: +MD5 ("") = d41d8cd98f00b204e9800998ecf8427e +MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661 +MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 +MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0 +MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b +MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = +d174ab98d277d9f5a5611c2c9f419d9f +MD5 ("123456789012345678901234567890123456789012345678901234567890123456 +78901234567890") = 57edf4a22be3c955ac49da2e2107b67a + +Security Considerations + + The level of security discussed in this memo is considered to be + sufficient for implementing very high security hybrid digital- + signature schemes based on MD5 and a public-key cryptosystem. + +Author's Address + + Ronald L. Rivest + Massachusetts Institute of Technology + Laboratory for Computer Science + NE43-324 + 545 Technology Square + Cambridge, MA 02139-1986 + + Phone: (617) 253-5880 + EMail: rivest@theory.lcs.mit.edu + + -- 1.6.5