source: tol/tolsh/tolsh.vfs/lib/tcllib1.10/ripemd/ripemd128.tcl

devel
Last change on this file was 8597867d, checked in by Jorge Pérez <josp.jorge@…>, 16 years ago

closes #976, se incluye tcllib1.10, base64 debe eliminarse del raiz de lib ya que esta incluido en tcllib

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@2556 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 28.1 KB
Line 
1# ripemd128.tcl - Copyright (C) 2003 Pat Thoyts <patthoyts@users.sf.net>
2#
3# This is a Tcl-only implementation of the RIPEMD-128 hash algorithm as
4# described in [RIPE].
5# Included is an implementation of keyed message authentication using
6# the RIPEMD-128 function [HMAC].
7#
8# See http://www.esat.kuleuven.ac.be/~cosicart/pdf/AB-9601/
9#
10# [RIPE] Dobbertin, H., Bosselaers A., and Preneel, B.
11#        "RIPEMD-160: A Strengthened Version of RIPEMD"
12#        Fast Software Encryption, LNCS 1039, D. Gollmann, Ed.,
13#        Springer-Verlag, 1996, pp. 71-82
14# [HMAC] Krawczyk, H., Bellare, M., and R. Canetti,
15#       "HMAC: Keyed-Hashing for Message Authentication",
16#        RFC 2104, February 1997.
17#
18# RFC 2286, ``Test cases for HMAC-RIPEMD160 and HMAC-RIPEMD128,''
19# Internet Request for Comments 2286, J. Kapp,
20#
21# -------------------------------------------------------------------------
22# See the file "license.terms" for information on usage and redistribution
23# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
24# -------------------------------------------------------------------------
25#
26# $Id: ripemd128.tcl,v 1.9 2005/10/17 19:39:52 andreas_kupries Exp $
27
28package require Tcl 8.2;                # tcl minimum version
29
30namespace eval ::ripemd {
31    namespace eval ripemd128 {
32        variable version 1.0.3
33        variable rcsid {$Id: ripemd128.tcl,v 1.9 2005/10/17 19:39:52 andreas_kupries Exp $}
34        variable accel
35        array set accel {trf 0}
36
37        variable uid
38        if {![info exists uid]} {
39            set uid 0
40        }
41
42        namespace export ripemd128 hmac128 Hex \
43            RIPEMD128Init RIPEMD128Update RIPEMD128Final \
44            RIPEHMAC128Init RIPEHMAC128Update RIPEHMAC128Final
45    }
46}
47
48# -------------------------------------------------------------------------
49
50# RIPEMD128Init - create and initialize an MD4 state variable. This will be
51# cleaned up when we call MD4Final
52#
53proc ::ripemd::ripemd128::RIPEMD128Init {} {
54    variable accel
55    variable uid
56    set token [namespace current]::[incr uid]
57    upvar #0 $token state
58
59    # Initialize RIPEMD-128 state structure (same as MD4).
60    array set state \
61        [list \
62             A [expr {0x67452301}] \
63             B [expr {0xefcdab89}] \
64             C [expr {0x98badcfe}] \
65             D [expr {0x10325476}] \
66             n 0 i "" ]
67    if {$accel(trf)} {
68        set s {}
69        switch -exact -- $::tcl_platform(platform) {
70            windows { set s [open NUL w] }
71            unix    { set s [open /dev/null w] }
72        }
73        if {$s != {}} {
74            fconfigure $s -translation binary -buffering none
75            ::ripemd128 -attach $s -mode write \
76                -read-type variable \
77                -read-destination [subst $token](trfread) \
78                -write-type variable \
79                -write-destination [subst $token](trfwrite)
80            array set state [list trfread 0 trfwrite 0 trf $s]
81        }
82    }
83    return $token
84}
85
86proc ::ripemd::ripemd128::RIPEMD128Update {token data} {
87    upvar #0 $token state
88
89    if {[info exists state(trf)]} {
90        puts -nonewline $state(trf) $data
91        return
92    }
93
94    # Update the state values
95    incr state(n) [string length $data]
96    append state(i) $data
97
98    # Calculate the hash for any complete blocks
99    set len [string length $state(i)]
100    for {set n 0} {($n + 64) <= $len} {} {
101        RIPEMD128Hash $token [string range $state(i) $n [incr n 64]]
102    }
103
104    # Adjust the state for the blocks completed.
105    set state(i) [string range $state(i) $n end]
106    return
107}
108
109proc ::ripemd::ripemd128::RIPEMD128Final {token} {
110    upvar #0 $token state
111
112    if {[info exists state(trf)]} {
113        close $state(trf)
114        set r $state(trfwrite)
115        unset state
116        return $r
117    }
118
119    # RFC1320:3.1 - Padding
120    #
121    set len [string length $state(i)]
122    set pad [expr {56 - ($len % 64)}]
123    if {$len % 64 > 56} {
124        incr pad 64
125    }
126    if {$pad == 0} {
127        incr pad 64
128    }
129    append state(i) [binary format a$pad \x80]
130
131    # RFC1320:3.2 - Append length in bits as little-endian wide int.
132    append state(i) [binary format ii [expr {8 * $state(n)}] 0]
133
134    # Calculate the hash for the remaining block.
135    set len [string length $state(i)]
136    for {set n 0} {($n + 64) <= $len} {} {
137        RIPEMD128Hash $token [string range $state(i) $n [incr n 64]]
138    }
139
140    # RFC1320:3.5 - Output
141    set r [bytes $state(A)][bytes $state(B)][bytes $state(C)][bytes $state(D)]
142    unset state
143    return $r
144}
145
146# -------------------------------------------------------------------------
147# HMAC Hashed Message Authentication (RFC 2104)
148#
149# hmac = H(K xor opad, H(K xor ipad, text))
150#
151proc ::ripemd::ripemd128::RIPEHMAC128Init {K} {
152
153    # Key K is adjusted to be 64 bytes long. If K is larger, then use
154    # the RIPEMD-128 digest of K and pad this instead.
155    set len [string length $K]
156    if {$len > 64} {
157        set tok [RIPEMD128Init]
158        RIPEMD128Update $tok $K
159        set K [RIPEMD128Final $tok]
160        set len [string length $K]
161    }
162    set pad [expr {64 - $len}]
163    append K [string repeat \0 $pad]
164
165    # Cacluate the padding buffers.
166    set Ki {}
167    set Ko {}
168    binary scan $K i16 Ks
169    foreach k $Ks {
170        append Ki [binary format i [expr {$k ^ 0x36363636}]]
171        append Ko [binary format i [expr {$k ^ 0x5c5c5c5c}]]
172    }
173
174    set tok [RIPEMD128Init]
175    RIPEMD128Update $tok $Ki;                 # initialize with the inner pad
176   
177    # preserve the Ko value for the final stage.
178    # FRINK: nocheck
179    set [subst $tok](Ko) $Ko
180
181    return $tok
182}
183
184proc ::ripemd::ripemd128::RIPEHMAC128Update {token data} {
185    RIPEMD128Update $token $data
186    return
187}
188
189proc ::ripemd::ripemd128::RIPEHMAC128Final {token} {
190    # FRINK: nocheck
191    variable $token
192    upvar 0 $token state
193
194    set tok [RIPEMD128Init];            # init the outer hashing function
195    RIPEMD128Update $tok $state(Ko);    # prepare with the outer pad.
196    RIPEMD128Update $tok [RIPEMD128Final $token];  # hash the inner result
197    return [RIPEMD128Final $tok]
198}
199
200# -------------------------------------------------------------------------
201
202set ::ripemd::ripemd128::RIPEMD128Hash_body {
203    variable $token
204    upvar 0 $token state
205
206    # RFC1320:3.4 - Process Message in 16-Word Blocks
207    binary scan $msg i* blocks
208    foreach {X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15} $blocks {
209        set A $state(A)   ;  set AA $state(A)
210        set B $state(B)   ;  set BB $state(B)
211        set C $state(C)   ;  set CC $state(C)
212        set D $state(D)   ;  set DD $state(D)
213
214        # Round 1 (track 1).
215        #    F(x,y,z) = x ^ y ^ z
216        # Let [abcd x s] denote the operation
217        #    a = (a + F(b,c,d) + X[x]) <<< s.
218        # Do the following 16 operations.
219        # [ABCD  0  11]  [DABC  1  14]  [CDAB  2 15]  [BCDA  3 12]
220        set A [expr {($A + [F $B $C $D] + $X0)  <<< 11}]
221        set D [expr {($D + [F $A $B $C] + $X1)  <<< 14}]
222        set C [expr {($C + [F $D $A $B] + $X2)  <<< 15}]
223        set B [expr {($B + [F $C $D $A] + $X3)  <<< 12}]
224        # [ABCD  4  5]  [DABC  5  8]  [CDAB  6 7]  [BCDA  7 9]
225        set A [expr {($A + [F $B $C $D] + $X4)  <<< 5}]
226        set D [expr {($D + [F $A $B $C] + $X5)  <<< 8}]
227        set C [expr {($C + [F $D $A $B] + $X6)  <<< 7}]
228        set B [expr {($B + [F $C $D $A] + $X7)  <<< 9}]
229        # [ABCD  8  11]  [DABC  9  13]  [CDAB 10 14]  [BCDA 11 15]
230        set A [expr {($A + [F $B $C $D] + $X8)  <<< 11}]
231        set D [expr {($D + [F $A $B $C] + $X9)  <<< 13}]
232        set C [expr {($C + [F $D $A $B] + $X10) <<< 14}]
233        set B [expr {($B + [F $C $D $A] + $X11) <<< 15}]
234        # [ABCD 12  6]  [DABC 13  7]  [CDAB 14 9]  [BCDA 15 8]
235        set A [expr {($A + [F $B $C $D] + $X12) <<< 6}]
236        set D [expr {($D + [F $A $B $C] + $X13) <<< 7}]
237        set C [expr {($C + [F $D $A $B] + $X14) <<< 9}]
238        set B [expr {($B + [F $C $D $A] + $X15) <<< 8}]
239
240        # Round 2 (track 1).
241        #   G(x, y, z) = (x & y) | (~x & z)
242        # Let [abcd k s] denote the operation
243        #   a = (a + G(b,c,d) + X[k] + 5A827999) <<< s
244        # Do the following 16 operations.
245        # [ABCD  7  7]  [DABC  4  6]  [CDAB  13  8]  [BCDA 1 13]
246        set A [expr {($A + [G $B $C $D] + $X7  + 0x5a827999) <<< 7}]
247        set D [expr {($D + [G $A $B $C] + $X4  + 0x5a827999) <<< 6}]
248        set C [expr {($C + [G $D $A $B] + $X13 + 0x5a827999) <<< 8}]
249        set B [expr {($B + [G $C $D $A] + $X1  + 0x5a827999) <<< 13}]
250        # [ABCD  10  11]  [DABC  6  9]  [CDAB  15  7]  [BCDA 3 15]
251        set A [expr {($A + [G $B $C $D] + $X10 + 0x5a827999) <<< 11}]
252        set D [expr {($D + [G $A $B $C] + $X6  + 0x5a827999) <<< 9}]
253        set C [expr {($C + [G $D $A $B] + $X15 + 0x5a827999) <<< 7}]
254        set B [expr {($B + [G $C $D $A] + $X3  + 0x5a827999) <<< 15}]
255        # [ABCD 12  7]  [DABC  0  12]  [CDAB 9  15]  [BCDA 5 9]
256        set A [expr {($A + [G $B $C $D] + $X12 + 0x5a827999) <<< 7}]
257        set D [expr {($D + [G $A $B $C] + $X0  + 0x5a827999) <<< 12}]
258        set C [expr {($C + [G $D $A $B] + $X9  + 0x5a827999) <<< 15}]
259        set B [expr {($B + [G $C $D $A] + $X5  + 0x5a827999) <<< 9}]
260        # [ABCD  2  11]  [DABC  14  7]  [CDAB 11  13]  [BCDA 8 12]
261        set A [expr {($A + [G $B $C $D] + $X2  + 0x5a827999) <<< 11}]
262        set D [expr {($D + [G $A $B $C] + $X14 + 0x5a827999) <<< 7}]
263        set C [expr {($C + [G $D $A $B] + $X11 + 0x5a827999) <<< 13}]
264        set B [expr {($B + [G $C $D $A] + $X8  + 0x5a827999) <<< 12}]
265       
266        # Round 3 (track 1).
267        #   H(x,y,z) = (x | ~y) ^ z
268        # Let [abcd k s] denote the operation
269        #   a = (a + H(b,c,d) + X[k] + 6ED9EBA1) <<< s.
270        # Do the following 16 operations.
271        # [ABCD  3  11]  [DABC  10  13]  [CDAB  14 6]  [BCDA 4 7]
272        set A [expr {($A + [H $B $C $D] + $X3  + 0x6ed9eba1) <<< 11}]
273        set D [expr {($D + [H $A $B $C] + $X10 + 0x6ed9eba1) <<< 13}]
274        set C [expr {($C + [H $D $A $B] + $X14 + 0x6ed9eba1) <<< 6}]
275        set B [expr {($B + [H $C $D $A] + $X4  + 0x6ed9eba1) <<< 7}]
276        # [ABCD  9  14]  [DABC 15  9]  [CDAB  8 13]  [BCDA 1 15]
277        set A [expr {($A + [H $B $C $D] + $X9  + 0x6ed9eba1) <<< 14}]
278        set D [expr {($D + [H $A $B $C] + $X15 + 0x6ed9eba1) <<< 9}]
279        set C [expr {($C + [H $D $A $B] + $X8  + 0x6ed9eba1) <<< 13}]
280        set B [expr {($B + [H $C $D $A] + $X1  + 0x6ed9eba1) <<< 15}]
281        # [ABCD  2  14]  [DABC  7  8]  [CDAB  0 13]  [BCDA 6 6]
282        set A [expr {($A + [H $B $C $D] + $X2  + 0x6ed9eba1) <<< 14}]
283        set D [expr {($D + [H $A $B $C] + $X7  + 0x6ed9eba1) <<< 8}]
284        set C [expr {($C + [H $D $A $B] + $X0  + 0x6ed9eba1) <<< 13}]
285        set B [expr {($B + [H $C $D $A] + $X6  + 0x6ed9eba1) <<< 6}]
286        # [ABCD  13  5]  [DABC 11  12]  [CDAB  5 7]  [BCDA 12  5]
287        set A [expr {($A + [H $B $C $D] + $X13 + 0x6ed9eba1) <<< 5}]
288        set D [expr {($D + [H $A $B $C] + $X11 + 0x6ed9eba1) <<< 12}]
289        set C [expr {($C + [H $D $A $B] + $X5  + 0x6ed9eba1) <<< 7}]
290        set B [expr {($B + [H $C $D $A] + $X12 + 0x6ed9eba1) <<< 5}]
291
292        # Round 4 (track 1).
293        #   I(x,y,z) = (x & z) | (y & ^ ~z)
294        # Let [abcd k s] denote the operation
295        #   a = (a + I(b,c,d) + X[k] + 8F1BBCDC) <<< s.
296        # Do the following 16 operations.
297        # [ABCD  1  11]  [DABC  9  12]  [CDAB  11 14]  [BCDA 10 15]
298        set A [expr {($A + [I $B $C $D] + $X1  + 0x8f1bbcdc) <<< 11}]
299        set D [expr {($D + [I $A $B $C] + $X9  + 0x8f1bbcdc) <<< 12}]
300        set C [expr {($C + [I $D $A $B] + $X11 + 0x8f1bbcdc) <<< 14}]
301        set B [expr {($B + [I $C $D $A] + $X10 + 0x8f1bbcdc) <<< 15}]
302        # [ABCD  0  14]  [DABC 8  15]  [CDAB 12 9]  [BCDA 4 8]
303        set A [expr {($A + [I $B $C $D] + $X0  + 0x8f1bbcdc) <<< 14}]
304        set D [expr {($D + [I $A $B $C] + $X8  + 0x8f1bbcdc) <<< 15}]
305        set C [expr {($C + [I $D $A $B] + $X12 + 0x8f1bbcdc) <<< 9}]
306        set B [expr {($B + [I $C $D $A] + $X4  + 0x8f1bbcdc) <<< 8}]
307        # [ABCD  13  9]  [DABC  3  14]  [CDAB  7 5]  [BCDA 15 6]
308        set A [expr {($A + [I $B $C $D] + $X13 + 0x8f1bbcdc) <<< 9}]
309        set D [expr {($D + [I $A $B $C] + $X3  + 0x8f1bbcdc) <<< 14}]
310        set C [expr {($C + [I $D $A $B] + $X7  + 0x8f1bbcdc) <<< 5}]
311        set B [expr {($B + [I $C $D $A] + $X15 + 0x8f1bbcdc) <<< 6}]
312        # [ABCD  14  8]  [DABC 5  6]  [CDAB  6 5]  [BCDA 2 12]
313        set A [expr {($A + [I $B $C $D] + $X14 + 0x8f1bbcdc) <<< 8}]
314        set D [expr {($D + [I $A $B $C] + $X5  + 0x8f1bbcdc) <<< 6}]
315        set C [expr {($C + [I $D $A $B] + $X6  + 0x8f1bbcdc) <<< 5}]
316        set B [expr {($B + [I $C $D $A] + $X2  + 0x8f1bbcdc) <<< 12}]
317
318
319        # Round 1 (track 2).
320        #   I(x,y,z) = (x & z) | (y & ^ ~z)
321        # Let [abcd k s] denote the operation
322        #   a = (a + I(b,c,d) + X[k] + 50A28BE6) <<< s.
323        # Do the following 16 operations.
324        # [ABCD  5  8]  [DABC  14  9]  [CDAB  7 9]  [BCDA 0 11]
325        set AA [expr {($AA + [I $BB $CC $DD] + $X5  + 0x50a28be6) <<< 8}]
326        set DD [expr {($DD + [I $AA $BB $CC] + $X14 + 0x50a28be6) <<< 9}]
327        set CC [expr {($CC + [I $DD $AA $BB] + $X7  + 0x50a28be6) <<< 9}]
328        set BB [expr {($BB + [I $CC $DD $AA] + $X0  + 0x50a28be6) <<< 11}]
329        # [ABCD  9  13]  [DABC 2  15]  [CDAB 11 15]  [BCDA 4 5]
330        set AA [expr {($AA + [I $BB $CC $DD] + $X9  + 0x50a28be6) <<< 13}]
331        set DD [expr {($DD + [I $AA $BB $CC] + $X2  + 0x50a28be6) <<< 15}]
332        set CC [expr {($CC + [I $DD $AA $BB] + $X11 + 0x50a28be6) <<< 15}]
333        set BB [expr {($BB + [I $CC $DD $AA] + $X4  + 0x50a28be6) <<< 5}]
334        # [ABCD  13  7]  [DABC  6  7]  [CDAB  15 8]  [BCDA 8 11]
335        set AA [expr {($AA + [I $BB $CC $DD] + $X13 + 0x50a28be6) <<< 7}]
336        set DD [expr {($DD + [I $AA $BB $CC] + $X6  + 0x50a28be6) <<< 7}]
337        set CC [expr {($CC + [I $DD $AA $BB] + $X15 + 0x50a28be6) <<< 8}]
338        set BB [expr {($BB + [I $CC $DD $AA] + $X8  + 0x50a28be6) <<< 11}]
339        # [ABCD  1  14]  [DABC 10  14]  [CDAB  3 12]  [BCDA 12 6]
340        set AA [expr {($AA + [I $BB $CC $DD] + $X1  + 0x50a28be6) <<< 14}]
341        set DD [expr {($DD + [I $AA $BB $CC] + $X10 + 0x50a28be6) <<< 14}]
342        set CC [expr {($CC + [I $DD $AA $BB] + $X3  + 0x50a28be6) <<< 12}]
343        set BB [expr {($BB + [I $CC $DD $AA] + $X12 + 0x50a28be6) <<< 6}]
344
345        # Round 2 (track 2).
346        #   H(x,y,z) = (x | ~y) ^ z
347        # Let [abcd k s] denote the operation
348        #   a = (a + H(b,c,d) + X[k] + 5C4DD124) <<< s.
349        # Do the following 16 operations.
350        # [ABCD  6  9]  [DABC  11  13]  [CDAB  3 15]  [BCDA 7 7]
351        set AA [expr {($AA + [H $BB $CC $DD] + $X6  + 0x5c4dd124) <<< 9}]
352        set DD [expr {($DD + [H $AA $BB $CC] + $X11 + 0x5c4dd124) <<< 13}]
353        set CC [expr {($CC + [H $DD $AA $BB] + $X3  + 0x5c4dd124) <<< 15}]
354        set BB [expr {($BB + [H $CC $DD $AA] + $X7  + 0x5c4dd124) <<< 7}]
355        # [ABCD  0  12]  [DABC 13  8]  [CDAB 5 9]  [BCDA 10 11]
356        set AA [expr {($AA + [H $BB $CC $DD] + $X0  + 0x5c4dd124) <<< 12}]
357        set DD [expr {($DD + [H $AA $BB $CC] + $X13 + 0x5c4dd124) <<< 8}]
358        set CC [expr {($CC + [H $DD $AA $BB] + $X5  + 0x5c4dd124) <<< 9}]
359        set BB [expr {($BB + [H $CC $DD $AA] + $X10 + 0x5c4dd124) <<< 11}]
360        # [ABCD  14  7]  [DABC  15  7]  [CDAB  8 12]  [BCDA 12 7]
361        set AA [expr {($AA + [H $BB $CC $DD] + $X14 + 0x5c4dd124) <<< 7}]
362        set DD [expr {($DD + [H $AA $BB $CC] + $X15 + 0x5c4dd124) <<< 7}]
363        set CC [expr {($CC + [H $DD $AA $BB] + $X8  + 0x5c4dd124) <<< 12}]
364        set BB [expr {($BB + [H $CC $DD $AA] + $X12 + 0x5c4dd124) <<< 7}]
365        # [ABCD  4  6]  [DABC 9  15]  [CDAB  1 13]  [BCDA 2 11]
366        set AA [expr {($AA + [H $BB $CC $DD] + $X4  + 0x5c4dd124) <<< 6}]
367        set DD [expr {($DD + [H $AA $BB $CC] + $X9  + 0x5c4dd124) <<< 15}]
368        set CC [expr {($CC + [H $DD $AA $BB] + $X1  + 0x5c4dd124) <<< 13}]
369        set BB [expr {($BB + [H $CC $DD $AA] + $X2  + 0x5c4dd124) <<< 11}]
370
371        # Round 3 (track 2).
372        #   G(x, y, z) = (x & y) | (~x & z)
373        # Let [abcd k s] denote the operation
374        #   a = (a + G(b,c,d) + X[k] + 6D703EF3) <<< s.
375        # Do the following 16 operations.
376        # [ABCD  15  9]  [DABC  5 7]  [CDAB  1 15]  [BCDA 3 11]
377        set AA [expr {($AA + [G $BB $CC $DD] + $X15 + 0x6d703ef3) <<< 9}]
378        set DD [expr {($DD + [G $AA $BB $CC] + $X5  + 0x6d703ef3) <<< 7}]
379        set CC [expr {($CC + [G $DD $AA $BB] + $X1  + 0x6d703ef3) <<< 15}]
380        set BB [expr {($BB + [G $CC $DD $AA] + $X3  + 0x6d703ef3) <<< 11}]
381        # [ABCD  7  8]  [DABC 14  6]  [CDAB 6 6]  [BCDA 9 14]
382        set AA [expr {($AA + [G $BB $CC $DD] + $X7  + 0x6d703ef3) <<< 8}]
383        set DD [expr {($DD + [G $AA $BB $CC] + $X14 + 0x6d703ef3) <<< 6}]
384        set CC [expr {($CC + [G $DD $AA $BB] + $X6  + 0x6d703ef3) <<< 6}]
385        set BB [expr {($BB + [G $CC $DD $AA] + $X9  + 0x6d703ef3) <<< 14}]
386        # [ABCD  11  12]  [DABC  8  13]  [CDAB  12 5]  [BCDA 2 14]
387        set AA [expr {($AA + [G $BB $CC $DD] + $X11 + 0x6d703ef3) <<< 12}]
388        set DD [expr {($DD + [G $AA $BB $CC] + $X8  + 0x6d703ef3) <<< 13}]
389        set CC [expr {($CC + [G $DD $AA $BB] + $X12 + 0x6d703ef3) <<< 5}]
390        set BB [expr {($BB + [G $CC $DD $AA] + $X2  + 0x6d703ef3) <<< 14}]
391        # [ABCD  10  13]  [DABC 0  13]  [CDAB  4 7]  [BCDA 13 5]
392        set AA [expr {($AA + [G $BB $CC $DD] + $X10 + 0x6d703ef3) <<< 13}]
393        set DD [expr {($DD + [G $AA $BB $CC] + $X0  + 0x6d703ef3) <<< 13}]
394        set CC [expr {($CC + [G $DD $AA $BB] + $X4  + 0x6d703ef3) <<< 7}]
395        set BB [expr {($BB + [G $CC $DD $AA] + $X13 + 0x6d703ef3) <<< 5}]
396
397        # Round 4 (track 2).
398        #   F(x,y,z) = x ^ y ^ z
399        # Let [abcd k s] denote the operation
400        #   a = (a + F(b,c,d) + X[k]) <<< s.
401        # Do the following 16 operations.
402        # [ABCD  8  15]  [DABC  6 5]  [CDAB  4 8]  [BCDA 1 11]
403        set AA [expr {($AA + [F $BB $CC $DD] + $X8)  <<< 15}]
404        set DD [expr {($DD + [F $AA $BB $CC] + $X6)  <<< 5}]
405        set CC [expr {($CC + [F $DD $AA $BB] + $X4)  <<< 8}]
406        set BB [expr {($BB + [F $CC $DD $AA] + $X1)  <<< 11}]
407        # [ABCD  3  14]  [DABC 11 14]  [CDAB 15 6]  [BCDA 0 14]
408        set AA [expr {($AA + [F $BB $CC $DD] + $X3)  <<< 14}]
409        set DD [expr {($DD + [F $AA $BB $CC] + $X11) <<< 14}]
410        set CC [expr {($CC + [F $DD $AA $BB] + $X15) <<< 6}]
411        set BB [expr {($BB + [F $CC $DD $AA] + $X0)  <<< 14}]
412        # [ABCD  5  6]  [DABC  12 9]  [CDAB  2 12]  [BCDA 13 9]
413        set AA [expr {($AA + [F $BB $CC $DD] + $X5)  <<< 6}]
414        set DD [expr {($DD + [F $AA $BB $CC] + $X12) <<< 9}]
415        set CC [expr {($CC + [F $DD $AA $BB] + $X2)  <<< 12}]
416        set BB [expr {($BB + [F $CC $DD $AA] + $X13) <<< 9}]
417        # [ABCD  9  12]  [DABC 7  5]  [CDAB  10 15]  [BCDA 14 8]
418        set AA [expr {($AA + [F $BB $CC $DD] + $X9)  <<< 12}]
419        set DD [expr {($DD + [F $AA $BB $CC] + $X7)  <<< 5}]
420        set CC [expr {($CC + [F $DD $AA $BB] + $X10) <<< 15}]
421        set BB [expr {($BB + [F $CC $DD $AA] + $X14) <<< 8}]
422
423        # Then perform the following additions to combine the results.
424        set DD       [expr {$state(B) + $C + $DD}]
425        set state(B) [expr {$state(C) + $D + $AA}]
426        set state(C) [expr {$state(D) + $A + $BB}]
427        set state(D) [expr {$state(A) + $B + $CC}]
428        set state(A) $DD
429    }
430
431    return
432}
433
434proc ::ripemd::ripemd128::byte {n v} {expr {((0xFF << (8 * $n)) & $v) >> (8 * $n)}}
435proc ::ripemd::ripemd128::bytes {v} {
436    #format %c%c%c%c [byte 0 $v] [byte 1 $v] [byte 2 $v] [byte 3 $v]
437    format %c%c%c%c \
438        [expr {0xFF & $v}] \
439        [expr {(0xFF00 & $v) >> 8}] \
440        [expr {(0xFF0000 & $v) >> 16}] \
441        [expr {((0xFF000000 & $v) >> 24) & 0xFF}]
442}
443
444# 32bit rotate-left
445proc ::ripemd::ripemd128::<<< {v n} {
446    return [expr {((($v << $n) \
447                        | (($v >> (32 - $n)) \
448                               & (0x7FFFFFFF >> (31 - $n))))) \
449                      & 0xFFFFFFFF}]
450}
451
452# Convert our <<< pseudo-operator into a procedure call.
453regsub -all -line \
454    {\[expr {(.*) <<< (\d+)}\]} \
455    $::ripemd::ripemd128::RIPEMD128Hash_body \
456    {[<<< [expr {\1}] \2]} \
457    ::ripemd::ripemd128::RIPEMD128Hash_body
458
459#  F(x,y,z) = x ^ y ^ z
460proc ::ripemd::ripemd128::F {X Y Z} {
461    return [expr {$X ^ $Y ^ $Z}]
462}
463# Inline the F function F
464regsub -all -line \
465    {\[F (\$[ABCD]{1,2}) (\$[ABCD]{1,2}) (\$[ABCD]{1,2})\]} \
466    $::ripemd::ripemd128::RIPEMD128Hash_body \
467    {(\1 ^ \2 ^ \3)} \
468    ::ripemd::ripemd128::RIPEMD128Hash_body
469   
470# G(x,y,z) = (x & y) | (~x & z)
471proc ::ripemd::ripemd128::G {X Y Z} {
472    return [expr {($X & $Y) | (~$X & $Z)}]
473}
474# Inline the G function
475regsub -all -line \
476    {\[G (\$[ABCD]{1,2}) (\$[ABCD]{1,2}) (\$[ABCD]{1,2})\]} \
477    $::ripemd::ripemd128::RIPEMD128Hash_body \
478    {((\1 \& \2) | (~\1 \& \3))} \
479    ::ripemd::ripemd128::RIPEMD128Hash_body
480
481# H(x,y,z) = (x | ~y) ^ z
482proc ::ripemd::ripemd128::H {X Y Z} {
483    return [expr {($X | ~$Y) ^ $Z}]
484}
485# Inline the H function
486regsub -all -line \
487    {\[H (\$[ABCD]{1,2}) (\$[ABCD]{1,2}) (\$[ABCD]{1,2})\]} \
488    $::ripemd::ripemd128::RIPEMD128Hash_body \
489    {( (\1 | ~\2) ^ \3)} \
490    ::ripemd::ripemd128::RIPEMD128Hash_body
491
492# I(x,y,z) = (x & z) | (y & ~z)
493proc ::ripemd::ripemd128::I {X Y Z} {
494    return [expr {($X & $Z) | ($Y & ~$Z)}]
495}
496# Inline the I function
497regsub -all -line \
498    {\[I (\$[ABCD]{1,2}) (\$[ABCD]{1,2}) (\$[ABCD]{1,2})\]} \
499    $::ripemd::ripemd128::RIPEMD128Hash_body \
500    {( (\1 \& \3) | (\2 \& ~\3) )} \
501    ::ripemd::ripemd128::RIPEMD128Hash_body
502
503# Define the MD4 hashing procedure with inline functions.
504proc ::ripemd::ripemd128::RIPEMD128Hash {token msg} $::ripemd::ripemd128::RIPEMD128Hash_body
505
506# -------------------------------------------------------------------------
507
508proc ::ripemd::ripemd128::Hex {data} {
509    binary scan $data H* result
510    return $result
511}
512
513# -------------------------------------------------------------------------
514
515# LoadAccelerator --
516#
517#       This package can make use of a number of compiled extensions to
518#       accelerate the digest computation. This procedure manages the
519#       use of these extensions within the package. During normal usage
520#       this should not be called, but the test package manipulates the
521#       list of enabled accelerators.
522#
523proc ::ripemd::ripemd128::LoadAccelerator {name} {
524    variable accel
525    set r 0
526    switch -exact -- $name {
527        #critcl {
528        #    if {![catch {package require tcllibc}]
529        #        || ![catch {package require sha1c}]} {
530        #        set r [expr {[info command ::sha1::sha1c] != {}}]
531        #    }
532        #}
533        #cryptkit {
534        #    if {![catch {package require cryptkit}]} {
535        #        set r [expr {![catch {cryptkit::cryptInit}]}]
536        #    }
537        #}
538        trf {
539            if {![catch {package require Trf}]} {
540                set r [expr {![catch {::ripemd128 aa} msg]}]
541            }
542        }
543        default {
544            return -code error "invalid accelerator package:\
545                must be one of [join [array names accel] {, }]"
546        }
547    }
548    set accel($name) $r
549}
550
551# -------------------------------------------------------------------------
552
553# Description:
554#  Pop the nth element off a list. Used in options processing.
555#
556proc ::ripemd::ripemd128::Pop {varname {nth 0}} {
557    upvar $varname args
558    set r [lindex $args $nth]
559    set args [lreplace $args $nth $nth]
560    return $r
561}
562
563# -------------------------------------------------------------------------
564
565# fileevent handler for chunked file hashing.
566#
567proc ::ripemd::ripemd128::Chunk {token channel {chunksize 4096}} {
568    # FRINK: nocheck
569    variable $token
570    upvar 0 $token state
571   
572    if {[eof $channel]} {
573        fileevent $channel readable {}
574        set state(reading) 0
575    }
576       
577    RIPEMD128Update $token [read $channel $chunksize]
578}
579
580# -------------------------------------------------------------------------
581
582proc ::ripemd::ripemd128::ripemd128 {args} {
583    array set opts {-hex 0 -filename {} -channel {} -chunksize 4096}
584    while {[string match -* [set option [lindex $args 0]]]} {
585        switch -glob -- $option {
586            -hex       { set opts(-hex) 1 }
587            -file*     { set opts(-filename) [Pop args 1] }
588            -channel   { set opts(-channel) [Pop args 1] }
589            -chunksize { set opts(-chunksize) [Pop args 1] }
590            default {
591                if {[llength $args] == 1} { break }
592                if {[string compare $option "--"] == 0} { Pop args; break }
593                set err [join [lsort [array names opts]] ", "]
594                return -code error "bad option $option:\
595                    must be one of $err"
596            }
597        }
598        Pop args
599    }
600   
601    if {$opts(-filename) != {}} {
602        set opts(-channel) [open $opts(-filename) r]
603        fconfigure $opts(-channel) -translation binary
604    }
605
606    if {$opts(-channel) == {}} {
607
608        if {[llength $args] != 1} {
609            return -code error "wrong # args:\
610                should be \"ripemd128 ?-hex? -filename file | string\""
611        }
612        set tok [RIPEMD128Init]
613        RIPEMD128Update $tok [lindex $args 0]
614        set r [RIPEMD128Final $tok]
615
616    } else {
617
618        set tok [RIPEMD128Init]
619        # FRINK: nocheck
620        set [subst $tok](reading) 1
621        fileevent $opts(-channel) readable \
622            [list [namespace origin Chunk] \
623                 $tok $opts(-channel) $opts(-chunksize)]
624        vwait [subst $tok](reading)
625        set r [RIPEMD128Final $tok]
626
627        # If we opened the channel - we should close it too.
628        if {$opts(-filename) != {}} {
629            close $opts(-channel)
630        }
631    }
632   
633    if {$opts(-hex)} {
634        set r [Hex $r]
635    }
636    return $r
637}
638
639# -------------------------------------------------------------------------
640
641proc ::ripemd::ripemd128::hmac128 {args} {
642    array set opts {-hex 0 -filename {} -channel {} -chunksize 4096}
643    while {[string match -* [set option [lindex $args 0]]]} {
644        switch -glob -- $option {
645            -key       { set opts(-key) [Pop args 1] }
646            -hex       { set opts(-hex) 1 }
647            -file*     { set opts(-filename) [Pop args 1] }
648            -channel   { set opts(-channel) [Pop args 1] }
649            -chunksize { set opts(-chunksize) [Pop args 1] }
650            default {
651                if {[llength $args] == 1} { break }
652                if {[string compare $option "--"] == 0} { Pop args; break }
653                set err [join [lsort [array names opts]] ", "]
654                return -code error "bad option $option:\
655                    must be one of $err"
656            }
657        }
658        Pop args
659    }
660
661    if {![info exists opts(-key)]} {
662        return -code error "wrong # args:\
663            should be \"hmac128 ?-hex? -key key -filename file | string\""
664    }
665
666    if {$opts(-filename) != {}} {
667        set opts(-channel) [open $opts(-filename) r]
668        fconfigure $opts(-channel) -translation binary
669    }
670
671    if {$opts(-channel) == {}} {
672
673        if {[llength $args] != 1} {
674            return -code error "wrong # args:\
675                should be \"hmac128 ?-hex? -key key -filename file | string\""
676        }
677        set tok [RIPEHMAC128Init $opts(-key)]
678        RIPEHMAC128Update $tok [lindex $args 0]
679        set r [RIPEHMAC128Final $tok]
680
681    } else {
682
683        set tok [RIPEHMAC128Init $opts(-key)]
684        # FRINK: nocheck
685        set [subst $tok](reading) 1
686        fileevent $opts(-channel) readable \
687            [list [namespace origin Chunk] \
688                 $tok $opts(-channel) $opts(-chunksize)]
689        vwait [subst $tok](reading)
690        set r [RIPEHMAC128Final $tok]
691
692        # If we opened the channel - we should close it too.
693        if {$opts(-filename) != {}} {
694            close $opts(-channel)
695        }
696    }
697   
698    if {$opts(-hex)} {
699        set r [Hex $r]
700    }
701    return $r
702}
703
704# -------------------------------------------------------------------------
705
706namespace eval ::ripemd {
707
708    namespace import -force [namespace current]::ripemd128::*
709
710    namespace export ripemd128 hmac128 \
711        RIPEMD128Init RIPEMD128Update RIPEMD128Final \
712        RIPEHMAC128Init RIPEHMAC128Update RIPEHMAC128Final
713}
714
715# -------------------------------------------------------------------------
716
717# Try and load a compiled extension to help.
718namespace eval ::ripemd::ripemd128 {
719    foreach e {trf} { if {[LoadAccelerator $e]} { break } }
720}
721
722package provide ripemd128 $::ripemd::ripemd128::version
723
724# -------------------------------------------------------------------------
725# Local Variables:
726#   mode: tcl
727#   indent-tabs-mode: nil
728# End:
729
730
Note: See TracBrowser for help on using the repository browser.