md5c.tcl

Go to the documentation of this file.
00001 /*  md5c.tcl - */
00002 /* */
00003 /*  Wrapper for RSA's Message Digest in C*/
00004 /* */
00005 /*  Written by Jean-Claude Wippler <jcw@equi4.com>*/
00006 /* */
00007 /*  $Id: md5c.tcl,v 1.3 2004/01/15 06:36:13 andreas_kupries Exp $*/
00008 
00009 package require critcl;                 /*  needs critcl*/
00010 package provide md5c 0.11;              /*  */
00011 
00012 critcl::cheaders md5.h;                 /*  The RSA header file*/
00013 critcl::csources md5.c;                 /*  The RSA MD5 implementation.*/
00014 
00015 namespace ::md5 {
00016 
00017     critcl::ccode {
00018         /* include "md5.h"*/
00019         /* include <malloc.h>*/
00020         /* include <memory.h>*/
00021         /* include <assert.h>*/
00022         
00023         static
00024         Tcl_ObjType md5_type; /* fast internal access representation */
00025         
00026         static void 
00027         md5_free_rep(Tcl_Obj* obj)
00028         {
00029             MD5_CTX* mp = (MD5_CTX*) obj->internalRep.otherValuePtr;
00030             free(mp);
00031         }
00032         
00033         static void
00034         md5_dup_rep(Tcl_Obj* obj, Tcl_Obj* dup)
00035         {
00036             MD5_CTX* mp = (MD5_CTX*) obj->internalRep.otherValuePtr;
00037             dup->internalRep.otherValuePtr = malloc(sizeof *mp);
00038             memcpy(dup->internalRep.otherValuePtr, mp, sizeof *mp);
00039             dup->typePtr = &md5_type;
00040         }
00041         
00042         static void
00043         md5_string_rep(Tcl_Obj* obj)
00044         {
00045             unsigned char buf[16];
00046             Tcl_Obj* temp;
00047             char* str;
00048             MD5_CTX dup = *(MD5_CTX*) obj->internalRep.otherValuePtr;
00049             
00050             MD5Final(buf, &dup);
00051             
00052             /* convert via a byte array to properly handle null bytes */
00053             temp = Tcl_NewByteArrayObj(buf, sizeof buf);
00054             Tcl_IncrRefCount(temp);
00055             
00056             str = Tcl_GetStringFromObj(temp, &obj->length);
00057             obj->bytes = Tcl_Alloc(obj->length + 1);
00058             memcpy(obj->bytes, str, obj->length + 1);
00059             
00060             Tcl_DecrRefCount(temp);
00061         }
00062         
00063         static int
00064         md5_from_any(Tcl_Interp* ip, Tcl_Obj* obj)
00065         {
00066             assert(0);
00067             return TCL_ERROR;
00068         }
00069         
00070         static
00071         Tcl_ObjType md5_type = {
00072             "md5c", md5_free_rep, md5_dup_rep, md5_string_rep, md5_from_any
00073         };
00074     }
00075     
00076     critcl::ccommand md5c {dummy ip objc objv} {
00077         MD5_CTX* mp;
00078         unsigned char* data;
00079         int size;
00080         Tcl_Obj* obj;
00081         
00082         //Tcl_RegisterObjType(&md5_type);
00083         
00084         if (objc < 2 || objc > 3) {
00085             Tcl_WrongNumArgs(ip, 1, objv, "data ?context?");
00086             return TCL_ERROR;
00087         }
00088         
00089         if (objc == 3) {
00090             if (objv[2]->typePtr != &md5_type && md5_from_any(ip, objv[2]) != TCL_OK)
00091             return TCL_ERROR;
00092             obj = objv[2];
00093             if (Tcl_IsShared(obj))
00094             obj = Tcl_DuplicateObj(obj);
00095         } else {
00096             obj = Tcl_NewObj();
00097             mp = (MD5_CTX*) malloc(sizeof *mp);
00098             MD5Init(mp);
00099             
00100             if (obj->typePtr != NULL && obj->typePtr->freeIntRepProc != NULL)
00101             obj->typePtr->freeIntRepProc(obj);
00102             
00103             obj->internalRep.otherValuePtr = mp;
00104             obj->typePtr = &md5_type;
00105         }
00106         
00107         Tcl_SetObjResult(ip, obj);
00108         Tcl_IncrRefCount(obj); //!! huh?
00109         
00110         Tcl_InvalidateStringRep(obj);
00111         mp = (MD5_CTX*) obj->internalRep.otherValuePtr;
00112         
00113         data = Tcl_GetByteArrayFromObj(objv[1], &size);
00114         MD5Update(mp, data, size);
00115         
00116         return TCL_OK;
00117     }
00118 }
00119 
00120 if {[info exists pkgtest] && $pkgtest} {
00121 
00122   ret  md5c_try () {
00123     foreach {msg expected} {
00124       ""
00125       "d41d8cd98f00b204e9800998ecf8427e"
00126       "a"
00127       "0cc175b9c0f1b6a831c399e269772661"
00128       "abc"
00129       "900150983cd24fb0d6963f7d28e17f72"
00130       "message digest"
00131       "f96b697d7cb7938d525a2f31aaf161d0"
00132       "abcdefghijklmnopqrstuvwxyz"
00133       "c3fcd3d76192e4007dfb496cca67e13b"
00134       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
00135       "d174ab98d277d9f5a5611c2c9f419d9f"
00136       "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
00137       "57edf4a22be3c955ac49da2e2107b67a"
00138     } {
00139       puts "testing: ::md5::md5c \"$msg\""
00140       binary scan [::md5::md5c $msg] H* computed
00141       puts "computed: $computed"
00142       if {0 != [string compare $computed $expected]} {
00143     puts "expected: $expected"
00144     puts "FAILED"
00145       }
00146     }
00147 
00148     foreach len {10 50 100 500 1000 5000 10000} {
00149       set blanks [format %$len.0s ""]
00150       puts "input length $len: [time {md5c $blanks} 1000]"
00151     }
00152   }
00153 
00154   md5c_try
00155 }
00156 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1