From VisualWorks®, 7.6 of February 1, 2008 on February 1, 2008 at 12:31:26 pm (Dialog confirm: 'You are filing-in a Parcel source file!\\While this is possible it will not have\the same effect as loading the parcel.\None of the Parcel''s prerequisites will\be loaded and none of its load actions\will be performed.\\Are you sure you want to file-in?' withCRs) ifFalse: [self error: 'Parcel file-in abandoned. Choose terminate or close.'] <class> <name>MD5</name> <environment>Security</environment> <super>Security.Hash</super> <private>false</private> none a b c d aa bb cc dd f ff m <imports></imports> <category>Security-Hashes</category> <attributes> <package>MD5</package> </attributes> </class> <comment> Security.MD5
This implements the MD5 hashing algorithm, RFC1321 (http://www.ietf.org/rfc/rfc1321.txt). Less formal description can be also found in Bruce Schneier's "Applied Cryptography", Section 18.5. Instance variable naming follows the convention in the specification. Instance Variables: a <ThirtyTwoBitRegister> working register b <ThirtyTwoBitRegister> working register c <ThirtyTwoBitRegister> working register d <ThirtyTwoBitRegister> working register aa <ThirtyTwoBitRegister> backup register bb <ThirtyTwoBitRegister> backup register cc <ThirtyTwoBitRegister> backup register dd <ThirtyTwoBitRegister> backup register f <ThirtyTwoBitRegister> scratch register ff <ThirtyTwoBitRegister> scratch register m <Array of: ThirtyTwoBitRegister> 16 registers for current message block Shared Class Variables: T <Array of: ThirtyTwoBitRegister> array of constants T as described by the standard
</comment> <name>T</name> <environment>Security.MD5</environment> <private>false</private> <constant>false</constant> <category>constants</category> <initializer>MD5 computeSinTable</initializer> <attributes> <package>MD5</package> </attributes> <methods> Security.MD5 <category>private-algorithm</category>
a: aw b: bw f: fw M: mw s: s t: t "a = b + ((a + F(b,c,d) + m + t) <<< s)" aw += fw; += mw; += t; leftRotateBy: s; += bw
FFa: aw b: bw c: cw d: dw M: mw s: s t: t "F(b,c,d)=(b and c) or ((not b) and d)" ff set: bw; bitInvert; bitAnd: dw. f set: bw; bitAnd: cw; bitOr: ff. self a: aw b: bw f: f M: mw s: s t: t
GGa: aw b: bw c: cw d: dw M: mw s: s t: t "G(b,c,d)=(b and d) or ((not d) and c)" ff set: dw; bitInvert; bitAnd: cw. f set: bw; bitAnd: dw; bitOr: ff. self a: aw b: bw f: f M: mw s: s t: t
HHa: aw b: bw c: cw d: dw M: mw s: s t: t "H(b,c,d) = b xor c xor d" f set: bw; bitXor: cw; bitXor: dw. self a: aw b: bw f: f M: mw s: s t: t
IIa: aw b: bw c: cw d: dw M: mw s: s t: t "I(b,c,d) = c xor (b or (not d))" f set: dw; bitInvert; bitOr: bw; bitXor: cw. self a: aw b: bw f: f M: mw s: s t: t
processBlock "backup the working registers" aa set: a. bb set: b. cc set: c. dd set: d. self readBlock; round1; round2; round3; round4. "add the previous values into the working registers" a addIn: aa. b addIn: bb. c addIn: cc. d addIn: dd
readBlock "read in the message block" 1 to: 16 do: [:i | (m at: i) reverseLoadFrom: block at: (i - 1) * 4 + 1 ].
round1 self FFa: a b: b c: c d: d M: (m at: 1) s: 7 t: (T at: 1); FFa: d b: a c: b d: c M: (m at: 2) s: 12 t: (T at: 2); FFa: c b: d c: a d: b M: (m at: 3) s: 17 t: (T at: 3); FFa: b b: c c: d d: a M: (m at: 4) s: 22 t: (T at: 4); FFa: a b: b c: c d: d M: (m at: 5) s: 7 t: (T at: 5); FFa: d b: a c: b d: c M: (m at: 6) s: 12 t: (T at: 6); FFa: c b: d c: a d: b M: (m at: 7) s: 17 t: (T at: 7); FFa: b b: c c: d d: a M: (m at: 8) s: 22 t: (T at: 8); FFa: a b: b c: c d: d M: (m at: 9) s: 7 t: (T at: 9); FFa: d b: a c: b d: c M: (m at: 10) s: 12 t: (T at: 10); FFa: c b: d c: a d: b M: (m at: 11) s: 17 t: (T at: 11); FFa: b b: c c: d d: a M: (m at: 12) s: 22 t: (T at: 12); FFa: a b: b c: c d: d M: (m at: 13) s: 7 t: (T at: 13); FFa: d b: a c: b d: c M: (m at: 14) s: 12 t: (T at: 14); FFa: c b: d c: a d: b M: (m at: 15) s: 17 t: (T at: 15); FFa: b b: c c: d d: a M: (m at: 16) s: 22 t: (T at: 16)
round2 self GGa: a b: b c: c d: d M: (m at: 2) s: 5 t: (T at: 17); GGa: d b: a c: b d: c M: (m at: 7) s: 9 t: (T at: 18); GGa: c b: d c: a d: b M: (m at: 12) s: 14 t: (T at: 19); GGa: b b: c c: d d: a M: (m at: 1) s: 20 t: (T at: 20); GGa: a b: b c: c d: d M: (m at: 6) s: 5 t: (T at: 21); GGa: d b: a c: b d: c M: (m at: 11) s: 9 t: (T at: 22); GGa: c b: d c: a d: b M: (m at: 16) s: 14 t: (T at: 23); GGa: b b: c c: d d: a M: (m at: 5) s: 20 t: (T at: 24); GGa: a b: b c: c d: d M: (m at: 10) s: 5 t: (T at: 25); GGa: d b: a c: b d: c M: (m at: 15) s: 9 t: (T at: 26); GGa: c b: d c: a d: b M: (m at: 4) s: 14 t: (T at: 27); GGa: b b: c c: d d: a M: (m at: 9) s: 20 t: (T at: 28); GGa: a b: b c: c d: d M: (m at: 14) s: 5 t: (T at: 29); GGa: d b: a c: b d: c M: (m at: 3) s: 9 t: (T at: 30); GGa: c b: d c: a d: b M: (m at: 8) s: 14 t: (T at: 31); GGa: b b: c c: d d: a M: (m at: 13) s: 20 t: (T at: 32)
round3 self HHa: a b: b c: c d: d M: (m at: 6) s: 4 t: (T at: 33); HHa: d b: a c: b d: c M: (m at: 9) s: 11 t: (T at: 34); HHa: c b: d c: a d: b M: (m at: 12) s: 16 t: (T at: 35); HHa: b b: c c: d d: a M: (m at: 15) s: 23 t: (T at: 36); HHa: a b: b c: c d: d M: (m at: 2) s: 4 t: (T at: 37); HHa: d b: a c: b d: c M: (m at: 5) s: 11 t: (T at: 38); HHa: c b: d c: a d: b M: (m at: 8) s: 16 t: (T at: 39); HHa: b b: c c: d d: a M: (m at: 11) s: 23 t: (T at: 40); HHa: a b: b c: c d: d M: (m at: 14) s: 4 t: (T at: 41); HHa: d b: a c: b d: c M: (m at: 1) s: 11 t: (T at: 42); HHa: c b: d c: a d: b M: (m at: 4) s: 16 t: (T at: 43); HHa: b b: c c: d d: a M: (m at: 7) s: 23 t: (T at: 44); HHa: a b: b c: c d: d M: (m at: 10) s: 4 t: (T at: 45); HHa: d b: a c: b d: c M: (m at: 13) s: 11 t: (T at: 46); HHa: c b: d c: a d: b M: (m at: 16) s: 16 t: (T at: 47); HHa: b b: c c: d d: a M: (m at: 3) s: 23 t: (T at: 48)
round4 self IIa: a b: b c: c d: d M: (m at: 1) s: 6 t: (T at: 49); IIa: d b: a c: b d: c M: (m at: 8) s: 10 t: (T at: 50); IIa: c b: d c: a d: b M: (m at: 15) s: 15 t: (T at: 51); IIa: b b: c c: d d: a M: (m at: 6) s: 21 t: (T at: 52); IIa: a b: b c: c d: d M: (m at: 13) s: 6 t: (T at: 53); IIa: d b: a c: b d: c M: (m at: 4) s: 10 t: (T at: 54); IIa: c b: d c: a d: b M: (m at: 11) s: 15 t: (T at: 55); IIa: b b: c c: d d: a M: (m at: 2) s: 21 t: (T at: 56); IIa: a b: b c: c d: d M: (m at: 9) s: 6 t: (T at: 57); IIa: d b: a c: b d: c M: (m at: 16) s: 10 t: (T at: 58); IIa: c b: d c: a d: b M: (m at: 7) s: 15 t: (T at: 59); IIa: b b: c c: d d: a M: (m at: 14) s: 21 t: (T at: 60); IIa: a b: b c: c d: d M: (m at: 5) s: 6 t: (T at: 61); IIa: d b: a c: b d: c M: (m at: 12) s: 10 t: (T at: 62); IIa: c b: d c: a d: b M: (m at: 3) s: 15 t: (T at: 63); IIa: b b: c c: d d: a M: (m at: 10) s: 21 t: (T at: 64)
</methods> <methods> Security.MD5 <category>private-digest</category>
backupRegisters "This has to match with #restoreRegisters:" ^Array with: a copy with: b copy with: c copy with: d copy
restoreRegisters: anArrayOfRegisters "This has to match with #backupRegisters" a := anArrayOfRegisters at: 1. b := anArrayOfRegisters at: 2. c := anArrayOfRegisters at: 3. d := anArrayOfRegisters at: 4
storeLength "little-endian" | bufferSize length | bufferSize := self blockSize. length := self messageLength. bufferSize - 7 to: bufferSize do: [ :i | block at: i put: (length bitAnd: 255). length := length bitShift: -8 ].
writeDigestInto: aByteArray startingAt: start a reverseStoreTo: aByteArray at: start. b reverseStoreTo: aByteArray at: start + 4. c reverseStoreTo: aByteArray at: start + 8. d reverseStoreTo: aByteArray at: start + 12.
</methods> <methods> Security.MD5 <category>services-basic</category>
reset super reset. a reverseLoadFrom: #[16r01 16r23 16r45 16r67] at: 1. b reverseLoadFrom: #[16r89 16rAB 16rCD 16rEF] at: 1. c reverseLoadFrom: #[16rFE 16rDC 16rBA 16r98] at: 1. d reverseLoadFrom: #[16r76 16r54 16r32 16r10] at: 1
</methods> <methods> Security.MD5 <category>initialize-release</category>
initialize super initialize. a := ThirtyTwoBitRegister new. b := ThirtyTwoBitRegister new. c := ThirtyTwoBitRegister new. d := ThirtyTwoBitRegister new. aa := ThirtyTwoBitRegister new. bb := ThirtyTwoBitRegister new. cc := ThirtyTwoBitRegister new. dd := ThirtyTwoBitRegister new. f := ThirtyTwoBitRegister new. ff := ThirtyTwoBitRegister new. m := (1 to: 16) inject: (Array new: 16) into: [ :array :i | array at: i put: ThirtyTwoBitRegister new; yourself ]. self reset
</methods> <methods> Security.MD5 class <category>accessing</category>
blockSize ^64
digestSize ^16
</methods> <methods> Security.MD5 class <category>initialization</category>
computeSinTable "Obscure fact: those magic hex numbers in Bruce's book that are hard to type in correctly are actually the result of a simple trigonometric function. One must remember however to do the math in Doubles otherwise the values are trash." | c | c := 2 raisedTo: 32. ^(1 to: 64) inject: (Array new: 64) into: [ :t :i | t at: i put: (ThirtyTwoBitRegister new load: (c * i asDouble sin abs) truncated); yourself ].
</methods> <methods> Security.HMAC class <category>instance creation</category>
MD5 ^self hash: MD5 new
MD5: keyBytes ^self MD5 setKey: keyBytes; yourself
</methods> <methods> Core.ByteArray <category>security</category>
md5Value ^Security.MD5 integerHash: self
</methods> "Imported Classes:" self error: 'Attempting to file-in parcel imports. Choose terminate or close' <class> <name>ByteArray</name> <environment>Core</environment> <super>Core.IntegerArray</super> <private>false</private> bytes <imports></imports> <category>Collections-Arrayed</category> <attributes> <package>Collections-Arrayed</package> </attributes> </class> <class> <name>Hash</name> <environment>Security</environment> <super>Security.MessageDigest</super> <private>false</private> none block position total <imports></imports> <category>Security-Hashes</category> <attributes> <package>HashesBase</package> </attributes> </class>