ripemd160.tcl

Go to the documentation of this file.
00001 /*  ripemd160.tcl - Copyright (C) 2003 Pat Thoyts <patthoyts@users.sf.net>*/
00002 /* */
00003 /*  This is a Tcl-only implementation of the RIPEMD-160 hash algorithm as */
00004 /*  described in [RIPE].*/
00005 /*  Included is an implementation of keyed message authentication using */
00006 /*  the RIPEMD-160 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: ripemd160.tcl,v 1.7 2005/02/24 03:25:50 patthoyts Exp $*/
00027 
00028 package require Tcl 8.2;                /*  tcl minimum version*/
00029 /* catch {package require ripemdc 1.0};   # tcllib critcl alternative*/
00030 
00031 namespace ::ripemd {
00032     namespace ripemd160 {
00033         variable version 1.0.3
00034         variable rcsid {$Id: ripemd160.tcl,v 1.7 2005/02/24 03:25:50 patthoyts Exp $}
00035         variable accel
00036         array  accel =  {cryptkit 0 trf 0}
00037 
00038         variable uid
00039         if {![info exists uid]} {
00040              uid =  0
00041         }
00042 
00043         namespace export ripemd160 hmac160 Hex \
00044             RIPEMD160Init RIPEMD160Update RIPEMD160Final \
00045             RIPEHMAC160Init RIPEHMAC160Update RIPEHMAC160Final
00046     }
00047 }
00048 
00049 /*  -------------------------------------------------------------------------*/
00050 
00051 /*  RIPEMD160Init - create and initialize the state variable. This will be*/
00052 /*  cleaned up when we call RIPEMD160Final*/
00053 /* */
00054 ret  ::ripemd::ripemd160::RIPEMD160Init () {
00055     variable accel
00056     variable uid
00057     set token [namespace current]::[incr uid]
00058     upvar #0 $token state
00059 
00060     # Initialize RIPEMD-160 state structure (same as MD4).
00061     array set state \
00062         [list \
00063              A [expr {0x67452301}] \
00064              B [expr {0xefcdab89}] \
00065              C [expr {0x98badcfe}] \
00066              D [expr {0x10325476}] \
00067              E [expr {0xc3d2e1f0}] \
00068              n 0 i "" ]
00069     if {$accel(cryptkit)} {
00070         cryptkit::cryptCreateContext state(ckctx) \
00071             CRYPT_UNUSED CRYPT_ALGO_RIPEMD160
00072     } elseif {$accel(trf)} {
00073         set s {}
00074         switch -exact -- $::tcl_platform(platform) {
00075             windows { set s [open NUL w] }
00076             unix    { set s [open /dev/null w] }
00077         }
00078         if {$s != {}} {
00079             fconfigure $s -translation binary -buffering none
00080             ::ripemd160 -attach $s -mode write \
00081                 -read-type variable \
00082                 -read-destination [subst $token](trfread) \
00083                 -write-type variable \
00084                 -write-destination [subst $token](trfwrite)
00085             array set state [list trfread 0 trfwrite 0 trf $s]
00086         }
00087     }
00088     return $token
00089 }
00090 
00091 ret  ::ripemd::ripemd160::RIPEMD160Update (type token , type data) {
00092     upvar #0 $token state
00093 
00094     if {[info exists state(ckctx)]} {
00095         if {[string length $data] > 0} {
00096             cryptkit::cryptEncrypt $state(ckctx) $data
00097         }
00098         return
00099     } elseif {[info exists state(trf)]} {
00100         puts -nonewline $state(trf) $data
00101         return
00102     }
00103 
00104     # Update the state values
00105     incr state(n) [string length $data]
00106     append state(i) $data
00107 
00108     # Calculate the hash for any complete blocks
00109     set len [string length $state(i)]
00110     for {set n 0} {($n + 64) <= $len} {} {
00111         RIPEMD160Hash $token [string range $state(i) $n [incr n 64]]
00112     }
00113 
00114     # Adjust the state for the blocks completed.
00115     set state(i) [string range $state(i) $n end]
00116     return
00117 }
00118 
00119 ret  ::ripemd::ripemd160::RIPEMD160Final (type token) {
00120     upvar #0 $token state
00121 
00122     if {[info exists state(ckctx)]} {
00123         cryptkit::cryptEncrypt $state(ckctx) ""
00124         cryptkit::cryptGetAttributeString $state(ckctx) \
00125             CRYPT_CTXINFO_HASHVALUE r 20
00126         cryptkit::cryptDestroyContext $state(ckctx)
00127         # If nothing was hashed, we get no r variable set!
00128         if {[info exists r]} {
00129             unset state
00130             return $r
00131         }
00132     } elseif {[info exists state(trf)]} {
00133         close $state(trf)
00134         set r $state(trfwrite)
00135         unset state
00136         return $r
00137     }
00138 
00139     # Padding
00140     #
00141     set len [string length $state(i)]
00142     set pad [expr {56 - ($len % 64)}]
00143     if {$len % 64 > 56} {
00144         incr pad 64
00145     }
00146     if {$pad == 0} {
00147         incr pad 64
00148     }
00149     append state(i) [binary format a$pad \x80]
00150 
00151     # Append length in bits as little-endian wide int.
00152     append state(i) [binary format ii [expr {8 * $state(n)}] 0]
00153 
00154     # Calculate the hash for the remaining block.
00155     set len [string length $state(i)]
00156     for {set n 0} {($n + 64) <= $len} {} {
00157         RIPEMD160Hash $token [string range $state(i) $n [incr n 64]]
00158     }
00159 
00160     # Output
00161     set r [bytes $state(A)][bytes $state(B)][bytes $state(C)][bytes $state(D)][bytes $state(E)]
00162     unset state
00163     return $r
00164 }
00165 
00166 /*  -------------------------------------------------------------------------*/
00167 /*  HMAC Hashed Message Authentication (RFC 2104)*/
00168 /* */
00169 /*  hmac = H(K xor opad, H(K xor ipad, text))*/
00170 /* */
00171 ret  ::ripemd::ripemd160::RIPEHMAC160Init (type K) {
00172 
00173     # Key K is adjusted to be 64 bytes long. If K is larger, then use
00174     # the RIPEMD-160 digest of K and pad this instead.
00175     set len [string length $K]
00176     if {$len > 64} {
00177         set tok [RIPEMD160Init]
00178         RIPEMD160Update $tok $K
00179         set K [RIPEMD160Final $tok]
00180         set len [string length $K]
00181     }
00182     set pad [expr {64 - $len}]
00183     append K [string repeat \0 $pad]
00184 
00185     # Cacluate the padding buffers.
00186     set Ki {}
00187     set Ko {}
00188     binary scan $K i16 Ks
00189     foreach k $Ks {
00190         append Ki [binary format i [expr {$k ^ 0x36363636}]]
00191         append Ko [binary format i [expr {$k ^ 0x5c5c5c5c}]]
00192     }
00193 
00194     set tok [RIPEMD160Init]
00195     RIPEMD160Update $tok $Ki;                 # initialize with the inner pad
00196     
00197     # preserve the Ko value for the final stage.
00198     # FRINK: nocheck
00199     set [subst $tok](Ko) $Ko
00200 
00201     return $tok
00202 }
00203 
00204 ret  ::ripemd::ripemd160::RIPEHMAC160Update (type token , type data) {
00205     RIPEMD160Update $token $data
00206     return
00207 }
00208 
00209 ret  ::ripemd::ripemd160::RIPEHMAC160Final (type token) {
00210     # FRINK: nocheck
00211     variable $token
00212     upvar 0 $token state
00213 
00214     set tok [RIPEMD160Init];            # init the outer hashing function
00215     RIPEMD160Update $tok $state(Ko);    # prepare with the outer pad.
00216     RIPEMD160Update $tok [RIPEMD160Final $token];  # hash the inner result
00217     return [RIPEMD160Final $tok]
00218 }
00219 
00220 /*  -------------------------------------------------------------------------*/
00221 
00222  ::ripemd = ::ripemd160::RIPEMD160Hash_body {
00223     variable $token
00224     upvar 0 $token state
00225 
00226     binary scan $msg i* blocks
00227     foreach {X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15} $blocks {
00228          A =  $state(A)   ;   AA =  $state(A)
00229          B =  $state(B)   ;   BB =  $state(B)
00230          C =  $state(C)   ;   CC =  $state(C)
00231          D =  $state(D)   ;   DD =  $state(D)
00232          E =  $state(E)   ;   EE =  $state(E)
00233 
00234         FF A B C D E $X0 11
00235         FF E A B C D $X1 14
00236         FF D E A B C $X2 15
00237         FF C D E A B $X3 12
00238         FF B C D E A $X4 5
00239         FF A B C D E $X5 8
00240         FF E A B C D $X6 7
00241         FF D E A B C $X7 9
00242         FF C D E A B $X8 11
00243         FF B C D E A $X9 13
00244         FF A B C D E $X10 14
00245         FF E A B C D $X11 15
00246         FF D E A B C $X12 6
00247         FF C D E A B $X13 7
00248         FF B C D E A $X14 9
00249         FF A B C D E $X15 8
00250         
00251         GG E A B C D $X7 7
00252         GG D E A B C $X4 6
00253         GG C D E A B $X13 8
00254         GG B C D E A $X1 13
00255         GG A B C D E $X10 11
00256         GG E A B C D $X6 9
00257         GG D E A B C $X15 7
00258         GG C D E A B $X3 15
00259         GG B C D E A $X12 7
00260         GG A B C D E $X0 12
00261         GG E A B C D $X9 15
00262         GG D E A B C $X5 9
00263         GG C D E A B $X2 11
00264         GG B C D E A $X14 7
00265         GG A B C D E $X11 13
00266         GG E A B C D $X8 12
00267         
00268         HH D E A B C $X3 11
00269         HH C D E A B $X10 13
00270         HH B C D E A $X14 6
00271         HH A B C D E $X4 7
00272         HH E A B C D $X9 14
00273         HH D E A B C $X15 9
00274         HH C D E A B $X8 13
00275         HH B C D E A $X1 15
00276         HH A B C D E $X2 14
00277         HH E A B C D $X7 8
00278         HH D E A B C $X0 13
00279         HH C D E A B $X6 6
00280         HH B C D E A $X13 5
00281         HH A B C D E $X11 12
00282         HH E A B C D $X5 7
00283         HH D E A B C $X12 5
00284         
00285         II C D E A B $X1 11
00286         II B C D E A $X9 12
00287         II A B C D E $X11 14
00288         II E A B C D $X10 15
00289         II D E A B C $X0 14
00290         II C D E A B $X8 15
00291         II B C D E A $X12 9
00292         II A B C D E $X4 8
00293         II E A B C D $X13 9
00294         II D E A B C $X3 14
00295         II C D E A B $X7 5
00296         II B C D E A $X15 6
00297         II A B C D E $X14 8
00298         II E A B C D $X5 6
00299         II D E A B C $X6 5
00300         II C D E A B $X2 12
00301         
00302         JJ B C D E A $X4 9
00303         JJ A B C D E $X0 15
00304         JJ E A B C D $X5 5
00305         JJ D E A B C $X9 11
00306         JJ C D E A B $X7 6
00307         JJ B C D E A $X12 8
00308         JJ A B C D E $X2 13
00309         JJ E A B C D $X10 12
00310         JJ D E A B C $X14 5
00311         JJ C D E A B $X1 12
00312         JJ B C D E A $X3 13
00313         JJ A B C D E $X8 14
00314         JJ E A B C D $X11 11
00315         JJ D E A B C $X6 8
00316         JJ C D E A B $X15 5
00317         JJ B C D E A $X13 6
00318         
00319         JJJ AA BB CC DD EE $X5 8
00320         JJJ EE AA BB CC DD $X14 9
00321         JJJ DD EE AA BB CC $X7 9
00322         JJJ CC DD EE AA BB $X0 11
00323         JJJ BB CC DD EE AA $X9 13
00324         JJJ AA BB CC DD EE $X2 15
00325         JJJ EE AA BB CC DD $X11 15
00326         JJJ DD EE AA BB CC $X4 5
00327         JJJ CC DD EE AA BB $X13 7
00328         JJJ BB CC DD EE AA $X6 7
00329         JJJ AA BB CC DD EE $X15 8
00330         JJJ EE AA BB CC DD $X8 11
00331         JJJ DD EE AA BB CC $X1 14
00332         JJJ CC DD EE AA BB $X10 14
00333         JJJ BB CC DD EE AA $X3 12
00334         JJJ AA BB CC DD EE $X12 6
00335         
00336         III EE AA BB CC DD $X6 9
00337         III DD EE AA BB CC $X11 13
00338         III CC DD EE AA BB $X3 15
00339         III BB CC DD EE AA $X7 7
00340         III AA BB CC DD EE $X0 12
00341         III EE AA BB CC DD $X13 8
00342         III DD EE AA BB CC $X5 9
00343         III CC DD EE AA BB $X10 11
00344         III BB CC DD EE AA $X14 7
00345         III AA BB CC DD EE $X15 7
00346         III EE AA BB CC DD $X8 12
00347         III DD EE AA BB CC $X12 7
00348         III CC DD EE AA BB $X4 6
00349         III BB CC DD EE AA $X9 15
00350         III AA BB CC DD EE $X1 13
00351         III EE AA BB CC DD $X2 11
00352         
00353         HHH DD EE AA BB CC $X15 9
00354         HHH CC DD EE AA BB $X5 7
00355         HHH BB CC DD EE AA $X1 15
00356         HHH AA BB CC DD EE $X3 11
00357         HHH EE AA BB CC DD $X7 8
00358         HHH DD EE AA BB CC $X14 6
00359         HHH CC DD EE AA BB $X6 6
00360         HHH BB CC DD EE AA $X9 14
00361         HHH AA BB CC DD EE $X11 12
00362         HHH EE AA BB CC DD $X8 13
00363         HHH DD EE AA BB CC $X12 5
00364         HHH CC DD EE AA BB $X2 14
00365         HHH BB CC DD EE AA $X10 13
00366         HHH AA BB CC DD EE $X0 13
00367         HHH EE AA BB CC DD $X4 7
00368         HHH DD EE AA BB CC $X13 5
00369         
00370         GGG CC DD EE AA BB $X8 15
00371         GGG BB CC DD EE AA $X6 5
00372         GGG AA BB CC DD EE $X4 8
00373         GGG EE AA BB CC DD $X1 11
00374         GGG DD EE AA BB CC $X3 14
00375         GGG CC DD EE AA BB $X11 14
00376         GGG BB CC DD EE AA $X15 6
00377         GGG AA BB CC DD EE $X0 14
00378         GGG EE AA BB CC DD $X5 6
00379         GGG DD EE AA BB CC $X12 9
00380         GGG CC DD EE AA BB $X2 12
00381         GGG BB CC DD EE AA $X13 9
00382         GGG AA BB CC DD EE $X9 12
00383         GGG EE AA BB CC DD $X7 5
00384         GGG DD EE AA BB CC $X10 15
00385         GGG CC DD EE AA BB $X14 8
00386         
00387         FFF BB CC DD EE AA $X12 8
00388         FFF AA BB CC DD EE $X15 5
00389         FFF EE AA BB CC DD $X10 12
00390         FFF DD EE AA BB CC $X4 9
00391         FFF CC DD EE AA BB $X1 12
00392         FFF BB CC DD EE AA $X5 5
00393         FFF AA BB CC DD EE $X8 14
00394         FFF EE AA BB CC DD $X7 6
00395         FFF DD EE AA BB CC $X6 8
00396         FFF CC DD EE AA BB $X2 13
00397         FFF BB CC DD EE AA $X13 6
00398         FFF AA BB CC DD EE $X14 5
00399         FFF EE AA BB CC DD $X0 15
00400         FFF DD EE AA BB CC $X3 13
00401         FFF CC DD EE AA BB $X9 11
00402         FFF BB CC DD EE AA $X11 11
00403 
00404         /*  Then perform the following additions to combine the results.*/
00405          DD =        [expr {$state(B) + $C + $DD}]
00406          state = (B) [expr {$state(C) + $D + $EE}]
00407          state = (C) [expr {$state(D) + $E + $AA}]
00408          state = (D) [expr {$state(E) + $A + $BB}]
00409          state = (E) [expr {$state(A) + $B + $CC}]
00410          state = (A) $DD
00411     }
00412 
00413     return
00414 }
00415 
00416 ret  ::ripemd::ripemd160::byte (type n , type v) {expr {((0xFF << (8 * $n)) & $v) >> (8 * $n)}}
00417 ret  ::ripemd::ripemd160::bytes (type v) { 
00418     #format %c%c%c%c [byte 0 $v] [byte 1 $v] [byte 2 $v] [byte 3 $v]
00419     format %c%c%c%c \
00420         [expr {0xFF & $v}] \
00421         [expr {(0xFF00 & $v) >> 8}] \
00422         [expr {(0xFF0000 & $v) >> 16}] \
00423         [expr {((0xFF000000 & $v) >> 24) & 0xFF}]
00424 }
00425 
00426 /*   F(x,y,z) = x ^ y ^ z*/
00427 ret  ::ripemd::ripemd160::F (type X , type Y , type Z) {
00428     return [expr {$X ^ $Y ^ $Z}]
00429 }
00430 /*  G(x,y,z) = (x & y) | (~x & z)*/
00431 ret  ::ripemd::ripemd160::G (type X , type Y , type Z) {
00432     return [expr {($X & $Y) | (~$X & $Z)}]
00433 }
00434 /*  H(x,y,z) = (x | ~y) ^ z*/
00435 ret  ::ripemd::ripemd160::H (type X , type Y , type Z) {
00436     return [expr {($X | ~$Y) ^ $Z}]
00437 }
00438 /*  I(x,y,z) = (x & z) | (y & ~z)*/
00439 ret  ::ripemd::ripemd160::I (type X , type Y , type Z) {
00440     return [expr {($X & $Z) | ($Y & ~$Z)}]
00441 }
00442 /*  J(x,y,z) = x ^ (y | ~z)*/
00443 ret  ::ripemd::ripemd160::J (type X , type Y , type Z) {
00444     return [expr {($X ^ ($Y | ~$Z))}]
00445 }
00446 
00447 ret  ::ripemd::ripemd160::FF (type a , type b , type c , type d , type e , type x , type s) {
00448     upvar $a A $b B $c C $d D $e E
00449     set A [<<< [expr {$A + ($B ^ $C ^ $D) + $x}] $s]
00450     incr A $E
00451     set C [<<< $C 10]
00452 }
00453 
00454 ret  ::ripemd::ripemd160::GG (type a , type b , type c , type d , type e , type x , type s) {
00455     upvar $a A $b B $c C $d D $e E
00456     set A [<<< [expr {$A + (($B & $C) | (~$B & $D)) + $x + 0x5a827999}] $s]
00457     incr A $E
00458     set C [<<< $C 10]
00459 }
00460 
00461 ret  ::ripemd::ripemd160::HH (type a , type b , type c , type d , type e , type x , type s) {
00462     upvar $a A $b B $c C $d D $e E
00463     set A [<<< [expr {$A + (($B | ~$C) ^ $D) + $x + 0x6ed9eba1}] $s]
00464     incr A $E
00465     set C [<<< $C 10]
00466 }
00467 
00468 ret  ::ripemd::ripemd160::II (type a , type b , type c , type d , type e , type x , type s) {
00469     upvar $a A $b B $c C $d D $e E
00470     set A [<<< [expr {$A + (($B & $D)|($C & ~$D)) + $x + 0x8f1bbcdc}] $s]
00471     incr A $E
00472     set C [<<< $C 10]
00473 
00474 }
00475 
00476 ret  ::ripemd::ripemd160::JJ (type a , type b , type c , type d , type e , type x , type s) {
00477     upvar $a A $b B $c C $d D $e E
00478     set A [<<< [expr {$A + ($B ^ ($C | ~$D)) + $x + 0xa953fd4e}] $s]
00479     incr A $E
00480     set C [<<< $C 10]
00481 }
00482 
00483 
00484 ret  ::ripemd::ripemd160::FFF (type a , type b , type c , type d , type e , type x , type s) {
00485     upvar $a A $b B $c C $d D $e E
00486     set A [<<< [expr {$A + ($B ^ $C ^ $D) + $x}] $s]
00487     incr A $E
00488     set C [<<< $C 10]
00489 }
00490 
00491 ret  ::ripemd::ripemd160::GGG (type a , type b , type c , type d , type e , type x , type s) {
00492     upvar $a A $b B $c C $d D $e E
00493     set A [<<< [expr {$A + (($B & $C) | (~$B & $D)) + $x + 0x7a6d76e9}] $s]
00494     incr A $E
00495     set C [<<< $C 10]
00496 }
00497 
00498 ret  ::ripemd::ripemd160::HHH (type a , type b , type c , type d , type e , type x , type s) {
00499     upvar $a A $b B $c C $d D $e E
00500     set A [<<< [expr {$A + (($B | ~$C) ^ $D) + $x + 0x6d703ef3}] $s]
00501     incr A $E
00502     set C [<<< $C 10]
00503 }
00504 
00505 ret  ::ripemd::ripemd160::III (type a , type b , type c , type d , type e , type x , type s) {
00506     upvar $a A $b B $c C $d D $e E
00507     set A [<<< [expr {$A + (($B & $D)|($C & ~$D)) + $x + 0x5c4dd124}] $s]
00508     incr A $E
00509     set C [<<< $C 10]
00510 
00511 }
00512 
00513 ret  ::ripemd::ripemd160::JJJ (type a , type b , type c , type d , type e , type x , type s) {
00514     upvar $a A $b B $c C $d D $e E
00515     set A [<<< [expr {$A + ($B ^ ($C | ~$D)) + $x + 0x50a28be6}] $s]
00516     incr A $E
00517     set C [<<< $C 10]
00518 }
00519 
00520 /*  32bit rotate-left*/
00521 ret  ::ripemd::ripemd160::<<< (type v , type n) {
00522     return [expr {((($v << $n) \
00523                         | (($v >> (32 - $n)) \
00524                                & (0x7FFFFFFF >> (31 - $n))))) \
00525                       & 0xFFFFFFFF}]
00526 }
00527 
00528 /*  -------------------------------------------------------------------------*/
00529 /*  Inline the algorithm functions*/
00530 /* */
00531 /*  On my test system inlining the functions like this improves*/
00532 /*    time {ripmd::ripmd160 [string repeat a 100]} 100*/
00533 /*  from 28ms per iteration to 13ms per iteration.*/
00534 /* */
00535 /*  This means that the functions above (F - J, FF - JJ and FFF-JJJ) are*/
00536 /*  not actually required for the code to operate. However, they provide*/
00537 /*  a readable way to document what is going on so have been left in.*/
00538 /* */
00539 namespace ::ripemd::ripemd160 {
00540 
00541     /*  Inline function FF and FFF*/
00542      Split =  {(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)}
00543     
00544     regsub -all -line \
00545         "^\\s+FFF?\\s+$Split$" \
00546         $RIPEMD160Hash_body \
00547         { \1 [<<< [expr =  {$\1 + ($\2 ^ $\3 ^ $\4) + \6}] \7];\
00548              incr \1 $\5;  \3 [<<< $\3 10]} \
00549         RIPEMD160Hash = _body
00550     
00551     /*  Inline function GG*/
00552     regsub -all -line \
00553         "^\\s+GG\\s+$Split$" \
00554         $RIPEMD160Hash_body \
00555         { \1 [<<< [expr =  {$\1 + (($\2 \& $\3) | (~$\2 \& $\4)) + \6 \
00556                                 + 0x5a827999}] \7];\
00557              incr \1 $\5;  \3 [<<< $\3 10]} \
00558         RIPEMD160Hash = _body
00559 
00560     /*  Inline function GGG*/
00561     regsub -all -line \
00562         "^\\s+GGG\\s+$Split$" \
00563         $RIPEMD160Hash_body \
00564         { \1 [<<< [expr =  {$\1 + (($\2 \& $\3) | (~$\2 \& $\4)) + \6 \
00565                                 + 0x7a6d76e9}] \7];\
00566              incr \1 $\5;  \3 [<<< $\3 10]} \
00567         RIPEMD160Hash = _body
00568 
00569     /*  Inline function HH*/
00570     regsub -all -line \
00571         "^\\s+HH\\s+$Split$" \
00572         $RIPEMD160Hash_body \
00573         { \1 [<<< [expr =  {$\1 + (($\2 | ~$\3) ^ $\4) + \6 \
00574                                 + 0x6ed9eba1}] \7];\
00575              incr \1 $\5;  \3 [<<< $\3 10]} \
00576         RIPEMD160Hash = _body
00577 
00578     /*  Inline function HHH*/
00579     regsub -all -line \
00580         "^\\s+HHH\\s+$Split$" \
00581         $RIPEMD160Hash_body \
00582         { \1 [<<< [expr =  {$\1 + (($\2 | ~$\3) ^ $\4) + \6 \
00583                                 + 0x6d703ef3}] \7];\
00584              incr \1 $\5;  \3 [<<< $\3 10]} \
00585         RIPEMD160Hash = _body
00586 
00587     /*  Inline function II*/
00588     regsub -all -line \
00589         "^\\s+II\\s+$Split$" \
00590         $RIPEMD160Hash_body \
00591         { \1 [<<< [expr =  {$\1 + (($\2 \& $\4) | ($\3 \& ~$\4)) + \6 \
00592                                 + 0x8f1bbcdc}] \7];\
00593              incr \1 $\5;  \3 [<<< $\3 10]} \
00594         RIPEMD160Hash = _body
00595 
00596     /*  Inline function III*/
00597     regsub -all -line \
00598         "^\\s+III\\s+$Split$" \
00599         $RIPEMD160Hash_body \
00600         { \1 [<<< [expr =  {$\1 + (($\2 \& $\4) | ($\3 \& ~$\4)) + \6 \
00601                                 + 0x5c4dd124}] \7];\
00602              incr \1 $\5;  \3 [<<< $\3 10]} \
00603         RIPEMD160Hash = _body
00604 
00605     /*  Inline function JJ*/
00606     regsub -all -line \
00607         "^\\s+JJ\\s+$Split$" \
00608         $RIPEMD160Hash_body \
00609         { \1 [<<< [expr =  {$\1 + ($\2 ^ ($\3 | ~$\4)) + \6 \
00610                                 + 0xa953fd4e}] \7];\
00611              incr \1 $\5;  \3 [<<< $\3 10]} \
00612         RIPEMD160Hash = _body
00613 
00614     /*  Inline function JJJ*/
00615     regsub -all -line \
00616         "^\\s+JJJ\\s+$Split$" \
00617         $RIPEMD160Hash_body \
00618         { \1 [<<< [expr =  {$\1 + ($\2 ^ ($\3 | ~$\4)) + \6 \
00619                                 + 0x50a28be6}] \7];\
00620              incr \1 $\5;  \3 [<<< $\3 10]} \
00621         RIPEMD160Hash = _body
00622 
00623     /*  Inline simple <<<*/
00624     regsub -all -line \
00625         {\[<<< (\$\S+)\s+(\d+)\]$} \
00626         $RIPEMD160Hash_body \
00627         {[expr {(((\1 << \2) \
00628                       | ((\1 >> (32 - \2)) \
00629                              \& (0x7FFFFFFF >> (31 - \2))))) \
00630                     \& 0xFFFFFFFF}]} \
00631         RIPEMD160Hash_body
00632 }
00633 
00634 /*  -------------------------------------------------------------------------*/
00635 
00636 /*  Define the hashing procedure with inline functions.*/
00637 ret  ::ripemd::ripemd160::RIPEMD160Hash (type token , type msg) \
00638     $::ripemd::ripemd160::RIPEMD160Hash_body
00639 
00640 # -------------------------------------------------------------------------
00641 
00642 proc ::ripemd::ripemd160::Hex {data} {
00643     binary scan $data H* result
00644     return $result
00645 }
00646 
00647 /*  -------------------------------------------------------------------------*/
00648 
00649 /*  LoadAccelerator --*/
00650 /* */
00651 /*  This package can make use of a number of compiled extensions to*/
00652 /*  accelerate the digest computation. This procedure manages the*/
00653 /*  use of these extensions within the package. During normal usage*/
00654 /*  this should not be called, but the test package manipulates the*/
00655 /*  list of enabled accelerators.*/
00656 /* */
00657 ret  ::ripemd::ripemd160::LoadAccelerator (type name) {
00658     variable accel
00659     set r 0
00660     switch -exact -- $name {
00661         #critcl {
00662         #    if {![catch {package require tcllibc}]
00663         #        || ![catch {package require sha1c}]} {
00664         #        set r [expr {[info command ::sha1::sha1c] != {}}]
00665         #    }
00666         #}
00667         cryptkit {
00668             if {![catch {package require cryptkit}]} {
00669                 set r [expr {![catch {cryptkit::cryptInit}]}]
00670             }
00671         }
00672         trf {
00673             if {![catch {package require Trf}]} {
00674                 set r [expr {![catch {::ripemd160 aa} msg]}]
00675             }
00676         }
00677         default {
00678             return -code error "invalid accelerator package:\
00679                 must be one of [join [array names accel] {, }]"
00680         }
00681     }
00682     set accel($name) $r
00683 }
00684 
00685 /*  -------------------------------------------------------------------------*/
00686 
00687 /*  Description:*/
00688 /*   Pop the nth element off a list. Used in options processing.*/
00689 /* */
00690 ret  ::ripemd::ripemd160::Pop (type varname , optional nth =0) {
00691     upvar $varname args
00692     set r [lindex $args $nth]
00693     set args [lreplace $args $nth $nth]
00694     return $r
00695 }
00696 
00697 /*  -------------------------------------------------------------------------*/
00698 
00699 /*  fileevent handler for chunked file hashing.*/
00700 /* */
00701 ret  ::ripemd::ripemd160::Chunk (type token , type channel , optional chunksize =4096) {
00702     # FRINK: nocheck
00703     variable $token
00704     upvar 0 $token state
00705     
00706     if {[eof $channel]} {
00707         fileevent $channel readable {}
00708         set state(reading) 0
00709     }
00710         
00711     RIPEMD160Update $token [read $channel $chunksize]
00712 }
00713 
00714 /*  -------------------------------------------------------------------------*/
00715 
00716 ret  ::ripemd::ripemd160::ripemd160 (type args) {
00717     array set opts {-hex 0 -filename {} -channel {} -chunksize 4096}
00718     while {[string match -* [set option [lindex $args 0]]]} {
00719         switch -glob -- $option {
00720             -hex       { set opts(-hex) 1 }
00721             -file*     { set opts(-filename) [Pop args 1] }
00722             -channel   { set opts(-channel) [Pop args 1] }
00723             -chunksize { set opts(-chunksize) [Pop args 1] }
00724             default {
00725                 if {[llength $args] == 1} { break }
00726                 if {[string compare $option "--"] == 0} { Pop args; break }
00727                 set err [join [lsort [array names opts]] ", "]
00728                 return -code error "bad option $option:\
00729                     must be one of $err"
00730             }
00731         }
00732         Pop args
00733     }
00734 
00735     if {$opts(-filename) != {}} {
00736         set opts(-channel) [open $opts(-filename) r]
00737         fconfigure $opts(-channel) -translation binary
00738     }
00739 
00740     if {$opts(-channel) == {}} {
00741 
00742         if {[llength $args] != 1} {
00743             return -code error "wrong # args:\
00744                 should be \"ripemd160 ?-hex? -filename file | string\""
00745         }
00746         set tok [RIPEMD160Init]
00747         RIPEMD160Update $tok [lindex $args 0]
00748         set r [RIPEMD160Final $tok]
00749 
00750     } else {
00751 
00752         set tok [RIPEMD160Init]
00753         # FRINK: nocheck
00754         set [subst $tok](reading) 1
00755         fileevent $opts(-channel) readable \
00756             [list [namespace origin Chunk] \
00757                  $tok $opts(-channel) $opts(-chunksize)]
00758         vwait [subst $tok](reading)
00759         set r [RIPEMD160Final $tok]
00760 
00761         # If we opened the channel - we should close it too.
00762         if {$opts(-filename) != {}} {
00763             close $opts(-channel)
00764         }
00765     }
00766     
00767     if {$opts(-hex)} {
00768         set r [Hex $r]
00769     }
00770     return $r
00771 }
00772 
00773 /*  -------------------------------------------------------------------------*/
00774 
00775 ret  ::ripemd::ripemd160::hmac160 (type args) {
00776     array set opts {-hex 0 -filename {} -channel {} -chunksize 4096}
00777     while {[string match -* [set option [lindex $args 0]]]} {
00778         switch -glob -- $option {
00779             -key       { set opts(-key) [Pop args 1] }
00780             -hex       { set opts(-hex) 1 }
00781             -file*     { set opts(-filename) [Pop args 1] }
00782             -channel   { set opts(-channel) [Pop args 1] }
00783             -chunksize { set opts(-chunksize) [Pop args 1] }
00784             default {
00785                 if {[llength $args] == 1} { break }
00786                 if {[string compare $option "--"] == 0} { Pop args; break }
00787                 set err [join [lsort [array names opts]] ", "]
00788                 return -code error "bad option $option:\
00789                     must be one of $err"
00790             }
00791         }
00792         Pop args
00793     }
00794 
00795     if {![info exists opts(-key)]} {
00796         return -code error "wrong # args:\
00797             should be \"hmac160 ?-hex? -key key -filename file | string\""
00798     }
00799 
00800     if {$opts(-filename) != {}} {
00801         set opts(-channel) [open $opts(-filename) r]
00802         fconfigure $opts(-channel) -translation binary
00803     }
00804 
00805     if {$opts(-channel) == {}} {
00806 
00807         if {[llength $args] != 1} {
00808             return -code error "wrong # args:\
00809                 should be \"hmac160 ?-hex? -key key -filename file | string\""
00810         }
00811         set tok [RIPEHMAC160Init $opts(-key)]
00812         RIPEHMAC160Update $tok [lindex $args 0]
00813         set r [RIPEHMAC160Final $tok]
00814 
00815     } else {
00816 
00817         set tok [RIPEHMAC160Init $opts(-key)]
00818         # FRINK: nocheck
00819         set [subst $tok](reading) 1
00820         fileevent $opts(-channel) readable \
00821             [list [namespace origin Chunk] \
00822                  $tok $opts(-channel) $opts(-chunksize)]
00823         vwait [subst $tok](reading)
00824         set r [RIPEHMAC160Final $tok]
00825 
00826         # If we opened the channel - we should close it too.
00827         if {$opts(-filename) != {}} {
00828             close $opts(-channel)
00829         }
00830     }
00831     
00832     if {$opts(-hex)} {
00833         set r [Hex $r]
00834     }
00835     return $r
00836 }
00837 
00838 /*  -------------------------------------------------------------------------*/
00839 
00840 namespace ::ripemd {
00841 
00842     namespace import -force [namespace current]::ripemd160::*
00843 
00844     namespace export ripemd160 hmac160 \
00845         RIPEMD160Init RIPEMD160Update RIPEMD160Final \
00846         RIPEHMAC160Init RIPEHMAC160Update RIPEHMAC160Final
00847 }
00848 
00849 /*  -------------------------------------------------------------------------*/
00850 
00851 /*  Try and load a compiled extension to help.*/
00852 namespace ::ripemd::ripemd160 {
00853     foreach e {cryptkit trf} { if {[LoadAccelerator $e]} { break } }
00854 }
00855 
00856 package provide ripemd160 $::ripemd::ripemd160::version
00857 
00858 /*  -------------------------------------------------------------------------*/
00859 /*  Local Variables:*/
00860 /*    mode: tcl*/
00861 /*    indent-tabs-mode: nil*/
00862 /*  End:*/
00863 
00864 
00865 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1