"Fossies" - the Fresh Open Source Software Archive 
Member "seed7/lib/msgdigest.s7i" (19 Mar 2020, 43695 Bytes) of package /linux/misc/seed7_05_20210223.tgz:
As a special service "Fossies" has tried to format the requested text file into HTML format (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
1
2 (********************************************************************)
3 (* *)
4 (* msgdigest.s7i Message digest and secure hash algorithms. *)
5 (* Copyright (C) 2013, 2014, 2017 - 2019 Thomas Mertes *)
6 (* *)
7 (* This file is part of the Seed7 Runtime Library. *)
8 (* *)
9 (* The Seed7 Runtime Library is free software; you can *)
10 (* redistribute it and/or modify it under the terms of the GNU *)
11 (* Lesser General Public License as published by the Free Software *)
12 (* Foundation; either version 2.1 of the License, or (at your *)
13 (* option) any later version. *)
14 (* *)
15 (* The Seed7 Runtime Library is distributed in the hope that it *)
16 (* will be useful, but WITHOUT ANY WARRANTY; without even the *)
17 (* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *)
18 (* PURPOSE. See the GNU Lesser General Public License for more *)
19 (* details. *)
20 (* *)
21 (* You should have received a copy of the GNU Lesser General *)
22 (* Public License along with this program; if not, write to the *)
23 (* Free Software Foundation, Inc., 51 Franklin Street, *)
24 (* Fifth Floor, Boston, MA 02110-1301, USA. *)
25 (* *)
26 (********************************************************************)
27
28
29 include "bytedata.s7i";
30 include "bin32.s7i";
31 include "bin64.s7i";
32 include "float.s7i";
33 include "math.s7i";
34
35
36 (**
37 * Compute a message digest with the MD4 message digest algorithm.
38 * The security of MD4 has been severely compromised. This function
39 * is provided for backward compatibility.
40 * @return the MD4 message digest (a string of 16 bytes).
41 * @exception RANGE_ERROR If ''message'' contains a character beyond '\255;'.
42 *)
43 const func string: md4 (in var string: message) is func
44 result
45 var string: digest is "";
46 local
47 # Specify the per-round shift amounts
48 const array integer: shiftAmount is [] (
49 3, 7, 11, 19, 3, 7, 11, 19, 3, 7, 11, 19, 3, 7, 11, 19,
50 3, 5, 9, 13, 3, 5, 9, 13, 3, 5, 9, 13, 3, 5, 9, 13,
51 3, 9, 11, 15, 3, 9, 11, 15, 3, 9, 11, 15, 3, 9, 11, 15);
52 const array integer: idx is [] (
53 1, 9, 5, 13, 3, 11, 7, 15, 2, 10, 6, 14, 4, 12, 8, 16);
54 var integer: length is 0;
55 var integer: wordIndex is 1;
56 var integer: index is 0;
57 var array bin32: m is 16 times bin32.value;
58 var integer: a0 is 16#67452301; # a
59 var integer: b0 is 16#efcdab89; # b
60 var integer: c0 is 16#98badcfe; # c
61 var integer: d0 is 16#10325476; # d
62 var bin32: a is bin32(0);
63 var bin32: b is bin32(0);
64 var bin32: c is bin32(0);
65 var bin32: d is bin32(0);
66 var bin32: f is bin32(0);
67 var integer: g is 0;
68 var bin32: temp is bin32(0);
69 begin
70 length := length(message);
71 # Append the bit '1' to the message.
72 message &:= '\16#80;';
73 # Append '0' bits, so that the resulting bit length is congruent to 448 (mod 512).
74 message &:= "\0;" mult 63 - (length + 8) mod 64;
75 # Append length of message (before pre-processing), in bits, as 64-bit little-endian integer.
76 message &:= int64AsEightBytesLe(8 * length);
77
78 # Process the message in successive 512-bit chunks:
79 while wordIndex <= length(message) do
80 # Break chunk into sixteen 32-bit little-endian words.
81 for index range 1 to 16 do
82 m[index] := bin32(bytes2Int(message[wordIndex len 4], UNSIGNED, LE));
83 wordIndex +:= 4;
84 end for;
85
86 a := bin32(a0 mod 16#100000000);
87 b := bin32(b0 mod 16#100000000);
88 c := bin32(c0 mod 16#100000000);
89 d := bin32(d0 mod 16#100000000);
90
91 for index range 1 to 48 do
92 if index <= 16 then
93 f := d >< (b & (c >< d));
94 g := index;
95 elsif index <= 32 then
96 f := bin32(ord(b & (c | d) | (c & d)) + 16#5a827999);
97 g := (4 * index + 7) mod 15 + (index mdiv 32) * 15 + 1;
98 else
99 f := bin32(ord(b >< c >< d) + 16#6ed9eba1);
100 g := idx[index - 32];
101 end if;
102 temp := d;
103 d := c;
104 c := b;
105 b := rotLeft(bin32((ord(a) + ord(f) + ord(m[g])) mod 16#100000000),
106 shiftAmount[index]);
107 a := temp;
108 end for;
109
110 # Add this chunk's hash to result so far:
111 a0 +:= ord(a);
112 b0 +:= ord(b);
113 c0 +:= ord(c);
114 d0 +:= ord(d);
115 end while;
116
117 # Produce the final hash value:
118 digest := int32AsFourBytesLe(a0) &
119 int32AsFourBytesLe(b0) &
120 int32AsFourBytesLe(c0) &
121 int32AsFourBytesLe(d0);
122 end func;
123
124
125 # Use binary integer part of the sines of integers (Radians) as constants:
126 const func array integer: createMd5Table is func
127 result
128 var array integer: k is 64 times 0;
129 local
130 var integer: index is 0;
131 begin
132 for index range 1 to 64 do
133 k[index] := trunc(abs(sin(flt(index))) * 2.0 ** 32);
134 end for;
135 end func;
136
137
138 (**
139 * Compute a message digest with the MD5 message digest algorithm.
140 * MD5 is considered to be cryptographically broken. This function
141 * is provided for backward compatibility.
142 * @return the MD5 message digest (a string of 16 bytes).
143 * @exception RANGE_ERROR If ''message'' contains a character beyond '\255;'.
144 *)
145 const func string: md5 (in var string: message) is func
146 result
147 var string: digest is "";
148 local
149 # Specify the per-round shift amounts
150 const array integer: shiftAmount is [] (
151 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
152 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
153 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
154 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21);
155 const array integer: k is createMd5Table;
156 var integer: length is 0;
157 var integer: wordIndex is 1;
158 var integer: index is 0;
159 var array bin32: m is 16 times bin32.value;
160 var integer: a0 is 16#67452301; # a
161 var integer: b0 is 16#efcdab89; # b
162 var integer: c0 is 16#98badcfe; # c
163 var integer: d0 is 16#10325476; # d
164 var bin32: a is bin32(0);
165 var bin32: b is bin32(0);
166 var bin32: c is bin32(0);
167 var bin32: d is bin32(0);
168 var bin32: f is bin32(0);
169 var integer: g is 0;
170 var bin32: temp is bin32(0);
171 begin
172 length := length(message);
173 # Append the bit '1' to the message.
174 message &:= '\16#80;';
175 # Append '0' bits, so that the resulting bit length is congruent to 448 (mod 512).
176 message &:= "\0;" mult 63 - (length + 8) mod 64;
177 # Append length of message (before pre-processing), in bits, as 64-bit little-endian integer.
178 message &:= int64AsEightBytesLe(8 * length);
179
180 # Process the message in successive 512-bit chunks:
181 while wordIndex <= length(message) do
182 # Break chunk into sixteen 32-bit little-endian words.
183 for index range 1 to 16 do
184 m[index] := bin32(bytes2Int(message[wordIndex len 4], UNSIGNED, LE));
185 wordIndex +:= 4;
186 end for;
187
188 a := bin32(a0 mod 16#100000000);
189 b := bin32(b0 mod 16#100000000);
190 c := bin32(c0 mod 16#100000000);
191 d := bin32(d0 mod 16#100000000);
192
193 for index range 1 to 64 do
194 if index <= 16 then
195 f := d >< (b & (c >< d));
196 g := index;
197 elsif index <= 32 then
198 f := c >< (d & (b >< c));
199 g := (5 * index - 4) mod 16 + 1;
200 elsif index <= 48 then
201 f := b >< c >< d;
202 g := (3 * index + 2) mod 16 + 1;
203 else
204 f := c >< (b | (bin32(16#ffffffff) >< d));
205 g := (7 * pred(index)) mod 16 + 1;
206 end if;
207
208 temp := d;
209 d := c;
210 c := b;
211 b := bin32((ord(b) +
212 ord(rotLeft(bin32((ord(a) + ord(f) + k[index] + ord(m[g])) mod 16#100000000),
213 shiftAmount[index]))) mod 16#100000000);
214 a := temp;
215 end for;
216
217 # Add this chunk's hash to result so far:
218 a0 +:= ord(a);
219 b0 +:= ord(b);
220 c0 +:= ord(c);
221 d0 +:= ord(d);
222 end while;
223
224 # Produce the final hash value:
225 digest := int32AsFourBytesLe(a0) &
226 int32AsFourBytesLe(b0) &
227 int32AsFourBytesLe(c0) &
228 int32AsFourBytesLe(d0);
229 end func;
230
231
232 (**
233 * Compute a message digest with the RIPEMD-160 message digest algorithm.
234 * @return the RIPEMD-160 message digest (a string of 20 bytes).
235 * @exception RANGE_ERROR If ''message'' contains a character beyond '\255;'.
236 *)
237 const func string: ripemd160 (in var string: message) is func
238 result
239 var string: digest is "";
240 local
241 const array integer: k1 is [] (16#00000000, 16#5a827999, 16#6ed9eba1, 16#8f1bbcdc, 16#a953fd4e);
242 const array integer: k2 is [] (16#50a28be6, 16#5c4dd124, 16#6d703ef3, 16#7a6d76e9, 16#00000000);
243 const array integer: r1 is [] (
244 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
245 8, 5, 14, 2, 11, 7, 16, 4, 13, 1, 10, 6, 3, 15, 12, 9,
246 4, 11, 15, 5, 10, 16, 9, 2, 3, 8, 1, 7, 14, 12, 6, 13,
247 2, 10, 12, 11, 1, 9, 13, 5, 14, 4, 8, 16, 15, 6, 7, 3,
248 5, 1, 6, 10, 8, 13, 3, 11, 15, 2, 4, 9, 12, 7, 16, 14);
249 const array integer: r2 is [] (
250 6, 15, 8, 1, 10, 3, 12, 5, 14, 7, 16, 9, 2, 11, 4, 13,
251 7, 12, 4, 8, 1, 14, 6, 11, 15, 16, 9, 13, 5, 10, 2, 3,
252 16, 6, 2, 4, 8, 15, 7, 10, 12, 9, 13, 3, 11, 1, 5, 14,
253 9, 7, 5, 2, 4, 12, 16, 1, 6, 13, 3, 14, 10, 8, 11, 15,
254 13, 16, 11, 5, 2, 6, 9, 8, 7, 3, 14, 15, 1, 4, 10, 12);
255 const array integer: s1 is [] (
256 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
257 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
258 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
259 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
260 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6);
261 const array integer: s2 is [] (
262 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
263 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
264 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
265 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
266 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11);
267 var integer: length is 0;
268 var integer: wordIndex is 1;
269 var integer: index is 0;
270 var array integer: x is 16 times 0;
271 var integer: h0 is 16#67452301;
272 var integer: h1 is 16#efcdab89;
273 var integer: h2 is 16#98badcfe;
274 var integer: h3 is 16#10325476;
275 var integer: h4 is 16#c3d2e1f0;
276 var bin32: a1 is bin32(0);
277 var bin32: b1 is bin32(0);
278 var bin32: c1 is bin32(0);
279 var bin32: d1 is bin32(0);
280 var bin32: e1 is bin32(0);
281 var bin32: a2 is bin32(0);
282 var bin32: b2 is bin32(0);
283 var bin32: c2 is bin32(0);
284 var bin32: d2 is bin32(0);
285 var bin32: e2 is bin32(0);
286 var integer: t1 is 0;
287 var integer: t2 is 0;
288 begin
289 length := length(message);
290 # Append the bit '1' to the message.
291 message &:= '\16#80;';
292 # Append '0' bits, so that the resulting bit length is congruent to 448 (mod 512).
293 message &:= "\0;" mult 63 - (length + 8) mod 64;
294 # Append length of message (before pre-processing), in bits, as 64-bit little-endian integer.
295 message &:= int64AsEightBytesLe(8 * length);
296
297 # Process the message in successive 512-bit chunks:
298 while wordIndex <= length(message) do
299 # Break chunk into sixteen 32-bit little-endian words.
300 for index range 1 to 16 do
301 x[index] := bytes2Int(message[wordIndex len 4], UNSIGNED, LE);
302 wordIndex +:= 4;
303 end for;
304
305 a1 := bin32(h0);
306 b1 := bin32(h1);
307 c1 := bin32(h2);
308 d1 := bin32(h3);
309 e1 := bin32(h4);
310 a2 := bin32(h0);
311 b2 := bin32(h1);
312 c2 := bin32(h2);
313 d2 := bin32(h3);
314 e2 := bin32(h4);
315
316 for index range 1 to 80 do
317 case index of
318 when {1 .. 16}:
319 t1 := ord(b1 >< c1 >< d1); # + k1[1];
320 t2 := ord(b2 >< (c2 | ~d2)) + k2[1];
321 when {17 .. 32}:
322 t1 := ord((b1 & c1) | (~b1 & d1)) + k1[2];
323 t2 := ord((b2 & d2) | (c2 & ~d2)) + k2[2];
324 when {33 .. 48}:
325 t1 := ord((b1 | ~c1) >< d1) + k1[3];
326 t2 := ord((b2 | ~c2) >< d2) + k2[3];
327 when {49 .. 64}:
328 t1 := ord((b1 & d1) | (c1 & ~d1)) + k1[4];
329 t2 := ord((b2 & c2) | (~b2 & d2)) + k2[4];
330 when {65 .. 80}:
331 t1 := ord(b1 >< (c1 | ~d1)) + k1[5];
332 t2 := ord(b2 >< c2 >< d2); # + k2[5];
333 end case;
334 t1 +:= ord(a1) + x[r1[index]];
335 t1 := ord(rotLeft(bin32(t1 mod 16#100000000), s1[index])) + ord(e1);
336 a1 := e1;
337 e1 := d1;
338 d1 := rotLeft(c1, 10);
339 c1 := b1;
340 b1 := bin32(t1 mod 16#100000000);
341 t2 +:= ord(a2) + x[r2[index]];
342 t2 := ord(rotLeft(bin32(t2 mod 16#100000000), s2[index])) + ord(e2);
343 a2 := e2;
344 e2 := d2;
345 d2 := rotLeft(c2, 10);
346 c2 := b2;
347 b2 := bin32(t2 mod 16#100000000);
348 end for;
349
350 t1 := (h1 + ord(c1) + ord(d2)) mod 16#100000000;
351 h1 := (h2 + ord(d1) + ord(e2)) mod 16#100000000;
352 h2 := (h3 + ord(e1) + ord(a2)) mod 16#100000000;
353 h3 := (h4 + ord(a1) + ord(b2)) mod 16#100000000;
354 h4 := (h0 + ord(b1) + ord(c2)) mod 16#100000000;
355 h0 := t1;
356 end while;
357
358 # Produce the final hash value:
359 digest := int32AsFourBytesLe(h0) &
360 int32AsFourBytesLe(h1) &
361 int32AsFourBytesLe(h2) &
362 int32AsFourBytesLe(h3) &
363 int32AsFourBytesLe(h4);
364 end func;
365
366
367 (**
368 * Compute a message digest with the SHA-1 secure hash algorithm.
369 * @return the SHA-1 message digest (a string of 20 bytes).
370 * @exception RANGE_ERROR If ''message'' contains a character beyond '\255;'.
371 *)
372 const func string: sha1 (in var string: message) is func
373 result
374 var string: digest is "";
375 local
376 var integer: length is 0;
377 var integer: wordIndex is 1;
378 var integer: index is 0;
379 var array bin32: w is 80 times bin32.value;
380 var integer: h0 is 16#67452301;
381 var integer: h1 is 16#efcdab89;
382 var integer: h2 is 16#98badcfe;
383 var integer: h3 is 16#10325476;
384 var integer: h4 is 16#c3d2e1f0;
385 var bin32: a is bin32(0);
386 var bin32: b is bin32(0);
387 var bin32: c is bin32(0);
388 var bin32: d is bin32(0);
389 var bin32: e is bin32(0);
390 var bin32: f is bin32(0);
391 var bin32: g is bin32(0);
392 var integer: temp is 0;
393 var integer: k is 0;
394 begin
395 length := length(message);
396 # Append the bit '1' to the message.
397 message &:= '\16#80;';
398 # Append '0' bits, so that the resulting bit length is congruent to 448 (mod 512).
399 message &:= "\0;" mult 63 - (length + 8) mod 64;
400 # Append length of message (before pre-processing), in bits, as 64-bit big-endian integer.
401 message &:= int64AsEightBytesBe(8 * length);
402
403 # Process the message in successive 512-bit chunks:
404 while wordIndex <= length(message) do
405 # Break chunk into sixteen 32-bit big-endian words.
406 for index range 1 to 16 do
407 w[index] := bin32(bytes2Int(message[wordIndex len 4], UNSIGNED, BE));
408 wordIndex +:= 4;
409 end for;
410
411 # Extend the sixteen 32-bit words into eighty 32-bit words.
412 for index range 17 to 80 do
413 g := w[index-3] >< w[index-8] >< w[index-14] >< w[index-16];
414 w[index] := rotLeft(g, 1);
415 end for;
416
417 a := bin32(h0 mod 16#100000000);
418 b := bin32(h1 mod 16#100000000);
419 c := bin32(h2 mod 16#100000000);
420 d := bin32(h3 mod 16#100000000);
421 e := bin32(h4 mod 16#100000000);
422
423 for index range 1 to 80 do
424 if index <= 20 then
425 f := d >< (b & (c >< d));
426 k := 16#5a827999;
427 elsif index <= 40 then
428 f := b >< c >< d;
429 k := 16#6ed9eba1;
430 elsif index <= 60 then
431 f := (b & c) | (d & (b | c));
432 k := 16#8f1bbcdc;
433 else
434 f := b >< c >< d;
435 k := 16#ca62c1d6;
436 end if;
437
438 temp := ord(rotLeft(a, 5));
439 temp +:= ord(f) + ord(e) + k + ord(w[index]);
440 e := d;
441 d := c;
442 c := rotLeft(b, 30);
443 b := a;
444 a := bin32(temp mod 16#100000000);
445 end for;
446
447 # Add this chunk's hash to result so far:
448 h0 +:= ord(a);
449 h1 +:= ord(b);
450 h2 +:= ord(c);
451 h3 +:= ord(d);
452 h4 +:= ord(e);
453 end while;
454
455 # Produce the final hash value:
456 digest := int32AsFourBytesBe(h0) &
457 int32AsFourBytesBe(h1) &
458 int32AsFourBytesBe(h2) &
459 int32AsFourBytesBe(h3) &
460 int32AsFourBytesBe(h4);
461 end func;
462
463
464 (**
465 * Compute a message digest with the SHA-224 secure hash algorithm.
466 * @return the SHA-224 message digest (a string of 28 bytes).
467 * @exception RANGE_ERROR If ''message'' contains a character beyond '\255;'.
468 *)
469 const func string: sha224 (in var string: message) is func
470 result
471 var string: digest is "";
472 local
473 # Initialize array of round constants with the first 32 bits of
474 # the fractional parts of the cube roots of the first 64 primes 2..311.
475 const array integer: k is [] (
476 16#428a2f98, 16#71374491, 16#b5c0fbcf, 16#e9b5dba5, 16#3956c25b, 16#59f111f1, 16#923f82a4, 16#ab1c5ed5,
477 16#d807aa98, 16#12835b01, 16#243185be, 16#550c7dc3, 16#72be5d74, 16#80deb1fe, 16#9bdc06a7, 16#c19bf174,
478 16#e49b69c1, 16#efbe4786, 16#0fc19dc6, 16#240ca1cc, 16#2de92c6f, 16#4a7484aa, 16#5cb0a9dc, 16#76f988da,
479 16#983e5152, 16#a831c66d, 16#b00327c8, 16#bf597fc7, 16#c6e00bf3, 16#d5a79147, 16#06ca6351, 16#14292967,
480 16#27b70a85, 16#2e1b2138, 16#4d2c6dfc, 16#53380d13, 16#650a7354, 16#766a0abb, 16#81c2c92e, 16#92722c85,
481 16#a2bfe8a1, 16#a81a664b, 16#c24b8b70, 16#c76c51a3, 16#d192e819, 16#d6990624, 16#f40e3585, 16#106aa070,
482 16#19a4c116, 16#1e376c08, 16#2748774c, 16#34b0bcb5, 16#391c0cb3, 16#4ed8aa4a, 16#5b9cca4f, 16#682e6ff3,
483 16#748f82ee, 16#78a5636f, 16#84c87814, 16#8cc70208, 16#90befffa, 16#a4506ceb, 16#bef9a3f7, 16#c67178f2);
484 var integer: length is 0;
485 var integer: wordIndex is 1;
486 var integer: index is 0;
487 var array bin32: w is 64 times bin32.value;
488 # Initialize hash values with the second 32 bits of
489 # the fractional parts of the square roots of the 9th through 16th primes 23..53.
490 var integer: h0 is 16#c1059ed8;
491 var integer: h1 is 16#367cd507;
492 var integer: h2 is 16#3070dd17;
493 var integer: h3 is 16#f70e5939;
494 var integer: h4 is 16#ffc00b31;
495 var integer: h5 is 16#68581511;
496 var integer: h6 is 16#64f98fa7;
497 var integer: h7 is 16#befa4fa4;
498 var bin32: a is bin32(0);
499 var bin32: b is bin32(0);
500 var bin32: c is bin32(0);
501 var bin32: d is bin32(0);
502 var bin32: e is bin32(0);
503 var bin32: f is bin32(0);
504 var bin32: g is bin32(0);
505 var bin32: h is bin32(0);
506 var bin32: s0 is bin32(0);
507 var bin32: s1 is bin32(0);
508 var integer: temp1 is 0;
509 var integer: temp2 is 0;
510 var bin32: ch is bin32(0);
511 var bin32: maj is bin32(0);
512 begin
513 length := length(message);
514 # Append the bit '1' to the message.
515 message &:= '\16#80;';
516 # Append '0' bits, so that the resulting bit length is congruent to 448 (mod 512).
517 message &:= "\0;" mult 63 - (length + 8) mod 64;
518 # Append length of message (before pre-processing), in bits, as 64-bit big-endian integer.
519 message &:= int64AsEightBytesBe(8 * length);
520
521 # Process the message in successive 512-bit chunks:
522 while wordIndex <= length(message) do
523 # Break chunk into sixteen 32-bit big-endian words.
524 for index range 1 to 16 do
525 w[index] := bin32(bytes2Int(message[wordIndex len 4], UNSIGNED, BE));
526 wordIndex +:= 4;
527 end for;
528
529 # Extend the first 16 words into the remaining 48 words of message schedule array:
530 for index range 17 to 64 do
531 w[index] := bin32(ord(w[index-16]) +
532 ord(rotRight(w[index-15], 7) >< rotRight(w[index-15], 18) >< (w[index-15] >> 3)) +
533 ord(w[index-7]) +
534 ord(rotRight(w[index-2], 17) >< rotRight(w[index-2], 19) >< (w[index-2] >> 10))) &
535 bin32(16#ffffffff);
536 end for;
537
538 # Initialize working variables to current hash value:
539 a := bin32(h0 mod 16#100000000);
540 b := bin32(h1 mod 16#100000000);
541 c := bin32(h2 mod 16#100000000);
542 d := bin32(h3 mod 16#100000000);
543 e := bin32(h4 mod 16#100000000);
544 f := bin32(h5 mod 16#100000000);
545 g := bin32(h6 mod 16#100000000);
546 h := bin32(h7 mod 16#100000000);
547
548 # Compression function main loop:
549 for index range 1 to 64 do
550 s1 := rotRight(e, 6) >< rotRight(e, 11) >< rotRight(e, 25);
551 ch := (e & f) >< ((bin32(16#ffffffff) >< e) & g);
552 temp1 := ord(h) + ord(s1) + ord(ch) + k[index] + ord(w[index]);
553 s0 := rotRight(a, 2) >< rotRight(a, 13) >< rotRight(a, 22);
554 maj := (a & b) >< (a & c) >< (b & c);
555 temp2 := ord(s0) + ord(maj);
556
557 h := g;
558 g := f;
559 f := e;
560 e := bin32((ord(d) + temp1) mod 16#100000000);
561 d := c;
562 c := b;
563 b := a;
564 a := bin32((temp1 + temp2) mod 16#100000000);
565 end for;
566
567 # Add the compressed chunk to the current hash value:
568 h0 +:= ord(a);
569 h1 +:= ord(b);
570 h2 +:= ord(c);
571 h3 +:= ord(d);
572 h4 +:= ord(e);
573 h5 +:= ord(f);
574 h6 +:= ord(g);
575 h7 +:= ord(h);
576 end while;
577
578 # Produce the final hash value:
579 digest := int32AsFourBytesBe(h0) &
580 int32AsFourBytesBe(h1) &
581 int32AsFourBytesBe(h2) &
582 int32AsFourBytesBe(h3) &
583 int32AsFourBytesBe(h4) &
584 int32AsFourBytesBe(h5) &
585 int32AsFourBytesBe(h6);
586 end func;
587
588
589 (**
590 * Compute a message digest with the SHA-256 secure hash algorithm.
591 * @return the SHA-256 message digest (a string of 32 bytes).
592 * @exception RANGE_ERROR If ''message'' contains a character beyond '\255;'.
593 *)
594 const func string: sha256 (in var string: message) is func
595 result
596 var string: digest is "";
597 local
598 # Initialize array of round constants with the first 32 bits of
599 # the fractional parts of the cube roots of the first 64 primes 2..311.
600 const array integer: k is [] (
601 16#428a2f98, 16#71374491, 16#b5c0fbcf, 16#e9b5dba5, 16#3956c25b, 16#59f111f1, 16#923f82a4, 16#ab1c5ed5,
602 16#d807aa98, 16#12835b01, 16#243185be, 16#550c7dc3, 16#72be5d74, 16#80deb1fe, 16#9bdc06a7, 16#c19bf174,
603 16#e49b69c1, 16#efbe4786, 16#0fc19dc6, 16#240ca1cc, 16#2de92c6f, 16#4a7484aa, 16#5cb0a9dc, 16#76f988da,
604 16#983e5152, 16#a831c66d, 16#b00327c8, 16#bf597fc7, 16#c6e00bf3, 16#d5a79147, 16#06ca6351, 16#14292967,
605 16#27b70a85, 16#2e1b2138, 16#4d2c6dfc, 16#53380d13, 16#650a7354, 16#766a0abb, 16#81c2c92e, 16#92722c85,
606 16#a2bfe8a1, 16#a81a664b, 16#c24b8b70, 16#c76c51a3, 16#d192e819, 16#d6990624, 16#f40e3585, 16#106aa070,
607 16#19a4c116, 16#1e376c08, 16#2748774c, 16#34b0bcb5, 16#391c0cb3, 16#4ed8aa4a, 16#5b9cca4f, 16#682e6ff3,
608 16#748f82ee, 16#78a5636f, 16#84c87814, 16#8cc70208, 16#90befffa, 16#a4506ceb, 16#bef9a3f7, 16#c67178f2);
609 var integer: length is 0;
610 var integer: wordIndex is 1;
611 var integer: index is 0;
612 var array bin32: w is 64 times bin32.value;
613 # Initialize hash values with the first 32 bits of
614 # the fractional parts of the square roots of the first 8 primes 2..19.
615 var integer: h0 is 16#6a09e667;
616 var integer: h1 is 16#bb67ae85;
617 var integer: h2 is 16#3c6ef372;
618 var integer: h3 is 16#a54ff53a;
619 var integer: h4 is 16#510e527f;
620 var integer: h5 is 16#9b05688c;
621 var integer: h6 is 16#1f83d9ab;
622 var integer: h7 is 16#5be0cd19;
623 var bin32: a is bin32(0);
624 var bin32: b is bin32(0);
625 var bin32: c is bin32(0);
626 var bin32: d is bin32(0);
627 var bin32: e is bin32(0);
628 var bin32: f is bin32(0);
629 var bin32: g is bin32(0);
630 var bin32: h is bin32(0);
631 var bin32: s0 is bin32(0);
632 var bin32: s1 is bin32(0);
633 var integer: temp1 is 0;
634 var integer: temp2 is 0;
635 var bin32: ch is bin32(0);
636 var bin32: maj is bin32(0);
637 begin
638 length := length(message);
639 # Append the bit '1' to the message.
640 message &:= '\16#80;';
641 # Append '0' bits, so that the resulting bit length is congruent to 448 (mod 512).
642 message &:= "\0;" mult 63 - (length + 8) mod 64;
643 # Append length of message (before pre-processing), in bits, as 64-bit big-endian integer.
644 message &:= int64AsEightBytesBe(8 * length);
645
646 # Process the message in successive 512-bit chunks:
647 while wordIndex <= length(message) do
648 # Break chunk into sixteen 32-bit big-endian words.
649 for index range 1 to 16 do
650 w[index] := bin32(bytes2Int(message[wordIndex len 4], UNSIGNED, BE));
651 wordIndex +:= 4;
652 end for;
653
654 # Extend the first 16 words into the remaining 48 words of message schedule array:
655 for index range 17 to 64 do
656 w[index] := bin32(ord(w[index-16]) +
657 ord(rotRight(w[index-15], 7) >< rotRight(w[index-15], 18) >< (w[index-15] >> 3)) +
658 ord(w[index-7]) +
659 ord(rotRight(w[index-2], 17) >< rotRight(w[index-2], 19) >< (w[index-2] >> 10))) &
660 bin32(16#ffffffff);
661 end for;
662
663 # Initialize working variables to current hash value:
664 a := bin32(h0 mod 16#100000000);
665 b := bin32(h1 mod 16#100000000);
666 c := bin32(h2 mod 16#100000000);
667 d := bin32(h3 mod 16#100000000);
668 e := bin32(h4 mod 16#100000000);
669 f := bin32(h5 mod 16#100000000);
670 g := bin32(h6 mod 16#100000000);
671 h := bin32(h7 mod 16#100000000);
672
673 # Compression function main loop:
674 for index range 1 to 64 do
675 s1 := rotRight(e, 6) >< rotRight(e, 11) >< rotRight(e, 25);
676 ch := (e & f) >< ((bin32(16#ffffffff) >< e) & g);
677 temp1 := ord(h) + ord(s1) + ord(ch) + k[index] + ord(w[index]);
678 s0 := rotRight(a, 2) >< rotRight(a, 13) >< rotRight(a, 22);
679 maj := (a & b) >< (a & c) >< (b & c);
680 temp2 := ord(s0) + ord(maj);
681
682 h := g;
683 g := f;
684 f := e;
685 e := bin32((ord(d) + temp1) mod 16#100000000);
686 d := c;
687 c := b;
688 b := a;
689 a := bin32((temp1 + temp2) mod 16#100000000);
690 end for;
691
692 # Add the compressed chunk to the current hash value:
693 h0 +:= ord(a);
694 h1 +:= ord(b);
695 h2 +:= ord(c);
696 h3 +:= ord(d);
697 h4 +:= ord(e);
698 h5 +:= ord(f);
699 h6 +:= ord(g);
700 h7 +:= ord(h);
701 end while;
702
703 # Produce the final hash value:
704 digest := int32AsFourBytesBe(h0) &
705 int32AsFourBytesBe(h1) &
706 int32AsFourBytesBe(h2) &
707 int32AsFourBytesBe(h3) &
708 int32AsFourBytesBe(h4) &
709 int32AsFourBytesBe(h5) &
710 int32AsFourBytesBe(h6) &
711 int32AsFourBytesBe(h7);
712 end func;
713
714
715 (**
716 * Compute a message digest with the SHA-384 secure hash algorithm.
717 * @return the SHA-384 message digest (a string of 48 bytes).
718 * @exception RANGE_ERROR If ''message'' contains a character beyond '\255;'.
719 *)
720 const func string: sha384 (in var string: message) is func
721 result
722 var string: digest is "";
723 local
724 const bigInteger: powTwo64 is 2_**64;
725 # Initialize array of round constants with the first 64 bits of
726 # the fractional parts of the cube roots of the first 80 primes 2..409.
727 const array bigInteger: k is [] (
728 16#428a2f98d728ae22_, 16#7137449123ef65cd_, 16#b5c0fbcfec4d3b2f_, 16#e9b5dba58189dbbc_,
729 16#3956c25bf348b538_, 16#59f111f1b605d019_, 16#923f82a4af194f9b_, 16#ab1c5ed5da6d8118_,
730 16#d807aa98a3030242_, 16#12835b0145706fbe_, 16#243185be4ee4b28c_, 16#550c7dc3d5ffb4e2_,
731 16#72be5d74f27b896f_, 16#80deb1fe3b1696b1_, 16#9bdc06a725c71235_, 16#c19bf174cf692694_,
732 16#e49b69c19ef14ad2_, 16#efbe4786384f25e3_, 16#0fc19dc68b8cd5b5_, 16#240ca1cc77ac9c65_,
733 16#2de92c6f592b0275_, 16#4a7484aa6ea6e483_, 16#5cb0a9dcbd41fbd4_, 16#76f988da831153b5_,
734 16#983e5152ee66dfab_, 16#a831c66d2db43210_, 16#b00327c898fb213f_, 16#bf597fc7beef0ee4_,
735 16#c6e00bf33da88fc2_, 16#d5a79147930aa725_, 16#06ca6351e003826f_, 16#142929670a0e6e70_,
736 16#27b70a8546d22ffc_, 16#2e1b21385c26c926_, 16#4d2c6dfc5ac42aed_, 16#53380d139d95b3df_,
737 16#650a73548baf63de_, 16#766a0abb3c77b2a8_, 16#81c2c92e47edaee6_, 16#92722c851482353b_,
738 16#a2bfe8a14cf10364_, 16#a81a664bbc423001_, 16#c24b8b70d0f89791_, 16#c76c51a30654be30_,
739 16#d192e819d6ef5218_, 16#d69906245565a910_, 16#f40e35855771202a_, 16#106aa07032bbd1b8_,
740 16#19a4c116b8d2d0c8_, 16#1e376c085141ab53_, 16#2748774cdf8eeb99_, 16#34b0bcb5e19b48a8_,
741 16#391c0cb3c5c95a63_, 16#4ed8aa4ae3418acb_, 16#5b9cca4f7763e373_, 16#682e6ff3d6b2b8a3_,
742 16#748f82ee5defb2fc_, 16#78a5636f43172f60_, 16#84c87814a1f0ab72_, 16#8cc702081a6439ec_,
743 16#90befffa23631e28_, 16#a4506cebde82bde9_, 16#bef9a3f7b2c67915_, 16#c67178f2e372532b_,
744 16#ca273eceea26619c_, 16#d186b8c721c0c207_, 16#eada7dd6cde0eb1e_, 16#f57d4f7fee6ed178_,
745 16#06f067aa72176fba_, 16#0a637dc5a2c898a6_, 16#113f9804bef90dae_, 16#1b710b35131c471b_,
746 16#28db77f523047d84_, 16#32caab7b40c72493_, 16#3c9ebe0a15c9bebc_, 16#431d67c49c100d4c_,
747 16#4cc5d4becb3e42b6_, 16#597f299cfc657e2a_, 16#5fcb6fab3ad6faec_, 16#6c44198c4a475817_);
748 var integer: length is 0;
749 var integer: chunkIndex is 0;
750 var integer: index is 0;
751 var array bin64: w is 80 times bin64.value;
752 # Initialize hash values with the first 64 bits of
753 # the fractional parts of the square roots of the first 8 primes 2..19.
754 var bigInteger: h0 is 16#cbbb9d5dc1059ed8_;
755 var bigInteger: h1 is 16#629a292a367cd507_;
756 var bigInteger: h2 is 16#9159015a3070dd17_;
757 var bigInteger: h3 is 16#152fecd8f70e5939_;
758 var bigInteger: h4 is 16#67332667ffc00b31_;
759 var bigInteger: h5 is 16#8eb44a8768581511_;
760 var bigInteger: h6 is 16#db0c2e0d64f98fa7_;
761 var bigInteger: h7 is 16#47b5481dbefa4fa4_;
762 var bin64: a is bin64(0);
763 var bin64: b is bin64(0);
764 var bin64: c is bin64(0);
765 var bin64: d is bin64(0);
766 var bin64: e is bin64(0);
767 var bin64: f is bin64(0);
768 var bin64: g is bin64(0);
769 var bin64: h is bin64(0);
770 var bin64: s0 is bin64(0);
771 var bin64: s1 is bin64(0);
772 var bin64: temp1 is bin64(0);
773 var bin64: temp2 is bin64(0);
774 var bin64: ch is bin64(0);
775 var bin64: maj is bin64(0);
776 begin
777 length := length(message);
778 # Append the bit '1' to the message.
779 message &:= '\16#80;';
780 # Append '0' bits, so that the resulting bit length is congruent to 448 (mod 1024).
781 message &:= "\0;" mult 127 - (length + 8) mod 128;
782 # Append length of message (before pre-processing), in bits, as 64-bit big-endian integer.
783 message &:= int64AsEightBytesBe(8 * length);
784
785 # Process the message in successive 1024-bit chunks:
786 for chunkIndex range 1 to length(message) step 128 do
787 # Check that the input contains no character beyond '\255;'.
788 for index range 0 to 127 do
789 if ord(message[chunkIndex + index]) > 255 then
790 raise RANGE_ERROR;
791 end if;
792 end for;
793
794 # Break chunk into sixteen 64-bit big-endian words.
795 for index range 1 to 16 do
796 w[index] := bin64(message[chunkIndex + 8 * pred(index) len 8], BE);
797 end for;
798
799 # Extend the first 16 words into the remaining 64 words of message schedule array:
800 for index range 17 to 80 do
801 w[index] := bin64((big(w[index-16]) +
802 big(rotRight(w[index-15], 1) ><
803 rotRight(w[index-15], 8) ><
804 (w[index-15] >> 7)) +
805 big(w[index-7]) +
806 big(rotRight(w[index-2], 19) ><
807 rotRight(w[index-2], 61) ><
808 (w[index-2] >> 6))) mod powTwo64);
809 end for;
810
811 # Initialize working variables to current hash value:
812 a := bin64(h0 mod powTwo64);
813 b := bin64(h1 mod powTwo64);
814 c := bin64(h2 mod powTwo64);
815 d := bin64(h3 mod powTwo64);
816 e := bin64(h4 mod powTwo64);
817 f := bin64(h5 mod powTwo64);
818 g := bin64(h6 mod powTwo64);
819 h := bin64(h7 mod powTwo64);
820
821 # Compression function main loop:
822 for index range 1 to 80 do
823 s1 := rotRight(e, 14) >< rotRight(e, 18) >< rotRight(e, 41);
824 ch := (e & f) >< (~e & g);
825 temp1 := bin64((big(h) + big(s1) + big(ch) + k[index] + big(w[index])) mod powTwo64);
826 s0 := rotRight(a, 28) >< rotRight(a, 34) >< rotRight(a, 39);
827 maj := (a & b) >< (a & c) >< (b & c);
828 temp2 := bin64((big(s0) + big(maj)) mod powTwo64);
829
830 h := g;
831 g := f;
832 f := e;
833 e := bin64((big(d) + big(temp1)) mod powTwo64);
834 d := c;
835 c := b;
836 b := a;
837 a := bin64((big(temp1) + big(temp2)) mod powTwo64);
838 end for;
839
840 # Add the compressed chunk to the current hash value:
841 h0 +:= big(a);
842 h1 +:= big(b);
843 h2 +:= big(c);
844 h3 +:= big(d);
845 h4 +:= big(e);
846 h5 +:= big(f);
847 h6 +:= big(g);
848 h7 +:= big(h);
849 end for;
850
851 # Produce the final hash value:
852 digest := bigAsEightBytesBe(h0) &
853 bigAsEightBytesBe(h1) &
854 bigAsEightBytesBe(h2) &
855 bigAsEightBytesBe(h3) &
856 bigAsEightBytesBe(h4) &
857 bigAsEightBytesBe(h5);
858 end func;
859
860
861 (**
862 * Compute a message digest with the SHA-512 secure hash algorithm.
863 * @return the SHA-512 message digest (a string of 64 bytes).
864 * @exception RANGE_ERROR If ''message'' contains a character beyond '\255;'.
865 *)
866 const func string: sha512 (in var string: message) is func
867 result
868 var string: digest is "";
869 local
870 const bigInteger: powTwo64 is 2_**64;
871 # Initialize array of round constants with the first 64 bits of
872 # the fractional parts of the cube roots of the first 80 primes 2..409.
873 const array bigInteger: k is [] (
874 16#428a2f98d728ae22_, 16#7137449123ef65cd_, 16#b5c0fbcfec4d3b2f_, 16#e9b5dba58189dbbc_,
875 16#3956c25bf348b538_, 16#59f111f1b605d019_, 16#923f82a4af194f9b_, 16#ab1c5ed5da6d8118_,
876 16#d807aa98a3030242_, 16#12835b0145706fbe_, 16#243185be4ee4b28c_, 16#550c7dc3d5ffb4e2_,
877 16#72be5d74f27b896f_, 16#80deb1fe3b1696b1_, 16#9bdc06a725c71235_, 16#c19bf174cf692694_,
878 16#e49b69c19ef14ad2_, 16#efbe4786384f25e3_, 16#0fc19dc68b8cd5b5_, 16#240ca1cc77ac9c65_,
879 16#2de92c6f592b0275_, 16#4a7484aa6ea6e483_, 16#5cb0a9dcbd41fbd4_, 16#76f988da831153b5_,
880 16#983e5152ee66dfab_, 16#a831c66d2db43210_, 16#b00327c898fb213f_, 16#bf597fc7beef0ee4_,
881 16#c6e00bf33da88fc2_, 16#d5a79147930aa725_, 16#06ca6351e003826f_, 16#142929670a0e6e70_,
882 16#27b70a8546d22ffc_, 16#2e1b21385c26c926_, 16#4d2c6dfc5ac42aed_, 16#53380d139d95b3df_,
883 16#650a73548baf63de_, 16#766a0abb3c77b2a8_, 16#81c2c92e47edaee6_, 16#92722c851482353b_,
884 16#a2bfe8a14cf10364_, 16#a81a664bbc423001_, 16#c24b8b70d0f89791_, 16#c76c51a30654be30_,
885 16#d192e819d6ef5218_, 16#d69906245565a910_, 16#f40e35855771202a_, 16#106aa07032bbd1b8_,
886 16#19a4c116b8d2d0c8_, 16#1e376c085141ab53_, 16#2748774cdf8eeb99_, 16#34b0bcb5e19b48a8_,
887 16#391c0cb3c5c95a63_, 16#4ed8aa4ae3418acb_, 16#5b9cca4f7763e373_, 16#682e6ff3d6b2b8a3_,
888 16#748f82ee5defb2fc_, 16#78a5636f43172f60_, 16#84c87814a1f0ab72_, 16#8cc702081a6439ec_,
889 16#90befffa23631e28_, 16#a4506cebde82bde9_, 16#bef9a3f7b2c67915_, 16#c67178f2e372532b_,
890 16#ca273eceea26619c_, 16#d186b8c721c0c207_, 16#eada7dd6cde0eb1e_, 16#f57d4f7fee6ed178_,
891 16#06f067aa72176fba_, 16#0a637dc5a2c898a6_, 16#113f9804bef90dae_, 16#1b710b35131c471b_,
892 16#28db77f523047d84_, 16#32caab7b40c72493_, 16#3c9ebe0a15c9bebc_, 16#431d67c49c100d4c_,
893 16#4cc5d4becb3e42b6_, 16#597f299cfc657e2a_, 16#5fcb6fab3ad6faec_, 16#6c44198c4a475817_);
894 var integer: length is 0;
895 var integer: chunkIndex is 0;
896 var integer: index is 0;
897 var array bin64: w is 80 times bin64.value;
898 # Initialize hash values with the first 64 bits of
899 # the fractional parts of the square roots of the first 8 primes 2..19.
900 var bigInteger: h0 is 16#6a09e667f3bcc908_;
901 var bigInteger: h1 is 16#bb67ae8584caa73b_;
902 var bigInteger: h2 is 16#3c6ef372fe94f82b_;
903 var bigInteger: h3 is 16#a54ff53a5f1d36f1_;
904 var bigInteger: h4 is 16#510e527fade682d1_;
905 var bigInteger: h5 is 16#9b05688c2b3e6c1f_;
906 var bigInteger: h6 is 16#1f83d9abfb41bd6b_;
907 var bigInteger: h7 is 16#5be0cd19137e2179_;
908 var bin64: a is bin64(0);
909 var bin64: b is bin64(0);
910 var bin64: c is bin64(0);
911 var bin64: d is bin64(0);
912 var bin64: e is bin64(0);
913 var bin64: f is bin64(0);
914 var bin64: g is bin64(0);
915 var bin64: h is bin64(0);
916 var bin64: s0 is bin64(0);
917 var bin64: s1 is bin64(0);
918 var bin64: temp1 is bin64(0);
919 var bin64: temp2 is bin64(0);
920 var bin64: ch is bin64(0);
921 var bin64: maj is bin64(0);
922 begin
923 length := length(message);
924 # Append the bit '1' to the message.
925 message &:= '\16#80;';
926 # Append '0' bits, so that the resulting bit length is congruent to 448 (mod 1024).
927 message &:= "\0;" mult 127 - (length + 8) mod 128;
928 # Append length of message (before pre-processing), in bits, as 64-bit big-endian integer.
929 message &:= int64AsEightBytesBe(8 * length);
930
931 # Process the message in successive 1024-bit chunks:
932 for chunkIndex range 1 to length(message) step 128 do
933 # Check that the input contains no character beyond '\255;'.
934 for index range 0 to 127 do
935 if ord(message[chunkIndex + index]) > 255 then
936 raise RANGE_ERROR;
937 end if;
938 end for;
939
940 # Break chunk into sixteen 64-bit big-endian words.
941 for index range 1 to 16 do
942 w[index] := bin64(message[chunkIndex + 8 * pred(index) len 8], BE);
943 end for;
944
945 # Extend the first 16 words into the remaining 64 words of message schedule array:
946 for index range 17 to 80 do
947 w[index] := bin64((big(w[index-16]) +
948 big(rotRight(w[index-15], 1) ><
949 rotRight(w[index-15], 8) ><
950 (w[index-15] >> 7)) +
951 big(w[index-7]) +
952 big(rotRight(w[index-2], 19) ><
953 rotRight(w[index-2], 61) ><
954 (w[index-2] >> 6))) mod powTwo64);
955 end for;
956
957 # Initialize working variables to current hash value:
958 a := bin64(h0 mod powTwo64);
959 b := bin64(h1 mod powTwo64);
960 c := bin64(h2 mod powTwo64);
961 d := bin64(h3 mod powTwo64);
962 e := bin64(h4 mod powTwo64);
963 f := bin64(h5 mod powTwo64);
964 g := bin64(h6 mod powTwo64);
965 h := bin64(h7 mod powTwo64);
966
967 # Compression function main loop:
968 for index range 1 to 80 do
969 s1 := rotRight(e, 14) >< rotRight(e, 18) >< rotRight(e, 41);
970 ch := (e & f) >< (~e & g);
971 temp1 := bin64((big(h) + big(s1) + big(ch) + k[index] + big(w[index])) mod powTwo64);
972 s0 := rotRight(a, 28) >< rotRight(a, 34) >< rotRight(a, 39);
973 maj := (a & b) >< (a & c) >< (b & c);
974 temp2 := bin64((big(s0) + big(maj)) mod powTwo64);
975
976 h := g;
977 g := f;
978 f := e;
979 e := bin64((big(d) + big(temp1)) mod powTwo64);
980 d := c;
981 c := b;
982 b := a;
983 a := bin64((big(temp1) + big(temp2)) mod powTwo64);
984 end for;
985
986 # Add the compressed chunk to the current hash value:
987 h0 +:= big(a);
988 h1 +:= big(b);
989 h2 +:= big(c);
990 h3 +:= big(d);
991 h4 +:= big(e);
992 h5 +:= big(f);
993 h6 +:= big(g);
994 h7 +:= big(h);
995 end for;
996
997 # Produce the final hash value:
998 digest := bigAsEightBytesBe(h0) &
999 bigAsEightBytesBe(h1) &
1000 bigAsEightBytesBe(h2) &
1001 bigAsEightBytesBe(h3) &
1002 bigAsEightBytesBe(h4) &
1003 bigAsEightBytesBe(h5) &
1004 bigAsEightBytesBe(h6) &
1005 bigAsEightBytesBe(h7);
1006 end func;
1007
1008
1009 (**
1010 * Enumeration of message digest algorithms.
1011 * Defines: NO_DIGEST, MD4, MD5, RIPEMD160, SHA1, SHA224, SHA256, SHA384 and SHA512.
1012 *)
1013 const type: digestAlgorithm is new enum
1014 NO_DIGEST, MD4, MD5, RIPEMD160, SHA1, SHA224, SHA256, SHA384, SHA512
1015 end enum;
1016
1017
1018 (**
1019 * Compute a message digest with the given [[msgdigest#digestAlgorithm|digestAlgorithm]].
1020 * @param digestAlg The [[msgdigest#digestAlgorithm|digestAlgorithm]] to be used.
1021 * @return the message digest of the ''message''.
1022 * @exception RANGE_ERROR If ''message'' contains a character beyond '\255;'.
1023 *)
1024 const func string: msgDigest (in digestAlgorithm: digestAlg, in string: message) is DYNAMIC;
1025
1026 const func string: msgDigest (NO_DIGEST, in string: message) is return "";
1027 const func string: msgDigest (MD4, in string: message) is return md4(message);
1028 const func string: msgDigest (MD5, in string: message) is return md5(message);
1029 const func string: msgDigest (RIPEMD160, in string: message) is return ripemd160(message);
1030 const func string: msgDigest (SHA1, in string: message) is return sha1(message);
1031 const func string: msgDigest (SHA224, in string: message) is return sha224(message);
1032 const func string: msgDigest (SHA256, in string: message) is return sha256(message);
1033 const func string: msgDigest (SHA384, in string: message) is return sha384(message);
1034 const func string: msgDigest (SHA512, in string: message) is return sha512(message);
1035
1036
1037 (**
1038 * Block size used by the given [[msgdigest#digestAlgorithm|digestAlgorithm]].
1039 * @return the block size in bytes used by the message digest algorithm.
1040 *)
1041 const func integer: blockSize (in digestAlgorithm: digestAlg) is DYNAMIC;
1042
1043 const func integer: blockSize (NO_DIGEST) is 0;
1044 const func integer: blockSize (MD4) is 64;
1045 const func integer: blockSize (MD5) is 64;
1046 const func integer: blockSize (RIPEMD160) is 64;
1047 const func integer: blockSize (SHA1) is 64;
1048 const func integer: blockSize (SHA224) is 64;
1049 const func integer: blockSize (SHA256) is 64;
1050 const func integer: blockSize (SHA384) is 128;
1051 const func integer: blockSize (SHA512) is 128;
1052
1053
1054 (**
1055 * Size of a message digest computed with the given [[msgdigest#digestAlgorithm|digestAlgorithm]].
1056 * @return the size of a message digest in bytes.
1057 *)
1058 const func integer: digestSize (in digestAlgorithm: digestAlg) is DYNAMIC;
1059
1060 const func integer: digestSize (NO_DIGEST) is 0;
1061 const func integer: digestSize (MD4) is 16;
1062 const func integer: digestSize (MD5) is 16;
1063 const func integer: digestSize (RIPEMD160) is 20;
1064 const func integer: digestSize (SHA1) is 20;
1065 const func integer: digestSize (SHA224) is 28;
1066 const func integer: digestSize (SHA256) is 32;
1067 const func integer: digestSize (SHA384) is 48;
1068 const func integer: digestSize (SHA512) is 64;