/* Windows MD5 sample code * Richard A. DeVenezia * http://www.devenezia.com * May 19, 2004 */ * Sometimes you need to mask data, MD5 is sufficient in most cases; * One common use is storing passwords (hashed) where anyone can read them, * access is granted only when an input password is hashed and is found to * match an entry in the password table.; * * Another common use is too blind parts of data distributed to analysts. * Typically, name, social security numbers and other identifiers that would * de-anonymize an individual that permitted their information to be studied * in aggregates; filename sascbtbl catalog 'WORK.API.MD5.SOURCE'; data _null_; file sascbtbl; input; put _infile_; cards4; routine MD5Init module=cryptdll minarg=1 maxarg=1 stackpop=called ; arg 1 input num format=pib4. byvalue ; * MD5_CTX * (use addr()); routine MD5Update module=cryptdll minarg=3 maxarg=3 stackpop=called ; arg 1 input num format=pib4. byvalue ; * MD5_CTX * context (use addr()); arg 2 input char format=$cstr200. ; * const unsigned char * bufferBeingHashed; arg 3 input num format=pib4. byvalue ; * unsigned int numberOfCharsInBuffer; routine MD5Final module=cryptdll minarg=1 maxarg=1 stackpop=called ; arg 1 input num format=pib4. byvalue ; * MD5_CTX * (use addr()); ;;;; run; /* context must be large enough to contain this structure typedef struct { ULONG i[2]; ULONG buf[4]; unsigned char in[64]; unsigned char digest[16]; } MD5_CTX; */ data work.class; length name_hashed $32; length md5_context $110; set sashelp.class; md5_context = ' '; call module ('MD5Init', addr(md5_context)); call module ('MD5Update', addr(md5_context), name, length(name)); call module ('MD5Final', addr(md5_context)); name_hashed = put (substr (md5_context,89, 16), $hex32.); label name_hashed = 'Name (hashed per MD5)'; drop md5: name; run; filename sascbtbl; ods listing; proc print data=work.class; run;