ripemd128.tcl

Go to the documentation of this file.
00001 /*  ripemd128.tcl - Copyright (C) 2003 Pat Thoyts <patthoyts@users.sf.net>*/
00002 /* */
00003 /*  This is a Tcl-only implementation of the RIPEMD-128 hash algorithm as */
00004 /*  described in [RIPE].*/
00005 /*  Included is an implementation of keyed message authentication using */
00006 /*  the RIPEMD-128 function [HMAC].*/
00007 /* */
00008 /*  See http://www.esat.kuleuven.ac.be/~cosicart/pdf/AB-9601/*/
00009 /* */
00010 /*  [RIPE] Dobbertin, H., Bosselaers A., and Preneel, B.*/
00011 /*         "RIPEMD-160: A Strengthened Version of RIPEMD" */
00012 /*         Fast Software Encryption, LNCS 1039, D. Gollmann, Ed., */
00013 /*         Springer-Verlag, 1996, pp. 71-82*/
00014 /*  [HMAC] Krawczyk, H., Bellare, M., and R. Canetti, */
00015 /*        "HMAC: Keyed-Hashing for Message Authentication",*/
00016 /*         RFC 2104, February 1997.*/
00017 /* */
00018 /*  RFC 2286, ``Test cases for HMAC-RIPEMD160 and HMAC-RIPEMD128,''*/
00019 /*  Internet Request for Comments 2286, J. Kapp, */
00020 /* */
00021 /*  -------------------------------------------------------------------------*/
00022 /*  See the file "license.terms" for information on usage and redistribution*/
00023 /*  of this file, and for a DISCLAIMER OF ALL WARRANTIES.*/
00024 /*  -------------------------------------------------------------------------*/
00025 /* */
00026 /*  $Id: ripemd128.tcl,v 1.9 2005/10/17 19:39:52 andreas_kupries Exp $*/
00027 
00028 package require Tcl 8.2;                /*  tcl minimum version*/
00029 
00030 namespace ::ripemd {
00031     namespace ripemd128 {
00032         variable version 1.0.3
00033         variable rcsid {$Id: ripemd128.tcl,v 1.9 2005/10/17 19:39:52 andreas_kupries Exp $}
00034         variable accel
00035         array  accel =  {trf 0}
00036 
00037         variable uid
00038         if {![info exists uid]} {
00039              uid =  0
00040         }
00041 
00042         namespace export ripemd128 hmac128 Hex \
00043             RIPEMD128Init RIPEMD128Update RIPEMD128Final \
00044             RIPEHMAC128Init RIPEHMAC128Update RIPEHMAC128Final
00045     }
00046 }
00047 
00048 /*  -------------------------------------------------------------------------*/
00049 
00050 /*  RIPEMD128Init - create and initialize an MD4 state variable. This will be*/
00051 /*  cleaned up when we call MD4Final*/
00052 /* */
00053 ret  ::ripemd::ripemd128::RIPEMD128Init () {
00054     variable accel
00055     variable uid
00056     set token [namespace current]::[incr uid]
00057     upvar #0 $token state
00058 
00059     # Initialize RIPEMD-128 state structure (same as MD4).
00060     array set state \
00061         [list \
00062              A [expr {0x67452301}] \
00063              B [expr {0xefcdab89}] \
00064              C [expr {0x98badcfe}] \
00065              D [expr {0x10325476}] \
00066              n 0 i "" ]
00067     if {$accel(trf)} {
00068         set s {}
00069         switch -exact -- $::tcl_platform(platform) {
00070             windows { set s [open NUL w] }
00071             unix    { set s [open /dev/null w] }
00072         }
00073         if {$s != {}} {
00074             fconfigure $s -translation binary -buffering none
00075             ::ripemd128 -attach $s -mode write \
00076                 -read-type variable \
00077                 -read-destination [subst $token](trfread) \
00078                 -write-type variable \
00079                 -write-destination [subst $token](trfwrite)
00080             array set state [list trfread 0 trfwrite 0 trf $s]
00081         }
00082     }
00083     return $token
00084 }
00085 
00086 ret  ::ripemd::ripemd128::RIPEMD128Update (type token , type data) {
00087     upvar #0 $token state
00088 
00089     if {[info exists state(trf)]} {
00090         puts -nonewline $state(trf) $data
00091         return
00092     }
00093 
00094     # Update the state values
00095     incr state(n) [string length $data]
00096     append state(i) $data
00097 
00098     # Calculate the hash for any complete blocks
00099     set len [string length $state(i)]
00100     for {set n 0} {($n + 64) <= $len} {} {
00101         RIPEMD128Hash $token [string range $state(i) $n [incr n 64]]
00102     }
00103 
00104     # Adjust the state for the blocks completed.
00105     set state(i) [string range $state(i) $n end]
00106     return
00107 }
00108 
00109 ret  ::ripemd::ripemd128::RIPEMD128Final (type token) {
00110     upvar #0 $token state
00111 
00112     if {[info exists state(trf)]} {
00113         close $state(trf)
00114         set r $state(trfwrite)
00115         unset state
00116         return $r
00117     }
00118 
00119     # RFC1320:3.1 - Padding
00120     #
00121     set len [string length $state(i)]
00122     set pad [expr {56 - ($len % 64)}]
00123     if {$len % 64 > 56} {
00124         incr pad 64
00125     }
00126     if {$pad == 0} {
00127         incr pad 64
00128     }
00129     append state(i) [binary format a$pad \x80]
00130 
00131     # RFC1320:3.2 - Append length in bits as little-endian wide int.
00132     append state(i) [binary format ii [expr {8 * $state(n)}] 0]
00133 
00134     # Calculate the hash for the remaining block.
00135     set len [string length $state(i)]
00136     for {set n 0} {($n + 64) <= $len} {} {
00137         RIPEMD128Hash $token [string range $state(i) $n [incr n 64]]
00138     }
00139 
00140     # RFC1320:3.5 - Output
00141     set r [bytes $state(A)][bytes $state(B)][bytes $state(C)][bytes $state(D)]
00142     unset state
00143     return $r
00144 }
00145 
00146 /*  -------------------------------------------------------------------------*/
00147 /*  HMAC Hashed Message Authentication (RFC 2104)*/
00148 /* */
00149 /*  hmac = H(K xor opad, H(K xor ipad, text))*/
00150 /* */
00151 ret  ::ripemd::ripemd128::RIPEHMAC128Init (type K) {
00152 
00153     # Key K is adjusted to be 64 bytes long. If K is larger, then use
00154     # the RIPEMD-128 digest of K and pad this instead.
00155     set len [string length $K]
00156     if {$len > 64} {
00157         set tok [RIPEMD128Init]
00158         RIPEMD128Update $tok $K
00159         set K [RIPEMD128Final $tok]
00160         set len [string length $K]
00161     }
00162     set pad [expr {64 - $len}]
00163     append K [string repeat \0 $pad]
00164 
00165     # Cacluate the padding buffers.
00166     set Ki {}
00167     set Ko {}
00168     binary scan $K i16 Ks
00169     foreach k $Ks {
00170         append Ki [binary format i [expr {$k ^ 0x36363636}]]
00171         append Ko [binary format i [expr {$k ^ 0x5c5c5c5c}]]
00172     }
00173 
00174     set tok [RIPEMD128Init]
00175     RIPEMD128Update $tok $Ki;                 # initialize with the inner pad
00176     
00177     # preserve the Ko value for the final stage.
00178     # FRINK: nocheck
00179     set [subst $tok](Ko) $Ko
00180 
00181     return $tok
00182 }
00183 
00184 ret  ::ripemd::ripemd128::RIPEHMAC128Update (type token , type data) {
00185     RIPEMD128Update $token $data
00186     return
00187 }
00188 
00189 ret  ::ripemd::ripemd128::RIPEHMAC128Final (type token) {
00190     # FRINK: nocheck
00191     variable $token
00192     upvar 0 $token state
00193 
00194     set tok [RIPEMD128Init];            # init the outer hashing function
00195     RIPEMD128Update $tok $state(Ko);    # prepare with the outer pad.
00196     RIPEMD128Update $tok [RIPEMD128Final $token];  # hash the inner result
00197     return [RIPEMD128Final $tok]
00198 }
00199 
00200 /*  -------------------------------------------------------------------------*/
00201 
00202  ::ripemd = ::ripemd128::RIPEMD128Hash_body {
00203     variable $token
00204     upvar 0 $token state
00205 
00206     /*  RFC1320:3.4 - Process Message in 16-Word Blocks*/
00207     binary scan $msg i* blocks
00208     foreach {X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15} $blocks {
00209          A =  $state(A)   ;   AA =  $state(A)
00210          B =  $state(B)   ;   BB =  $state(B)
00211          C =  $state(C)   ;   CC =  $state(C)
00212          D =  $state(D)   ;   DD =  $state(D)
00213 
00214         /*  Round 1 (track 1). */
00215         /*     F(x,y,z) = x ^ y ^ z*/
00216         /*  Let [abcd x s] denote the operation*/
00217         /*     a = (a + F(b,c,d) + X[x]) <<< s.*/
00218         /*  Do the following 16 operations.*/
00219         /*  [ABCD  0  11]  [DABC  1  14]  [CDAB  2 15]  [BCDA  3 12]*/
00220          A =  [expr {($A + [F $B $C $D] + $X0)  <<< 11}]
00221          D =  [expr {($D + [F $A $B $C] + $X1)  <<< 14}]
00222          C =  [expr {($C + [F $D $A $B] + $X2)  <<< 15}]
00223          B =  [expr {($B + [F $C $D $A] + $X3)  <<< 12}]
00224         /*  [ABCD  4  5]  [DABC  5  8]  [CDAB  6 7]  [BCDA  7 9]*/
00225          A =  [expr {($A + [F $B $C $D] + $X4)  <<< 5}]
00226          D =  [expr {($D + [F $A $B $C] + $X5)  <<< 8}]
00227          C =  [expr {($C + [F $D $A $B] + $X6)  <<< 7}]
00228          B =  [expr {($B + [F $C $D $A] + $X7)  <<< 9}]
00229         /*  [ABCD  8  11]  [DABC  9  13]  [CDAB 10 14]  [BCDA 11 15]*/
00230          A =  [expr {($A + [F $B $C $D] + $X8)  <<< 11}]
00231          D =  [expr {($D + [F $A $B $C] + $X9)  <<< 13}]
00232          C =  [expr {($C + [F $D $A $B] + $X10) <<< 14}]
00233          B =  [expr {($B + [F $C $D $A] + $X11) <<< 15}]
00234         /*  [ABCD 12  6]  [DABC 13  7]  [CDAB 14 9]  [BCDA 15 8]*/
00235          A =  [expr {($A + [F $B $C $D] + $X12) <<< 6}]
00236          D =  [expr {($D + [F $A $B $C] + $X13) <<< 7}]
00237          C =  [expr {($C + [F $D $A $B] + $X14) <<< 9}]
00238          B =  [expr {($B + [F $C $D $A] + $X15) <<< 8}]
00239 
00240         /*  Round 2 (track 1).*/
00241         /*    G(x, y, z) = (x & y) | (~x & z)*/
00242         /*  Let [abcd k s] denote the operation*/
00243         /*    a = (a + G(b,c,d) + X[k] + 5A827999) <<< s*/
00244         /*  Do the following 16 operations.*/
00245         /*  [ABCD  7  7]  [DABC  4  6]  [CDAB  13  8]  [BCDA 1 13]*/
00246          A =  [expr {($A + [G $B $C $D] + $X7  + 0x5a827999) <<< 7}]
00247          D =  [expr {($D + [G $A $B $C] + $X4  + 0x5a827999) <<< 6}]
00248          C =  [expr {($C + [G $D $A $B] + $X13 + 0x5a827999) <<< 8}]
00249          B =  [expr {($B + [G $C $D $A] + $X1  + 0x5a827999) <<< 13}]
00250         /*  [ABCD  10  11]  [DABC  6  9]  [CDAB  15  7]  [BCDA 3 15]*/
00251          A =  [expr {($A + [G $B $C $D] + $X10 + 0x5a827999) <<< 11}]
00252          D =  [expr {($D + [G $A $B $C] + $X6  + 0x5a827999) <<< 9}]
00253          C =  [expr {($C + [G $D $A $B] + $X15 + 0x5a827999) <<< 7}]
00254          B =  [expr {($B + [G $C $D $A] + $X3  + 0x5a827999) <<< 15}]
00255         /*  [ABCD 12  7]  [DABC  0  12]  [CDAB 9  15]  [BCDA 5 9]*/
00256          A =  [expr {($A + [G $B $C $D] + $X12 + 0x5a827999) <<< 7}]
00257          D =  [expr {($D + [G $A $B $C] + $X0  + 0x5a827999) <<< 12}]
00258          C =  [expr {($C + [G $D $A $B] + $X9  + 0x5a827999) <<< 15}]
00259          B =  [expr {($B + [G $C $D $A] + $X5  + 0x5a827999) <<< 9}]
00260         /*  [ABCD  2  11]  [DABC  14  7]  [CDAB 11  13]  [BCDA 8 12]*/
00261          A =  [expr {($A + [G $B $C $D] + $X2  + 0x5a827999) <<< 11}]
00262          D =  [expr {($D + [G $A $B $C] + $X14 + 0x5a827999) <<< 7}]
00263          C =  [expr {($C + [G $D $A $B] + $X11 + 0x5a827999) <<< 13}]
00264          B =  [expr {($B + [G $C $D $A] + $X8  + 0x5a827999) <<< 12}]
00265         
00266         /*  Round 3 (track 1).*/
00267         /*    H(x,y,z) = (x | ~y) ^ z*/
00268         /*  Let [abcd k s] denote the operation*/
00269         /*    a = (a + H(b,c,d) + X[k] + 6ED9EBA1) <<< s.*/
00270         /*  Do the following 16 operations.*/
00271         /*  [ABCD  3  11]  [DABC  10  13]  [CDAB  14 6]  [BCDA 4 7]*/
00272          A =  [expr {($A + [H $B $C $D] + $X3  + 0x6ed9eba1) <<< 11}]
00273          D =  [expr {($D + [H $A $B $C] + $X10 + 0x6ed9eba1) <<< 13}]
00274          C =  [expr {($C + [H $D $A $B] + $X14 + 0x6ed9eba1) <<< 6}]
00275          B =  [expr {($B + [H $C $D $A] + $X4  + 0x6ed9eba1) <<< 7}]
00276         /*  [ABCD  9  14]  [DABC 15  9]  [CDAB  8 13]  [BCDA 1 15]*/
00277          A =  [expr {($A + [H $B $C $D] + $X9  + 0x6ed9eba1) <<< 14}]
00278          D =  [expr {($D + [H $A $B $C] + $X15 + 0x6ed9eba1) <<< 9}]
00279          C =  [expr {($C + [H $D $A $B] + $X8  + 0x6ed9eba1) <<< 13}]
00280          B =  [expr {($B + [H $C $D $A] + $X1  + 0x6ed9eba1) <<< 15}]
00281         /*  [ABCD  2  14]  [DABC  7  8]  [CDAB  0 13]  [BCDA 6 6]*/
00282          A =  [expr {($A + [H $B $C $D] + $X2  + 0x6ed9eba1) <<< 14}]
00283          D =  [expr {($D + [H $A $B $C] + $X7  + 0x6ed9eba1) <<< 8}]
00284          C =  [expr {($C + [H $D $A $B] + $X0  + 0x6ed9eba1) <<< 13}]
00285          B =  [expr {($B + [H $C $D $A] + $X6  + 0x6ed9eba1) <<< 6}]
00286         /*  [ABCD  13  5]  [DABC 11  12]  [CDAB  5 7]  [BCDA 12  5]*/
00287          A =  [expr {($A + [H $B $C $D] + $X13 + 0x6ed9eba1) <<< 5}]
00288          D =  [expr {($D + [H $A $B $C] + $X11 + 0x6ed9eba1) <<< 12}]
00289          C =  [expr {($C + [H $D $A $B] + $X5  + 0x6ed9eba1) <<< 7}]
00290          B =  [expr {($B + [H $C $D $A] + $X12 + 0x6ed9eba1) <<< 5}]
00291 
00292         /*  Round 4 (track 1).*/
00293         /*    I(x,y,z) = (x & z) | (y & ^ ~z)*/
00294         /*  Let [abcd k s] denote the operation*/
00295         /*    a = (a + I(b,c,d) + X[k] + 8F1BBCDC) <<< s.*/
00296         /*  Do the following 16 operations.*/
00297         /*  [ABCD  1  11]  [DABC  9  12]  [CDAB  11 14]  [BCDA 10 15]*/
00298          A =  [expr {($A + [I $B $C $D] + $X1  + 0x8f1bbcdc) <<< 11}]
00299          D =  [expr {($D + [I $A $B $C] + $X9  + 0x8f1bbcdc) <<< 12}]
00300          C =  [expr {($C + [I $D $A $B] + $X11 + 0x8f1bbcdc) <<< 14}]
00301          B =  [expr {($B + [I $C $D $A] + $X10 + 0x8f1bbcdc) <<< 15}]
00302         /*  [ABCD  0  14]  [DABC 8  15]  [CDAB 12 9]  [BCDA 4 8]*/
00303          A =  [expr {($A + [I $B $C $D] + $X0  + 0x8f1bbcdc) <<< 14}]
00304          D =  [expr {($D + [I $A $B $C] + $X8  + 0x8f1bbcdc) <<< 15}]
00305          C =  [expr {($C + [I $D $A $B] + $X12 + 0x8f1bbcdc) <<< 9}]
00306          B =  [expr {($B + [I $C $D $A] + $X4  + 0x8f1bbcdc) <<< 8}]
00307         /*  [ABCD  13  9]  [DABC  3  14]  [CDAB  7 5]  [BCDA 15 6]*/
00308          A =  [expr {($A + [I $B $C $D] + $X13 + 0x8f1bbcdc) <<< 9}]
00309          D =  [expr {($D + [I $A $B $C] + $X3  + 0x8f1bbcdc) <<< 14}]
00310          C =  [expr {($C + [I $D $A $B] + $X7  + 0x8f1bbcdc) <<< 5}]
00311          B =  [expr {($B + [I $C $D $A] + $X15 + 0x8f1bbcdc) <<< 6}]
00312         /*  [ABCD  14  8]  [DABC 5  6]  [CDAB  6 5]  [BCDA 2 12]*/
00313          A =  [expr {($A + [I $B $C $D] + $X14 + 0x8f1bbcdc) <<< 8}]
00314          D =  [expr {($D + [I $A $B $C] + $X5  + 0x8f1bbcdc) <<< 6}]
00315          C =  [expr {($C + [I $D $A $B] + $X6  + 0x8f1bbcdc) <<< 5}]
00316          B =  [expr {($B + [I $C $D $A] + $X2  + 0x8f1bbcdc) <<< 12}]
00317 
00318 
00319         /*  Round 1 (track 2).*/
00320         /*    I(x,y,z) = (x & z) | (y & ^ ~z)*/
00321         /*  Let [abcd k s] denote the operation*/
00322         /*    a = (a + I(b,c,d) + X[k] + 50A28BE6) <<< s.*/
00323         /*  Do the following 16 operations.*/
00324         /*  [ABCD  5  8]  [DABC  14  9]  [CDAB  7 9]  [BCDA 0 11]*/
00325          AA =  [expr {($AA + [I $BB $CC $DD] + $X5  + 0x50a28be6) <<< 8}]
00326          DD =  [expr {($DD + [I $AA $BB $CC] + $X14 + 0x50a28be6) <<< 9}]
00327          CC =  [expr {($CC + [I $DD $AA $BB] + $X7  + 0x50a28be6) <<< 9}]
00328          BB =  [expr {($BB + [I $CC $DD $AA] + $X0  + 0x50a28be6) <<< 11}]
00329         /*  [ABCD  9  13]  [DABC 2  15]  [CDAB 11 15]  [BCDA 4 5]*/
00330          AA =  [expr {($AA + [I $BB $CC $DD] + $X9  + 0x50a28be6) <<< 13}]
00331          DD =  [expr {($DD + [I $AA $BB $CC] + $X2  + 0x50a28be6) <<< 15}]
00332          CC =  [expr {($CC + [I $DD $AA $BB] + $X11 + 0x50a28be6) <<< 15}]
00333          BB =  [expr {($BB + [I $CC $DD $AA] + $X4  + 0x50a28be6) <<< 5}]
00334         /*  [ABCD  13  7]  [DABC  6  7]  [CDAB  15 8]  [BCDA 8 11]*/
00335          AA =  [expr {($AA + [I $BB $CC $DD] + $X13 + 0x50a28be6) <<< 7}]
00336          DD =  [expr {($DD + [I $AA $BB $CC] + $X6  + 0x50a28be6) <<< 7}]
00337          CC =  [expr {($CC + [I $DD $AA $BB] + $X15 + 0x50a28be6) <<< 8}]
00338          BB =  [expr {($BB + [I $CC $DD $AA] + $X8  + 0x50a28be6) <<< 11}]
00339         /*  [ABCD  1  14]  [DABC 10  14]  [CDAB  3 12]  [BCDA 12 6]*/
00340          AA =  [expr {($AA + [I $BB $CC $DD] + $X1  + 0x50a28be6) <<< 14}]
00341          DD =  [expr {($DD + [I $AA $BB $CC] + $X10 + 0x50a28be6) <<< 14}]
00342          CC =  [expr {($CC + [I $DD $AA $BB] + $X3  + 0x50a28be6) <<< 12}]
00343          BB =  [expr {($BB + [I $CC $DD $AA] + $X12 + 0x50a28be6) <<< 6}]
00344 
00345         /*  Round 2 (track 2).*/
00346         /*    H(x,y,z) = (x | ~y) ^ z*/
00347         /*  Let [abcd k s] denote the operation*/
00348         /*    a = (a + H(b,c,d) + X[k] + 5C4DD124) <<< s.*/
00349         /*  Do the following 16 operations.*/
00350         /*  [ABCD  6  9]  [DABC  11  13]  [CDAB  3 15]  [BCDA 7 7]*/
00351          AA =  [expr {($AA + [H $BB $CC $DD] + $X6  + 0x5c4dd124) <<< 9}]
00352          DD =  [expr {($DD + [H $AA $BB $CC] + $X11 + 0x5c4dd124) <<< 13}]
00353          CC =  [expr {($CC + [H $DD $AA $BB] + $X3  + 0x5c4dd124) <<< 15}]
00354          BB =  [expr {($BB + [H $CC $DD $AA] + $X7  + 0x5c4dd124) <<< 7}]
00355         /*  [ABCD  0  12]  [DABC 13  8]  [CDAB 5 9]  [BCDA 10 11]*/
00356          AA =  [expr {($AA + [H $BB $CC $DD] + $X0  + 0x5c4dd124) <<< 12}]
00357          DD =  [expr {($DD + [H $AA $BB $CC] + $X13 + 0x5c4dd124) <<< 8}]
00358          CC =  [expr {($CC + [H $DD $AA $BB] + $X5  + 0x5c4dd124) <<< 9}]
00359          BB =  [expr {($BB + [H $CC $DD $AA] + $X10 + 0x5c4dd124) <<< 11}]
00360         /*  [ABCD  14  7]  [DABC  15  7]  [CDAB  8 12]  [BCDA 12 7]*/
00361          AA =  [expr {($AA + [H $BB $CC $DD] + $X14 + 0x5c4dd124) <<< 7}]
00362          DD =  [expr {($DD + [H $AA $BB $CC] + $X15 + 0x5c4dd124) <<< 7}]
00363          CC =  [expr {($CC + [H $DD $AA $BB] + $X8  + 0x5c4dd124) <<< 12}]
00364          BB =  [expr {($BB + [H $CC $DD $AA] + $X12 + 0x5c4dd124) <<< 7}]
00365         /*  [ABCD  4  6]  [DABC 9  15]  [CDAB  1 13]  [BCDA 2 11]*/
00366          AA =  [expr {($AA + [H $BB $CC $DD] + $X4  + 0x5c4dd124) <<< 6}]
00367          DD =  [expr {($DD + [H $AA $BB $CC] + $X9  + 0x5c4dd124) <<< 15}]
00368          CC =  [expr {($CC + [H $DD $AA $BB] + $X1  + 0x5c4dd124) <<< 13}]
00369          BB =  [expr {($BB + [H $CC $DD $AA] + $X2  + 0x5c4dd124) <<< 11}]
00370 
00371         /*  Round 3 (track 2).*/
00372         /*    G(x, y, z) = (x & y) | (~x & z)*/
00373         /*  Let [abcd k s] denote the operation*/
00374         /*    a = (a + G(b,c,d) + X[k] + 6D703EF3) <<< s.*/
00375         /*  Do the following 16 operations.*/
00376         /*  [ABCD  15  9]  [DABC  5 7]  [CDAB  1 15]  [BCDA 3 11]*/
00377          AA =  [expr {($AA + [G $BB $CC $DD] + $X15 + 0x6d703ef3) <<< 9}]
00378          DD =  [expr {($DD + [G $AA $BB $CC] + $X5  + 0x6d703ef3) <<< 7}]
00379          CC =  [expr {($CC + [G $DD $AA $BB] + $X1  + 0x6d703ef3) <<< 15}]
00380          BB =  [expr {($BB + [G $CC $DD $AA] + $X3  + 0x6d703ef3) <<< 11}]
00381         /*  [ABCD  7  8]  [DABC 14  6]  [CDAB 6 6]  [BCDA 9 14]*/
00382          AA =  [expr {($AA + [G $BB $CC $DD] + $X7  + 0x6d703ef3) <<< 8}]
00383          DD =  [expr {($DD + [G $AA $BB $CC] + $X14 + 0x6d703ef3) <<< 6}]
00384          CC =  [expr {($CC + [G $DD $AA $BB] + $X6  + 0x6d703ef3) <<< 6}]
00385          BB =  [expr {($BB + [G $CC $DD $AA] + $X9  + 0x6d703ef3) <<< 14}]
00386         /*  [ABCD  11  12]  [DABC  8  13]  [CDAB  12 5]  [BCDA 2 14]*/
00387          AA =  [expr {($AA + [G $BB $CC $DD] + $X11 + 0x6d703ef3) <<< 12}]
00388          DD =  [expr {($DD + [G $AA $BB $CC] + $X8  + 0x6d703ef3) <<< 13}]
00389          CC =  [expr {($CC + [G $DD $AA $BB] + $X12 + 0x6d703ef3) <<< 5}]
00390          BB =  [expr {($BB + [G $CC $DD $AA] + $X2  + 0x6d703ef3) <<< 14}]
00391         /*  [ABCD  10  13]  [DABC 0  13]  [CDAB  4 7]  [BCDA 13 5]*/
00392          AA =  [expr {($AA + [G $BB $CC $DD] + $X10 + 0x6d703ef3) <<< 13}]
00393          DD =  [expr {($DD + [G $AA $BB $CC] + $X0  + 0x6d703ef3) <<< 13}]
00394          CC =  [expr {($CC + [G $DD $AA $BB] + $X4  + 0x6d703ef3) <<< 7}]
00395          BB =  [expr {($BB + [G $CC $DD $AA] + $X13 + 0x6d703ef3) <<< 5}]
00396 
00397         /*  Round 4 (track 2).*/
00398         /*    F(x,y,z) = x ^ y ^ z*/
00399         /*  Let [abcd k s] denote the operation*/
00400         /*    a = (a + F(b,c,d) + X[k]) <<< s.*/
00401         /*  Do the following 16 operations.*/
00402         /*  [ABCD  8  15]  [DABC  6 5]  [CDAB  4 8]  [BCDA 1 11]*/
00403          AA =  [expr {($AA + [F $BB $CC $DD] + $X8)  <<< 15}]
00404          DD =  [expr {($DD + [F $AA $BB $CC] + $X6)  <<< 5}]
00405          CC =  [expr {($CC + [F $DD $AA $BB] + $X4)  <<< 8}]
00406          BB =  [expr {($BB + [F $CC $DD $AA] + $X1)  <<< 11}]
00407         /*  [ABCD  3  14]  [DABC 11 14]  [CDAB 15 6]  [BCDA 0 14]*/
00408          AA =  [expr {($AA + [F $BB $CC $DD] + $X3)  <<< 14}]
00409          DD =  [expr {($DD + [F $AA $BB $CC] + $X11) <<< 14}]
00410          CC =  [expr {($CC + [F $DD $AA $BB] + $X15) <<< 6}]
00411          BB =  [expr {($BB + [F $CC $DD $AA] + $X0)  <<< 14}]
00412         /*  [ABCD  5  6]  [DABC  12 9]  [CDAB  2 12]  [BCDA 13 9]*/
00413          AA =  [expr {($AA + [F $BB $CC $DD] + $X5)  <<< 6}]
00414          DD =  [expr {($DD + [F $AA $BB $CC] + $X12) <<< 9}]
00415          CC =  [expr {($CC + [F $DD $AA $BB] + $X2)  <<< 12}]
00416          BB =  [expr {($BB + [F $CC $DD $AA] + $X13) <<< 9}]
00417         /*  [ABCD  9  12]  [DABC 7  5]  [CDAB  10 15]  [BCDA 14 8]*/
00418          AA =  [expr {($AA + [F $BB $CC $DD] + $X9)  <<< 12}]
00419          DD =  [expr {($DD + [F $AA $BB $CC] + $X7)  <<< 5}]
00420          CC =  [expr {($CC + [F $DD $AA $BB] + $X10) <<< 15}]
00421          BB =  [expr {($BB + [F $CC $DD $AA] + $X14) <<< 8}]
00422 
00423         /*  Then perform the following additions to combine the results.*/
00424          DD =        [expr {$state(B) + $C + $DD}]
00425          state = (B) [expr {$state(C) + $D + $AA}]
00426          state = (C) [expr {$state(D) + $A + $BB}]
00427          state = (D) [expr {$state(A) + $B + $CC}]
00428          state = (A) $DD
00429     }
00430 
00431     return
00432 }
00433 
00434 ret  ::ripemd::ripemd128::byte (type n , type v) {expr {((0xFF << (8 * $n)) & $v) >> (8 * $n)}}
00435 ret  ::ripemd::ripemd128::bytes (type v) { 
00436     #format %c%c%c%c [byte 0 $v] [byte 1 $v] [byte 2 $v] [byte 3 $v]
00437     format %c%c%c%c \
00438         [expr {0xFF & $v}] \
00439         [expr {(0xFF00 & $v) >> 8}] \
00440         [expr {(0xFF0000 & $v) >> 16}] \
00441         [expr {((0xFF000000 & $v) >> 24) & 0xFF}]
00442 }
00443 
00444 /*  32bit rotate-left*/
00445 ret  ::ripemd::ripemd128::<<< (type v , type n) {
00446     return [expr {((($v << $n) \
00447                         | (($v >> (32 - $n)) \
00448                                & (0x7FFFFFFF >> (31 - $n))))) \
00449                       & 0xFFFFFFFF}]
00450 }
00451 
00452 /*  Convert our <<< pseudo-operator into a procedure call.*/
00453 regsub -all -line \
00454     {\[expr {(.*) <<< (\d+)}\]} \
00455     $::ripemd::ripemd128::RIPEMD128Hash_body \
00456     {[<<< [expr {\1}] \2]} \
00457     ::ripemd::ripemd128::RIPEMD128Hash_body
00458 
00459 /*   F(x,y,z) = x ^ y ^ z*/
00460 ret  ::ripemd::ripemd128::F (type X , type Y , type Z) {
00461     return [expr {$X ^ $Y ^ $Z}]
00462 }
00463 /*  Inline the F function F*/
00464 regsub -all -line \
00465     {\[F (\$[ABCD]{1,2}) (\$[ABCD]{1,2}) (\$[ABCD]{1,2})\]} \
00466     $::ripemd::ripemd128::RIPEMD128Hash_body \
00467     {(\1 ^ \2 ^ \3)} \
00468     ::ripemd::ripemd128::RIPEMD128Hash_body
00469     
00470 /*  G(x,y,z) = (x & y) | (~x & z)*/
00471 ret  ::ripemd::ripemd128::G (type X , type Y , type Z) {
00472     return [expr {($X & $Y) | (~$X & $Z)}]
00473 }
00474 /*  Inline the G function*/
00475 regsub -all -line \
00476     {\[G (\$[ABCD]{1,2}) (\$[ABCD]{1,2}) (\$[ABCD]{1,2})\]} \
00477     $::ripemd::ripemd128::RIPEMD128Hash_body \
00478     {((\1 \& \2) | (~\1 \& \3))} \
00479     ::ripemd::ripemd128::RIPEMD128Hash_body
00480 
00481 /*  H(x,y,z) = (x | ~y) ^ z*/
00482 ret  ::ripemd::ripemd128::H (type X , type Y , type Z) {
00483     return [expr {($X | ~$Y) ^ $Z}]
00484 }
00485 /*  Inline the H function*/
00486 regsub -all -line \
00487     {\[H (\$[ABCD]{1,2}) (\$[ABCD]{1,2}) (\$[ABCD]{1,2})\]} \
00488     $::ripemd::ripemd128::RIPEMD128Hash_body \
00489     {( (\1 | ~\2) ^ \3)} \
00490     ::ripemd::ripemd128::RIPEMD128Hash_body
00491 
00492 /*  I(x,y,z) = (x & z) | (y & ~z)*/
00493 ret  ::ripemd::ripemd128::I (type X , type Y , type Z) {
00494     return [expr {($X & $Z) | ($Y & ~$Z)}]
00495 }
00496 /*  Inline the I function*/
00497 regsub -all -line \
00498     {\[I (\$[ABCD]{1,2}) (\$[ABCD]{1,2}) (\$[ABCD]{1,2})\]} \
00499     $::ripemd::ripemd128::RIPEMD128Hash_body \
00500     {( (\1 \& \3) | (\2 \& ~\3) )} \
00501     ::ripemd::ripemd128::RIPEMD128Hash_body
00502 
00503 /*  Define the MD4 hashing procedure with inline functions.*/
00504 ret  ::ripemd::ripemd128::RIPEMD128Hash (type token , type msg) $::ripemd::ripemd128::RIPEMD128Hash_body
00505 
00506 # -------------------------------------------------------------------------
00507 
00508 proc ::ripemd::ripemd128::Hex {data} {
00509     binary scan $data H* result
00510     return $result
00511 }
00512 
00513 /*  -------------------------------------------------------------------------*/
00514 
00515 /*  LoadAccelerator --*/
00516 /* */
00517 /*  This package can make use of a number of compiled extensions to*/
00518 /*  accelerate the digest computation. This procedure manages the*/
00519 /*  use of these extensions within the package. During normal usage*/
00520 /*  this should not be called, but the test package manipulates the*/
00521 /*  list of enabled accelerators.*/
00522 /* */
00523 ret  ::ripemd::ripemd128::LoadAccelerator (type name) {
00524     variable accel
00525     set r 0
00526     switch -exact -- $name {
00527         #critcl {
00528         #    if {![catch {package require tcllibc}]
00529         #        || ![catch {package require sha1c}]} {
00530         #        set r [expr {[info command ::sha1::sha1c] != {}}]
00531         #    }
00532         #}
00533         #cryptkit {
00534         #    if {![catch {package require cryptkit}]} {
00535         #        set r [expr {![catch {cryptkit::cryptInit}]}]
00536         #    }
00537         #}
00538         trf {
00539             if {![catch {package require Trf}]} {
00540                 set r [expr {![catch {::ripemd128 aa} msg]}]
00541             }
00542         }
00543         default {
00544             return -code error "invalid accelerator package:\
00545                 must be one of [join [array names accel] {, }]"
00546         }
00547     }
00548     set accel($name) $r
00549 }
00550 
00551 /*  -------------------------------------------------------------------------*/
00552 
00553 /*  Description:*/
00554 /*   Pop the nth element off a list. Used in options processing.*/
00555 /* */
00556 ret  ::ripemd::ripemd128::Pop (type varname , optional nth =0) {
00557     upvar $varname args
00558     set r [lindex $args $nth]
00559     set args [lreplace $args $nth $nth]
00560     return $r
00561 }
00562 
00563 /*  -------------------------------------------------------------------------*/
00564 
00565 /*  fileevent handler for chunked file hashing.*/
00566 /* */
00567 ret  ::ripemd::ripemd128::Chunk (type token , type channel , optional chunksize =4096) {
00568     # FRINK: nocheck
00569     variable $token
00570     upvar 0 $token state
00571     
00572     if {[eof $channel]} {
00573         fileevent $channel readable {}
00574         set state(reading) 0
00575     }
00576         
00577     RIPEMD128Update $token [read $channel $chunksize]
00578 }
00579 
00580 /*  -------------------------------------------------------------------------*/
00581 
00582 ret  ::ripemd::ripemd128::ripemd128 (type args) {
00583     array set opts {-hex 0 -filename {} -channel {} -chunksize 4096}
00584     while {[string match -* [set option [lindex $args 0]]]} {
00585         switch -glob -- $option {
00586             -hex       { set opts(-hex) 1 }
00587             -file*     { set opts(-filename) [Pop args 1] }
00588             -channel   { set opts(-channel) [Pop args 1] }
00589             -chunksize { set opts(-chunksize) [Pop args 1] }
00590             default {
00591                 if {[llength $args] == 1} { break }
00592                 if {[string compare $option "--"] == 0} { Pop args; break }
00593                 set err [join [lsort [array names opts]] ", "]
00594                 return -code error "bad option $option:\
00595                     must be one of $err"
00596             }
00597         }
00598         Pop args
00599     }
00600     
00601     if {$opts(-filename) != {}} {
00602         set opts(-channel) [open $opts(-filename) r]
00603         fconfigure $opts(-channel) -translation binary
00604     }
00605 
00606     if {$opts(-channel) == {}} {
00607 
00608         if {[llength $args] != 1} {
00609             return -code error "wrong # args:\
00610                 should be \"ripemd128 ?-hex? -filename file | string\""
00611         }
00612         set tok [RIPEMD128Init]
00613         RIPEMD128Update $tok [lindex $args 0]
00614         set r [RIPEMD128Final $tok]
00615 
00616     } else {
00617 
00618         set tok [RIPEMD128Init]
00619         # FRINK: nocheck
00620         set [subst $tok](reading) 1
00621         fileevent $opts(-channel) readable \
00622             [list [namespace origin Chunk] \
00623                  $tok $opts(-channel) $opts(-chunksize)]
00624         vwait [subst $tok](reading)
00625         set r [RIPEMD128Final $tok]
00626 
00627         # If we opened the channel - we should close it too.
00628         if {$opts(-filename) != {}} {
00629             close $opts(-channel)
00630         }
00631     }
00632     
00633     if {$opts(-hex)} {
00634         set r [Hex $r]
00635     }
00636     return $r
00637 }
00638 
00639 /*  -------------------------------------------------------------------------*/
00640 
00641 ret  ::ripemd::ripemd128::hmac128 (type args) {
00642     array set opts {-hex 0 -filename {} -channel {} -chunksize 4096}
00643     while {[string match -* [set option [lindex $args 0]]]} {
00644         switch -glob -- $option {
00645             -key       { set opts(-key) [Pop args 1] }
00646             -hex       { set opts(-hex) 1 }
00647             -file*     { set opts(-filename) [Pop args 1] }
00648             -channel   { set opts(-channel) [Pop args 1] }
00649             -chunksize { set opts(-chunksize) [Pop args 1] }
00650             default {
00651                 if {[llength $args] == 1} { break }
00652                 if {[string compare $option "--"] == 0} { Pop args; break }
00653                 set err [join [lsort [array names opts]] ", "]
00654                 return -code error "bad option $option:\
00655                     must be one of $err"
00656             }
00657         }
00658         Pop args
00659     }
00660 
00661     if {![info exists opts(-key)]} {
00662         return -code error "wrong # args:\
00663             should be \"hmac128 ?-hex? -key key -filename file | string\""
00664     }
00665 
00666     if {$opts(-filename) != {}} {
00667         set opts(-channel) [open $opts(-filename) r]
00668         fconfigure $opts(-channel) -translation binary
00669     }
00670 
00671     if {$opts(-channel) == {}} {
00672 
00673         if {[llength $args] != 1} {
00674             return -code error "wrong # args:\
00675                 should be \"hmac128 ?-hex? -key key -filename file | string\""
00676         }
00677         set tok [RIPEHMAC128Init $opts(-key)]
00678         RIPEHMAC128Update $tok [lindex $args 0]
00679         set r [RIPEHMAC128Final $tok]
00680 
00681     } else {
00682 
00683         set tok [RIPEHMAC128Init $opts(-key)]
00684         # FRINK: nocheck
00685         set [subst $tok](reading) 1
00686         fileevent $opts(-channel) readable \
00687             [list [namespace origin Chunk] \
00688                  $tok $opts(-channel) $opts(-chunksize)]
00689         vwait [subst $tok](reading)
00690         set r [RIPEHMAC128Final $tok]
00691 
00692         # If we opened the channel - we should close it too.
00693         if {$opts(-filename) != {}} {
00694             close $opts(-channel)
00695         }
00696     }
00697     
00698     if {$opts(-hex)} {
00699         set r [Hex $r]
00700     }
00701     return $r
00702 }
00703 
00704 /*  -------------------------------------------------------------------------*/
00705 
00706 namespace ::ripemd {
00707 
00708     namespace import -force [namespace current]::ripemd128::*
00709 
00710     namespace export ripemd128 hmac128 \
00711         RIPEMD128Init RIPEMD128Update RIPEMD128Final \
00712         RIPEHMAC128Init RIPEHMAC128Update RIPEHMAC128Final
00713 }
00714 
00715 /*  -------------------------------------------------------------------------*/
00716 
00717 /*  Try and load a compiled extension to help.*/
00718 namespace ::ripemd::ripemd128 {
00719     foreach e {trf} { if {[LoadAccelerator $e]} { break } }
00720 }
00721 
00722 package provide ripemd128 $::ripemd::ripemd128::version
00723 
00724 /*  -------------------------------------------------------------------------*/
00725 /*  Local Variables:*/
00726 /*    mode: tcl*/
00727 /*    indent-tabs-mode: nil*/
00728 /*  End:*/
00729 
00730 
00731 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1