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(a)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(a)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(a)theory.lcs.mit.edu
+
+
--
1.6.5