[613] | 1 | XUMF5AU ;ISS/PAVEL - XUMF5 MD5 Hash API ;06/17/05
|
---|
| 2 | ;;8.0;KERNEL;**383**;July 10, 1995
|
---|
| 3 | ;
|
---|
| 4 | ;MD5 based on info from 4.005 SORT BY VUID;;original name was 'VESOUHSH' ; Secure hash functions
|
---|
| 5 | ;;(c) Copyright 1994 - 2004, ESI Technology Corp, Natick MA
|
---|
| 6 | ;; This source code contains the intellectual property of its copyright holder(s),
|
---|
| 7 | ;; and is made available under a license. If you are not familiar with the terms
|
---|
| 8 | ;; of the license, please refer to the license.txt file that is a part of the
|
---|
| 9 | ;; distribution kit.
|
---|
| 10 | ;; This is a routine version where Variables and Commands set to be Upercase. Pavel
|
---|
| 11 | ;
|
---|
| 12 | Q
|
---|
| 13 | ;;**************************************************
|
---|
| 14 | ;;MD5 'R'egular portion of the code. This will handle
|
---|
| 15 | ;; one string at a time.
|
---|
| 16 | ;;**************************************************
|
---|
| 17 | MD5R(STR) ; Construct a 128-bit MD5 hash of the input.
|
---|
| 18 | N TWOTO
|
---|
| 19 | N A,B,C,D
|
---|
| 20 | N AA,BB,CC,DD
|
---|
| 21 | D INITR
|
---|
| 22 | PAD1R ; Pad str out to 56 bytes mod 64
|
---|
| 23 | ; Padding is a 1 bit followed by all zero bits
|
---|
| 24 | N LEN,MOD,NPAD,PAD
|
---|
| 25 | S LEN=$L(STR),MOD=LEN#64
|
---|
| 26 | S NPAD=$S(MOD<56:56-MOD,1:120-MOD)
|
---|
| 27 | S PAD=$C(128)
|
---|
| 28 | S:NPAD>1 $P(PAD,$C(0),NPAD)=""
|
---|
| 29 | S STR=STR_PAD
|
---|
| 30 | PAD2R ; Append length in bits as 64-bit integer, little endian
|
---|
| 31 | S LEN=LEN*8
|
---|
| 32 | S STR=STR_$$UI64BIT(LEN)
|
---|
| 33 | PROCESSR ; Main processing and transformation loop
|
---|
| 34 | N J,POS,N,I
|
---|
| 35 | N X ; X(J) is a 4-byte word from a 64-byte block
|
---|
| 36 | S N=$L(STR)/64 ; Number of 64-byte blocks
|
---|
| 37 | F I=0:1:N-1 D
|
---|
| 38 | . F J=0:1:15 S POS=(64*I)+(4*J),X(J)=$E(STR,POS+1,POS+4)
|
---|
| 39 | . D SAVE
|
---|
| 40 | . D ROUND1
|
---|
| 41 | . D ROUND2
|
---|
| 42 | . D ROUND3
|
---|
| 43 | . D ROUND4
|
---|
| 44 | . D INCR
|
---|
| 45 | K X
|
---|
| 46 | Q A_B_C_D
|
---|
| 47 | ;
|
---|
| 48 | INITR ; Initialization
|
---|
| 49 | ; Set up array of powers of two for rotation
|
---|
| 50 | N I,N
|
---|
| 51 | S N=1
|
---|
| 52 | F I=0:1:31 S TWOTO(I)=N,N=N+N
|
---|
| 53 | ; Initialize 4-byte buffers A,B,C,D
|
---|
| 54 | S A=$C(1,35,69,103)
|
---|
| 55 | S B=$C(137,171,205,239)
|
---|
| 56 | S C=$C(254,220,186,152)
|
---|
| 57 | S D=$C(118,84,50,16)
|
---|
| 58 | Q
|
---|
| 59 | ;
|
---|
| 60 | ;;**************************************************
|
---|
| 61 | ;;MD5 'E'nhanced portion of the code. This will handle
|
---|
| 62 | ;; multiple strings and produce a value for them all
|
---|
| 63 | ;; as if they were submitted as one long string.
|
---|
| 64 | ;;**************************************************
|
---|
| 65 | MD5E(ABCD,STR,PP,LL) ; Construct a 128-bit MD5 hash of the input.
|
---|
| 66 | N TWOTO
|
---|
| 67 | N A,B,C,D
|
---|
| 68 | N AA,BB,CC,DD
|
---|
| 69 | D INITE(ABCD)
|
---|
| 70 | PAD1E ; Pad str out to 56 bytes mod 64
|
---|
| 71 | ; Padding is a 1 bit followed by all zero bits
|
---|
| 72 | ; PP = 1 Don't pad with $C(128) !!! Pavel Set to 1 if this is not last string !!
|
---|
| 73 | ; Set to 0 if this is last string !!
|
---|
| 74 | ; LL = Lenght passed form outside for pading of little endian Pavel !!! -
|
---|
| 75 | ; Seting lenght if this is last value othervise computed lenght used...
|
---|
| 76 | N LEN,MOD,NPAD,PAD
|
---|
| 77 | S LEN=$L(STR),MOD=LEN#64
|
---|
| 78 | S:$G(LL) LEN=LL ;Pavel
|
---|
| 79 | S NPAD=$S(MOD<56:56-MOD,1:120-MOD)
|
---|
| 80 | S PAD=$C(128)
|
---|
| 81 | S:NPAD>1 $P(PAD,$C(0),NPAD)=""
|
---|
| 82 | S:'$G(PP) STR=STR_PAD ;Pavel
|
---|
| 83 | ;S STR=STR_PAD
|
---|
| 84 | PAD2E ; Append length in bits as 64-bit integer, little endian
|
---|
| 85 | S LEN=LEN*8
|
---|
| 86 | S STR=STR_$$UI64BIT(LEN)
|
---|
| 87 | PROCESSE ; Main processing and transformation loop
|
---|
| 88 | N J,POS,N,I
|
---|
| 89 | N X ; X(J) is a 4-byte word from a 64-byte block
|
---|
| 90 | ;S N=$L(STR)/64 ; Number of 64-byte blocks
|
---|
| 91 | S N=$L(STR)\64 ; Number of 64-byte blocks
|
---|
| 92 | F I=0:1:N-1 D
|
---|
| 93 | . F J=0:1:15 S POS=(64*I)+(4*J),X(J)=$E(STR,POS+1,POS+4)
|
---|
| 94 | . D SAVE
|
---|
| 95 | . D ROUND1
|
---|
| 96 | . D ROUND2
|
---|
| 97 | . D ROUND3
|
---|
| 98 | . D ROUND4
|
---|
| 99 | . D INCR
|
---|
| 100 | . ;W !,I," ABCD=",$$MAIN^XUMF5BYT($$HEX(A_B_C_D)),!
|
---|
| 101 | K X
|
---|
| 102 | Q A_B_C_D
|
---|
| 103 | ;
|
---|
| 104 | INITE(LASTABCD) ; Initialization
|
---|
| 105 | ; Set up array of powers of two for rotation
|
---|
| 106 | N I,N,L
|
---|
| 107 | S N=1
|
---|
| 108 | F I=0:1:31 S TWOTO(I)=N,N=N+N
|
---|
| 109 | ; Initialize 4-byte buffers A,B,C,D
|
---|
| 110 | S A=$E(LASTABCD,1,4)
|
---|
| 111 | S B=$E(LASTABCD,5,8)
|
---|
| 112 | S C=$E(LASTABCD,9,12)
|
---|
| 113 | S D=$E(LASTABCD,13,16)
|
---|
| 114 | Q
|
---|
| 115 | ;
|
---|
| 116 | ;;**************************************************
|
---|
| 117 | ;;This is where common code starts, used by both
|
---|
| 118 | ;; Regular and Enhanced portions of this routine.
|
---|
| 119 | ;;**************************************************
|
---|
| 120 | SAVE ; Save buffers
|
---|
| 121 | S AA=A,BB=B,CC=C,DD=D
|
---|
| 122 | Q
|
---|
| 123 | ;
|
---|
| 124 | ROUND1 ; First round of transformation
|
---|
| 125 | D SUB(.A,B,C,D,X(0),7,3614090360,1)
|
---|
| 126 | D SUB(.D,A,B,C,X(1),12,3905402710,1)
|
---|
| 127 | D SUB(.C,D,A,B,X(2),17,606105819,1)
|
---|
| 128 | D SUB(.B,C,D,A,X(3),22,3250441966,1)
|
---|
| 129 | D SUB(.A,B,C,D,X(4),7,4118548399,1)
|
---|
| 130 | D SUB(.D,A,B,C,X(5),12,1200080426,1)
|
---|
| 131 | D SUB(.C,D,A,B,X(6),17,2821735955,1)
|
---|
| 132 | D SUB(.B,C,D,A,X(7),22,4249261313,1)
|
---|
| 133 | D SUB(.A,B,C,D,X(8),7,1770035416,1)
|
---|
| 134 | D SUB(.D,A,B,C,X(9),12,2336552879,1)
|
---|
| 135 | D SUB(.C,D,A,B,X(10),17,4294925233,1)
|
---|
| 136 | D SUB(.B,C,D,A,X(11),22,2304563134,1)
|
---|
| 137 | D SUB(.A,B,C,D,X(12),7,1804603682,1)
|
---|
| 138 | D SUB(.D,A,B,C,X(13),12,4254626195,1)
|
---|
| 139 | D SUB(.C,D,A,B,X(14),17,2792965006,1)
|
---|
| 140 | D SUB(.B,C,D,A,X(15),22,1236535329,1)
|
---|
| 141 | Q
|
---|
| 142 | ;
|
---|
| 143 | ROUND2 ; Second round of transformation
|
---|
| 144 | D SUB(.A,B,C,D,X(1),5,4129170786,2)
|
---|
| 145 | D SUB(.D,A,B,C,X(6),9,3225465664,2)
|
---|
| 146 | D SUB(.C,D,A,B,X(11),14,643717713,2)
|
---|
| 147 | D SUB(.B,C,D,A,X(0),20,3921069994,2)
|
---|
| 148 | D SUB(.A,B,C,D,X(5),5,3593408605,2)
|
---|
| 149 | D SUB(.D,A,B,C,X(10),9,38016083,2)
|
---|
| 150 | D SUB(.C,D,A,B,X(15),14,3634488961,2)
|
---|
| 151 | D SUB(.B,C,D,A,X(4),20,3889429448,2)
|
---|
| 152 | D SUB(.A,B,C,D,X(9),5,568446438,2)
|
---|
| 153 | D SUB(.D,A,B,C,X(14),9,3275163606,2)
|
---|
| 154 | D SUB(.C,D,A,B,X(3),14,4107603335,2)
|
---|
| 155 | D SUB(.B,C,D,A,X(8),20,1163531501,2)
|
---|
| 156 | D SUB(.A,B,C,D,X(13),5,2850285829,2)
|
---|
| 157 | D SUB(.D,A,B,C,X(2),9,4243563512,2)
|
---|
| 158 | D SUB(.C,D,A,B,X(7),14,1735328473,2)
|
---|
| 159 | D SUB(.B,C,D,A,X(12),20,2368359562,2)
|
---|
| 160 | Q
|
---|
| 161 | ;
|
---|
| 162 | ROUND3 ; Third round of transformation
|
---|
| 163 | D SUB(.A,B,C,D,X(5),4,4294588738,3)
|
---|
| 164 | D SUB(.D,A,B,C,X(8),11,2272392833,3)
|
---|
| 165 | D SUB(.C,D,A,B,X(11),16,1839030562,3)
|
---|
| 166 | D SUB(.B,C,D,A,X(14),23,4259657740,3)
|
---|
| 167 | D SUB(.A,B,C,D,X(1),4,2763975236,3)
|
---|
| 168 | D SUB(.D,A,B,C,X(4),11,1272893353,3)
|
---|
| 169 | D SUB(.C,D,A,B,X(7),16,4139469664,3)
|
---|
| 170 | D SUB(.B,C,D,A,X(10),23,3200236656,3)
|
---|
| 171 | D SUB(.A,B,C,D,X(13),4,681279174,3)
|
---|
| 172 | D SUB(.D,A,B,C,X(0),11,3936430074,3)
|
---|
| 173 | D SUB(.C,D,A,B,X(3),16,3572445317,3)
|
---|
| 174 | D SUB(.B,C,D,A,X(6),23,76029189,3)
|
---|
| 175 | D SUB(.A,B,C,D,X(9),4,3654602809,3)
|
---|
| 176 | D SUB(.D,A,B,C,X(12),11,3873151461,3)
|
---|
| 177 | D SUB(.C,D,A,B,X(15),16,530742520,3)
|
---|
| 178 | D SUB(.B,C,D,A,X(2),23,3299628645,3)
|
---|
| 179 | Q
|
---|
| 180 | ;
|
---|
| 181 | ROUND4 ; Fourth round of transformation
|
---|
| 182 | D SUB(.A,B,C,D,X(0),6,4096336452,4)
|
---|
| 183 | D SUB(.D,A,B,C,X(7),10,1126891415,4)
|
---|
| 184 | D SUB(.C,D,A,B,X(14),15,2878612391,4)
|
---|
| 185 | D SUB(.B,C,D,A,X(5),21,4237533241,4)
|
---|
| 186 | D SUB(.A,B,C,D,X(12),6,1700485571,4)
|
---|
| 187 | D SUB(.D,A,B,C,X(3),10,2399980690,4)
|
---|
| 188 | D SUB(.C,D,A,B,X(10),15,4293915773,4)
|
---|
| 189 | D SUB(.B,C,D,A,X(1),21,2240044497,4)
|
---|
| 190 | D SUB(.A,B,C,D,X(8),6,1873313359,4)
|
---|
| 191 | D SUB(.D,A,B,C,X(15),10,4264355552,4)
|
---|
| 192 | D SUB(.C,D,A,B,X(6),15,2734768916,4)
|
---|
| 193 | D SUB(.B,C,D,A,X(13),21,1309151649,4)
|
---|
| 194 | D SUB(.A,B,C,D,X(4),6,4149444226,4)
|
---|
| 195 | D SUB(.D,A,B,C,X(11),10,3174756917,4)
|
---|
| 196 | D SUB(.C,D,A,B,X(2),15,718787259,4)
|
---|
| 197 | D SUB(.B,C,D,A,X(9),21,3951481745,4)
|
---|
| 198 | Q
|
---|
| 199 | INCR ;
|
---|
| 200 | S A=$$ADD(A,AA)
|
---|
| 201 | S B=$$ADD(B,BB)
|
---|
| 202 | S C=$$ADD(C,CC)
|
---|
| 203 | S D=$$ADD(D,DD)
|
---|
| 204 | Q
|
---|
| 205 | ;
|
---|
| 206 | ; Auxiliary functions
|
---|
| 207 | ;
|
---|
| 208 | SUB(A,B,C,D,X,S,AC,FN) ; FN is 1 (F), 2 (G), 3 (H) or 4 (I)
|
---|
| 209 | N INT,COMB,CMD,DO
|
---|
| 210 | S INT=$$UINT32(A)
|
---|
| 211 | S DO="COMB"_FN
|
---|
| 212 | D @DO
|
---|
| 213 | S INT=$$ADDIW(INT,COMB)
|
---|
| 214 | S INT=$$ADDIW(INT,X)
|
---|
| 215 | S INT=$$ADDII(INT,AC)
|
---|
| 216 | S INT=$$ROTLI(INT,S)
|
---|
| 217 | S INT=$$ADDIW(INT,B)
|
---|
| 218 | S A=$$UI32BIT(INT)
|
---|
| 219 | Q
|
---|
| 220 | COMB ; Choose F, G, H or I
|
---|
| 221 | COMB1 S COMB=$$OR($$AND(B,C),$$AND($$NOT(B),D)) Q ; F
|
---|
| 222 | COMB2 S COMB=$$OR($$AND(B,D),$$AND(C,$$NOT(D))) Q ; G
|
---|
| 223 | COMB3 S COMB=$$XOR($$XOR(B,C),D) Q ; H
|
---|
| 224 | COMB4 S COMB=$$XOR(C,$$OR(B,$$NOT(D))) Q ; I
|
---|
| 225 | Q
|
---|
| 226 | ;
|
---|
| 227 | ; Boolean functions assume args are 4-character strings
|
---|
| 228 | ;
|
---|
| 229 | AND(X,Y) ;
|
---|
| 230 | Q $ZBOOLEAN(X,Y,1) ;;EOCONDCD;CACHE
|
---|
| 231 | Q X ; Placeholder for other M implementations
|
---|
| 232 | ;
|
---|
| 233 | OR(X,Y) ;
|
---|
| 234 | Q $ZBOOLEAN(X,Y,7) ;;EOCONDCD;CACHE
|
---|
| 235 | Q X ; Placeholder for other M implementations
|
---|
| 236 | ;
|
---|
| 237 | XOR(X,Y) ;
|
---|
| 238 | Q $ZBOOLEAN(X,Y,6) ;;EOCONDCD;CACHE
|
---|
| 239 | Q X ; Placeholder for other M implementations
|
---|
| 240 | ;
|
---|
| 241 | NOT(X) ;
|
---|
| 242 | Q $ZBOOLEAN(X,X,12) ;;EOCONDCD;CACHE
|
---|
| 243 | Q X ; Placeholder for other M implementations
|
---|
| 244 | ;
|
---|
| 245 | ; Functions to add and rotate 32-bit words
|
---|
| 246 | ; X and Y are 4-character strings
|
---|
| 247 | ; m, n and s are integers
|
---|
| 248 | ; ADD and ROTL return 4-character strings
|
---|
| 249 | ; ADDIW, ADDII and ROTLI return integers
|
---|
| 250 | ;
|
---|
| 251 | ADD(X,Y) ; modulo 2**32
|
---|
| 252 | Q $$UI32BIT($$UINT32(X)+$$UINT32(Y)#4294967296)
|
---|
| 253 | ;
|
---|
| 254 | ADDIW(M,Y) ; modulo 2**32
|
---|
| 255 | Q M+$$UINT32(Y)#4294967296
|
---|
| 256 | ;
|
---|
| 257 | ADDII(M,N) ; modulo 2**32
|
---|
| 258 | Q M+N#4294967296
|
---|
| 259 | ;
|
---|
| 260 | ROTL(X,S) ; rotate left by s bits
|
---|
| 261 | N INT,RIGHT,SWAP
|
---|
| 262 | S INT=$$UINT32(X)
|
---|
| 263 | S RIGHT=INT#TWOTO(32-S)
|
---|
| 264 | S SWAP=RIGHT*TWOTO(S)+(INT\TWOTO(32-S))
|
---|
| 265 | Q $$UI32BIT(SWAP)
|
---|
| 266 | ;
|
---|
| 267 | ROTLI(N,S) ; rotate left by s bits
|
---|
| 268 | N RIGHT,SWAP
|
---|
| 269 | S RIGHT=N#TWOTO(32-S)
|
---|
| 270 | S SWAP=RIGHT*TWOTO(S)+(N\TWOTO(32-S))
|
---|
| 271 | Q SWAP
|
---|
| 272 | ;
|
---|
| 273 | ; Utility functions
|
---|
| 274 | ;
|
---|
| 275 | UI64BIT(N) ; Convert unsigned integer to 64-bit form, little endian
|
---|
| 276 | ; code from CORBA ULONGLONG marshaling
|
---|
| 277 | N D,X,I
|
---|
| 278 | S D=""
|
---|
| 279 | F I=7:-1:1 D
|
---|
| 280 | . S X=0
|
---|
| 281 | . F Q:(N<(256**I)) S X=X+1,N=N-(256**I)
|
---|
| 282 | . S X(I)=X
|
---|
| 283 | S D=D_$C(N)
|
---|
| 284 | F I=1:1:7 S D=D_$C(X(I))
|
---|
| 285 | Q D
|
---|
| 286 | ;
|
---|
| 287 | UI32BIT(N) ; Convert unsigned integer to 32-bit form, little endian
|
---|
| 288 | ; code from CORBA ULONG marshaling
|
---|
| 289 | Q $C(N#256,(N\256#256),(N\(65536)#256),(N\(16777216)#256))
|
---|
| 290 | ;
|
---|
| 291 | UINT32(STR) ; Get integer value from bits of 4-character string
|
---|
| 292 | ; code from CORBA ULONG unmarshaling
|
---|
| 293 | Q $A(STR,1)+(256*$A(STR,2))+(65536*$A(STR,3))+(16777216*$A(STR,4))
|
---|
| 294 | ;
|
---|
| 295 | HEX(STR) ; Printable hex representation of characters in string
|
---|
| 296 | N DIGITS,RET,I,J,BYTE,OFFSET
|
---|
| 297 | S DIGITS="0123456789abcdef"
|
---|
| 298 | S RET=""
|
---|
| 299 | S OFFSET=$L(STR)#4
|
---|
| 300 | S:OFFSET STR=STR_$E($C(0,0,0),1,4-OFFSET) ; PAD
|
---|
| 301 | F I=0:4:$L(STR)-4 F J=4:-1:1 D ; Reverse byte order in each word
|
---|
| 302 | . S BYTE=$A(STR,I+J)
|
---|
| 303 | . S RET=RET_$E(DIGITS,1+(BYTE\16)) ; High nibble
|
---|
| 304 | . S RET=RET_$E(DIGITS,1+(BYTE#16)) ; Low nibble
|
---|
| 305 | Q RET
|
---|
| 306 | ;
|
---|
| 307 | CHR2OCT(STR) ; convert hex string to decimal byte values
|
---|
| 308 | N RET,I,BYTE,HIGH,LOW
|
---|
| 309 | S RET=""
|
---|
| 310 | F I=1:2:$L(STR) D
|
---|
| 311 | . S BYTE=$E(STR,I,I+1)
|
---|
| 312 | . Q:BYTE'?2NL
|
---|
| 313 | . S HIGH=$$CHAR1($E(BYTE,1))
|
---|
| 314 | . S LOW=$$CHAR1($E(BYTE,2))
|
---|
| 315 | . S RET=RET_(16*HIGH+LOW)_" "
|
---|
| 316 | Q RET
|
---|
| 317 | ;
|
---|
| 318 | CHAR1(DIGIT) ; convert one char to its hex value
|
---|
| 319 | N X
|
---|
| 320 | S X=$F("0123456789abcdef",DIGIT)
|
---|
| 321 | Q:X=0 0
|
---|
| 322 | Q X-2
|
---|