2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,3 +1,4 @@
NB. convert/misc/md5
NB. RSA Data Security, Inc. MD5 Message-Digest Algorithm
NB. version: 1.0.2
NB.
@ -6,18 +7,32 @@ NB. J implementation -- (C) 2003 Oleg Kobchenko;
NB.
NB. 09/04/2003 Oleg Kobchenko
NB. 03/31/2007 Oleg Kobchenko j601, JAL
NB. 12/17/2015 G.Pruss 64-bit
NB. ~60+ times slower than using the jqt library
require 'convert'
coclass 'pcrypt'
NB. lt= (*. -.)~ gt= *. -. ge= +. -. xor= ~:
'`lt gt ge xor'=: (20 b.)`(18 b.)`(27 b.)`(22 b.)
'`and or rot sh'=: (17 b.)`(23 b.)`(32 b.)`(33 b.)
'`and or sh'=: (17 b.)`(23 b.)`(33 b.)
3 : 0 ''
if. IF64 do.
rot=: (16bffffffff and sh or ] sh~ 32 -~ [) NB. (y << x) | (y >>> (32 - x))
add=: ((16bffffffff&and)@+)"0
else.
rot=: (32 b.)
add=: (+&(_16&sh) (16&sh@(+ _16&sh) or and&65535@]) +&(and&65535))"0
end.
EMPTY
)
hexlist=: tolower@:,@:hfd@:,@:(|."1)@(256 256 256 256&#:)
cmn=: 4 : 0
'x s t'=. x [ 'q a b'=. y
b add s rot (a add q) add (x add t)
'x s t'=. x [ 'q a b'=. y
b add s rot (a add q) add (x add t)
)
ff=: cmn (((1&{ and 2&{) or 1&{ lt 3&{) , 2&{.)
@ -27,55 +42,57 @@ ii=: cmn (( 2&{ xor 1&{ ge 3&{ ) , 2&{.)
op=: ff`gg`hh`ii
I=: ".;._2(0 : 0)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 6 11 0 5 10 15 4 9 14 3 8 13 2 7 12
5 8 11 14 1 4 7 10 13 0 3 6 9 12 15 2
0 7 14 5 12 3 10 1 8 15 6 13 4 11 2 9
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 6 11 0 5 10 15 4 9 14 3 8 13 2 7 12
5 8 11 14 1 4 7 10 13 0 3 6 9 12 15 2
0 7 14 5 12 3 10 1 8 15 6 13 4 11 2 9
)
S=: 4 4$7 12 17 22 5 9 14 20 4 11 16 23 6 10 15 21
T=: |:".;._2(0 : 0)
_680876936 _165796510 _378558 _198630844
_389564586 _1069501632 _2022574463 1126891415
606105819 643717713 1839030562 _1416354905
_1044525330 _373897302 _35309556 _57434055
_176418897 _701558691 _1530992060 1700485571
1200080426 38016083 1272893353 _1894986606
_1473231341 _660478335 _155497632 _1051523
_45705983 _405537848 _1094730640 _2054922799
1770035416 568446438 681279174 1873313359
_1958414417 _1019803690 _358537222 _30611744
_42063 _187363961 _722521979 _1560198380
_1990404162 1163531501 76029189 1309151649
1804603682 _1444681467 _640364487 _145523070
_40341101 _51403784 _421815835 _1120210379
_1502002290 1735328473 530742520 718787259
1236535329 _1926607734 _995338651 _343485551
_680876936 _165796510 _378558 _198630844
_389564586 _1069501632 _2022574463 1126891415
606105819 643717713 1839030562 _1416354905
_1044525330 _373897302 _35309556 _57434055
_176418897 _701558691 _1530992060 1700485571
1200080426 38016083 1272893353 _1894986606
_1473231341 _660478335 _155497632 _1051523
_45705983 _405537848 _1094730640 _2054922799
1770035416 568446438 681279174 1873313359
_1958414417 _1019803690 _358537222 _30611744
_42063 _187363961 _722521979 _1560198380
_1990404162 1163531501 76029189 1309151649
1804603682 _1444681467 _640364487 _145523070
_40341101 _51403784 _421815835 _1120210379
_1502002290 1735328473 530742520 718787259
1236535329 _1926607734 _995338651 _343485551
)
norm=: 3 : 0
n=. 16 * 1 + _6 sh 8 + #y
b=. n#0 [ y=. a.i.y
for_i. i. #y do.
b=. ((j { b) or (8*4|i) sh i{y) (j=. _2 sh i) } b
end.
b=. ((j { b) or (8*4|i) sh 128) (j=._2 sh i=.#y) } b
_16]\ (8 * #y) (n-2) } b
n=. 16 * 1 + _6 sh 8 + #y
b=. n#0 [ y=. a.i.y
for_i. i. #y do.
b=. ((j { b) or (8*4|i) sh i{y) (j=. _2 sh i) } b
end.
b=. ((j { b) or (8*4|i) sh 128) (j=._2 sh i=.#y) } b
_16]\ (8 * #y) (n-2) } b
)
NB.*md5 v MD5 Message-Digest Algorithm
NB. diagest=. md5 message
md5=: 3 : 0
X=. norm y
q=. r=. 1732584193 _271733879 _1732584194 271733878
for_x. X do.
for_j. i.4 do.
l=. ((j{I){x) ,. (16$j{S) ,. j{T
for_i. i.16 do.
r=. _1|.((i{l) (op@.j) r),}.r
end.
X=. norm y
q=. r=. 1732584193 _271733879 _1732584194 271733878
for_x. X do.
for_j. i.4 do.
l=. ((j{I){x) ,. (16$j{S) ,. j{T
for_i. i.16 do.
r=. _1|.((i{l) (op@.j) r),}.r
end.
q=. r=. r add q
end.
hexlist r
q=. r=. r add q
end.
hexlist r
)
md5_z_=: md5_pcrypt_

View file

@ -1,25 +1,22 @@
use Test;
sub infix:<>(uint32 $a, uint32 $b --> uint32) { ($a + $b) +& 0xffffffff }
sub infix:«<<<»(uint32 $a, UInt $n --> uint32) { ($a +< $n) +& 0xffffffff +| ($a +> (32-$n)) }
sub prefix:<¬>(\x) { (+^ x) % 2**32 }
sub infix:<>(\x, \y) { (x + y) % 2**32 }
sub infix:«<<<»(\x, \n) { (x +< n) % 2**32 +| (x +> (32-n)) }
constant FGHI = { ($^a +& $^b) +| (+^$a +& $^c) },
{ ($^a +& $^c) +| ($^b +& +^$c) },
{ $^a +^ $^b +^ $^c },
{ $^b +^ ($^a +| +^$^c) };
constant FGHI = -> \X, \Y, \Z { (X +& Y) +| (¬X +& Z) },
-> \X, \Y, \Z { (X +& Z) +| (Y +& ¬Z) },
-> \X, \Y, \Z { X +^ Y +^ Z },
-> \X, \Y, \Z { Y +^ (X +| ¬Z) };
constant S = flat (7, 12, 17, 22) xx 4,
(5, 9, 14, 20) xx 4,
(4, 11, 16, 23) xx 4,
(6, 10, 15, 21) xx 4;
constant _S = flat (7, 12, 17, 22) xx 4,
(5, 9, 14, 20) xx 4,
(4, 11, 16, 23) xx 4,
(6, 10, 15, 21) xx 4;
constant T = (floor(abs(sin($_ + 1)) * 2**32) for ^64);
constant k = flat ( $_ for ^16),
((5*$_ + 1) % 16 for ^16),
((3*$_ + 5) % 16 for ^16),
((7*$_ ) % 16 for ^16);
((5*$_ + 1) % 16 for ^16),
((3*$_ + 5) % 16 for ^16),
((7*$_ ) % 16 for ^16);
sub little-endian($w, $n, *@v) {
my \step1 = ($w X* ^$n).eager; # temporary bug workaround
@ -34,25 +31,24 @@ sub md5-pad(Blob $msg)
flat @padded.map({ :256[$^d,$^c,$^b,$^a] }), little-endian(32, 2, bits);
}
sub md5-block(@H is rw, @X)
sub md5-block(@H, @X)
{
my ($A, $B, $C, $D) = @H;
for ^64 -> \i {
my \f = FGHI[i div 16]($B, $C, $D);
($A, $B, $C, $D)
= ($D, $B(($AfT[i]@X[k[i]]) <<< S[i]), $B, $C);
}
my uint32 ($A, $B, $C, $D) = @H;
($A, $B, $C, $D) = ($D, $B(($AFGHI[$_ div 16]($B, $C, $D)T[$_]@X[k[$_]]) <<< _S[$_]), $B, $C) for ^64;
@H «=» ($A, $B, $C, $D);
}
sub md5(Blob $msg --> Blob)
{
my @M = md5-pad($msg);
my @H = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476;
my uint32 @M = md5-pad($msg);
my uint32 @H = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476;
md5-block(@H, @M[$_ .. $_+15]) for 0, 16 ...^ +@M;
Blob.new: little-endian(8, 4, @H);
}
use Test;
plan 7;
for 'd41d8cd98f00b204e9800998ecf8427e', '',
'0cc175b9c0f1b6a831c399e269772661', 'a',
'900150983cd24fb0d6963f7d28e17f72', 'abc',

View file

@ -0,0 +1,164 @@
use strict;
use warnings;
use integer;
use Test::More;
BEGIN { plan tests => 7 }
sub A() { 0x67_45_23_01 }
sub B() { 0xef_cd_ab_89 }
sub C() { 0x98_ba_dc_fe }
sub D() { 0x10_32_54_76 }
sub MAX() { 0xFFFFFFFF }
sub padding {
my $l = length (my $msg = shift() . chr(128));
$msg .= "\0" x (($l%64<=56?56:120)-$l%64);
$l = ($l-1)*8;
$msg .= pack 'VV', $l & MAX , ($l >> 16 >> 16);
}
sub rotate_left($$) {
($_[0] << $_[1]) | (( $_[0] >> (32 - $_[1]) ) & ((1 << $_[1]) - 1));
}
sub gen_code {
# Discard upper 32 bits on 64 bit archs.
my $MSK = ((1 << 16) << 16) ? ' & ' . MAX : '';
my %f = (
FF => "X0=rotate_left((X3^(X1&(X2^X3)))+X0+X4+X6$MSK,X5)+X1$MSK;",
GG => "X0=rotate_left((X2^(X3&(X1^X2)))+X0+X4+X6$MSK,X5)+X1$MSK;",
HH => "X0=rotate_left((X1^X2^X3)+X0+X4+X6$MSK,X5)+X1$MSK;",
II => "X0=rotate_left((X2^(X1|(~X3)))+X0+X4+X6$MSK,X5)+X1$MSK;",
);
my %s = ( # shift lengths
S11 => 7, S12 => 12, S13 => 17, S14 => 22, S21 => 5, S22 => 9, S23 => 14,
S24 => 20, S31 => 4, S32 => 11, S33 => 16, S34 => 23, S41 => 6, S42 => 10,
S43 => 15, S44 => 21
);
my $insert = "\n";
while(defined( my $data = <DATA> )) {
chomp $data;
next unless $data =~ /^[FGHI]/;
my ($func,@x) = split /,/, $data;
my $c = $f{$func};
$c =~ s/X(\d)/$x[$1]/g;
$c =~ s/(S\d{2})/$s{$1}/;
$c =~ s/^(.*)=rotate_left\((.*),(.*)\)\+(.*)$//;
my $su = 32 - $3;
my $sh = (1 << $3) - 1;
$c = "$1=(((\$r=$2)<<$3)|((\$r>>$su)&$sh))+$4";
$insert .= "\t$c\n";
}
close DATA;
my $dump = '
sub round {
my ($a,$b,$c,$d) = @_[0 .. 3];
my $r;' . $insert . '
$_[0]+$a' . $MSK . ', $_[1]+$b ' . $MSK .
', $_[2]+$c' . $MSK . ', $_[3]+$d' . $MSK . ';
}';
eval $dump;
}
gen_code();
sub _encode_hex { unpack 'H*', $_[0] }
sub md5 {
my $message = padding(join'',@_);
my ($a,$b,$c,$d) = (A,B,C,D);
my $i;
for $i (0 .. (length $message)/64-1) {
my @X = unpack 'V16', substr $message,$i*64,64;
($a,$b,$c,$d) = round($a,$b,$c,$d,@X);
}
pack 'V4',$a,$b,$c,$d;
}
my $strings = {
'd41d8cd98f00b204e9800998ecf8427e' => '',
'0cc175b9c0f1b6a831c399e269772661' => 'a',
'900150983cd24fb0d6963f7d28e17f72' => 'abc',
'f96b697d7cb7938d525a2f31aaf161d0' => 'message digest',
'c3fcd3d76192e4007dfb496cca67e13b' => 'abcdefghijklmnopqrstuvwxyz',
'd174ab98d277d9f5a5611c2c9f419d9f' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
'57edf4a22be3c955ac49da2e2107b67a' => '12345678901234567890123456789012345678901234567890123456789012345678901234567890',
};
for my $k (keys %$strings) {
my $digest = _encode_hex md5($strings->{$k});
is($digest, $k, "$digest is MD5 digest $strings->{$k}");
}
__DATA__
FF,$a,$b,$c,$d,$_[4],7,0xd76aa478,/* 1 */
FF,$d,$a,$b,$c,$_[5],12,0xe8c7b756,/* 2 */
FF,$c,$d,$a,$b,$_[6],17,0x242070db,/* 3 */
FF,$b,$c,$d,$a,$_[7],22,0xc1bdceee,/* 4 */
FF,$a,$b,$c,$d,$_[8],7,0xf57c0faf,/* 5 */
FF,$d,$a,$b,$c,$_[9],12,0x4787c62a,/* 6 */
FF,$c,$d,$a,$b,$_[10],17,0xa8304613,/* 7 */
FF,$b,$c,$d,$a,$_[11],22,0xfd469501,/* 8 */
FF,$a,$b,$c,$d,$_[12],7,0x698098d8,/* 9 */
FF,$d,$a,$b,$c,$_[13],12,0x8b44f7af,/* 10 */
FF,$c,$d,$a,$b,$_[14],17,0xffff5bb1,/* 11 */
FF,$b,$c,$d,$a,$_[15],22,0x895cd7be,/* 12 */
FF,$a,$b,$c,$d,$_[16],7,0x6b901122,/* 13 */
FF,$d,$a,$b,$c,$_[17],12,0xfd987193,/* 14 */
FF,$c,$d,$a,$b,$_[18],17,0xa679438e,/* 15 */
FF,$b,$c,$d,$a,$_[19],22,0x49b40821,/* 16 */
GG,$a,$b,$c,$d,$_[5],5,0xf61e2562,/* 17 */
GG,$d,$a,$b,$c,$_[10],9,0xc040b340,/* 18 */
GG,$c,$d,$a,$b,$_[15],14,0x265e5a51,/* 19 */
GG,$b,$c,$d,$a,$_[4],20,0xe9b6c7aa,/* 20 */
GG,$a,$b,$c,$d,$_[9],5,0xd62f105d,/* 21 */
GG,$d,$a,$b,$c,$_[14],9,0x2441453,/* 22 */
GG,$c,$d,$a,$b,$_[19],14,0xd8a1e681,/* 23 */
GG,$b,$c,$d,$a,$_[8],20,0xe7d3fbc8,/* 24 */
GG,$a,$b,$c,$d,$_[13],5,0x21e1cde6,/* 25 */
GG,$d,$a,$b,$c,$_[18],9,0xc33707d6,/* 26 */
GG,$c,$d,$a,$b,$_[7],14,0xf4d50d87,/* 27 */
GG,$b,$c,$d,$a,$_[12],20,0x455a14ed,/* 28 */
GG,$a,$b,$c,$d,$_[17],5,0xa9e3e905,/* 29 */
GG,$d,$a,$b,$c,$_[6],9,0xfcefa3f8,/* 30 */
GG,$c,$d,$a,$b,$_[11],14,0x676f02d9,/* 31 */
GG,$b,$c,$d,$a,$_[16],20,0x8d2a4c8a,/* 32 */
HH,$a,$b,$c,$d,$_[9],4,0xfffa3942,/* 33 */
HH,$d,$a,$b,$c,$_[12],11,0x8771f681,/* 34 */
HH,$c,$d,$a,$b,$_[15],16,0x6d9d6122,/* 35 */
HH,$b,$c,$d,$a,$_[18],23,0xfde5380c,/* 36 */
HH,$a,$b,$c,$d,$_[5],4,0xa4beea44,/* 37 */
HH,$d,$a,$b,$c,$_[8],11,0x4bdecfa9,/* 38 */
HH,$c,$d,$a,$b,$_[11],16,0xf6bb4b60,/* 39 */
HH,$b,$c,$d,$a,$_[14],23,0xbebfbc70,/* 40 */
HH,$a,$b,$c,$d,$_[17],4,0x289b7ec6,/* 41 */
HH,$d,$a,$b,$c,$_[4],11,0xeaa127fa,/* 42 */
HH,$c,$d,$a,$b,$_[7],16,0xd4ef3085,/* 43 */
HH,$b,$c,$d,$a,$_[10],23,0x4881d05,/* 44 */
HH,$a,$b,$c,$d,$_[13],4,0xd9d4d039,/* 45 */
HH,$d,$a,$b,$c,$_[16],11,0xe6db99e5,/* 46 */
HH,$c,$d,$a,$b,$_[19],16,0x1fa27cf8,/* 47 */
HH,$b,$c,$d,$a,$_[6],23,0xc4ac5665,/* 48 */
II,$a,$b,$c,$d,$_[4],6,0xf4292244,/* 49 */
II,$d,$a,$b,$c,$_[11],10,0x432aff97,/* 50 */
II,$c,$d,$a,$b,$_[18],15,0xab9423a7,/* 51 */
II,$b,$c,$d,$a,$_[9],21,0xfc93a039,/* 52 */
II,$a,$b,$c,$d,$_[16],6,0x655b59c3,/* 53 */
II,$d,$a,$b,$c,$_[7],10,0x8f0ccc92,/* 54 */
II,$c,$d,$a,$b,$_[14],15,0xffeff47d,/* 55 */
II,$b,$c,$d,$a,$_[5],21,0x85845dd1,/* 56 */
II,$a,$b,$c,$d,$_[12],6,0x6fa87e4f,/* 57 */
II,$d,$a,$b,$c,$_[19],10,0xfe2ce6e0,/* 58 */
II,$c,$d,$a,$b,$_[10],15,0xa3014314,/* 59 */
II,$b,$c,$d,$a,$_[17],21,0x4e0811a1,/* 60 */
II,$a,$b,$c,$d,$_[8],6,0xf7537e82,/* 61 */
II,$d,$a,$b,$c,$_[15],10,0xbd3af235,/* 62 */
II,$c,$d,$a,$b,$_[6],15,0x2ad7d2bb,/* 63 */
II,$b,$c,$d,$a,$_[13],21,0xeb86d391,/* 64 */

View file

@ -1,124 +1,115 @@
/*REXX program to test the MD5 procedure as per the test suite in the */
/* IETF RFC (1321) ─── The MD5 Message─Digest Algorithm. April 1992. */
/*REXX program tests the MD5 procedure (below) as per a test suite the IETF RFC (1321).*/
msg.1 = /*─────MD5 test suite [from above doc].*/
msg.2 = 'a'
msg.3 = 'abc'
msg.4 = 'message digest'
msg.5 = 'abcdefghijklmnopqrstuvwxyz'
msg.6 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
msg.7 = 12345678901234567890123456789012345678901234567890123456789012345678901234567890
msg.0 = 7 /* [↑] last value doesn't need quotes.*/
do m=1 for msg.0; say /*process each of the seven messages. */
say ' in =' msg.m /*display the in message. */
say 'out =' MD5(msg.m) /* " " out " */
end /*m*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
MD5: procedure; parse arg !; numeric digits 20 /*insure there's enough decimal digits.*/
a='67452301'x; b="efcdab89"x; c='98badcfe'x; d="10325476"x; x00='0'x; x80="80"x
#=length(!) /*length in bytes of the input message.*/
L=#*8//512; if L<448 then plus=448-L /*is the length less than 448 ? */
if L>448 then plus=960-L /* " " " greater " " */
if L=448 then plus=512 /* " " " equal to " */
x00000000='00000000'x /* [↓] a little of this, ··· */
$=! || x80 || copies( x00, plus%8 -1 )reverse(right(d2c(8 * #), 4, x00)) || x00000000
/* [↑] ··· and a little of that.*/
do j=0 to length($)%64-1 /*process the message (lots of steps).*/
a_=a; b_=b; c_=c; d_=d /*save the original values for later.*/
chunk=j*64 /*calculate the size of the chunks. */
do k=1 for 16 /*process the message in chunks. */
!.k=reverse( substr($, chunk + 1 + 4*(k-1), 4) ) /*magic stuff.*/
end /*k*/
/*─────────────────────────────────────Md5 test suite (from above doc). */
msg.1=''
msg.2='a'
msg.3='abc'
msg.4='message digest'
msg.5='abcdefghijklmnopqrstuvwxyz'
msg.6='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
msg.7='12345678901234567890123456789012345678901234567890123456789012345678901234567890'
msg.0=7
do m=1 for msg.0
say ' in =' msg.m
say 'out =' MD5(msg.m)
say
end /*m*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────MD5 subroutine──────────────────────*/
MD5: procedure; parse arg !; numeric digits 20 /*insure enough digits.*/
parse value '67452301'x 'efcdab89'x '98badcfe'x '10325476'x with a b c d
#=length(!)
L=#*8 // 512
select
when L<448 then plus=448-L
when L>448 then plus=960-L
when L=448 then plus=512
end /*select*/
a = .part1( a, b, c, d, 0, 7, 3614090360) /*■■■■ 1 ■■■■*/
d = .part1( d, a, b, c, 1, 12, 3905402710) /*■■■■ 2 ■■■■*/
c = .part1( c, d, a, b, 2, 17, 606105819) /*■■■■ 3 ■■■■*/
b = .part1( b, c, d, a, 3, 22, 3250441966) /*■■■■ 4 ■■■■*/
a = .part1( a, b, c, d, 4, 7, 4118548399) /*■■■■ 5 ■■■■*/
d = .part1( d, a, b, c, 5, 12, 1200080426) /*■■■■ 6 ■■■■*/
c = .part1( c, d, a, b, 6, 17, 2821735955) /*■■■■ 7 ■■■■*/
b = .part1( b, c, d, a, 7, 22, 4249261313) /*■■■■ 8 ■■■■*/
a = .part1( a, b, c, d, 8, 7, 1770035416) /*■■■■ 9 ■■■■*/
d = .part1( d, a, b, c, 9, 12, 2336552879) /*■■■■ 10 ■■■■*/
c = .part1( c, d, a, b, 10, 17, 4294925233) /*■■■■ 11 ■■■■*/
b = .part1( b, c, d, a, 11, 22, 2304563134) /*■■■■ 12 ■■■■*/
a = .part1( a, b, c, d, 12, 7, 1804603682) /*■■■■ 13 ■■■■*/
d = .part1( d, a, b, c, 13, 12, 4254626195) /*■■■■ 14 ■■■■*/
c = .part1( c, d, a, b, 14, 17, 2792965006) /*■■■■ 15 ■■■■*/
b = .part1( b, c, d, a, 15, 22, 1236535329) /*■■■■ 16 ■■■■*/
a = .part2( a, b, c, d, 1, 5, 4129170786) /*■■■■ 17 ■■■■*/
d = .part2( d, a, b, c, 6, 9, 3225465664) /*■■■■ 18 ■■■■*/
c = .part2( c, d, a, b, 11, 14, 643717713) /*■■■■ 19 ■■■■*/
b = .part2( b, c, d, a, 0, 20, 3921069994) /*■■■■ 20 ■■■■*/
a = .part2( a, b, c, d, 5, 5, 3593408605) /*■■■■ 21 ■■■■*/
d = .part2( d, a, b, c, 10, 9, 38016083) /*■■■■ 22 ■■■■*/
c = .part2( c, d, a, b, 15, 14, 3634488961) /*■■■■ 23 ■■■■*/
b = .part2( b, c, d, a, 4, 20, 3889429448) /*■■■■ 24 ■■■■*/
a = .part2( a, b, c, d, 9, 5, 568446438) /*■■■■ 25 ■■■■*/
d = .part2( d, a, b, c, 14, 9, 3275163606) /*■■■■ 26 ■■■■*/
c = .part2( c, d, a, b, 3, 14, 4107603335) /*■■■■ 27 ■■■■*/
b = .part2( b, c, d, a, 8, 20, 1163531501) /*■■■■ 28 ■■■■*/
a = .part2( a, b, c, d, 13, 5, 2850285829) /*■■■■ 29 ■■■■*/
d = .part2( d, a, b, c, 2, 9, 4243563512) /*■■■■ 30 ■■■■*/
c = .part2( c, d, a, b, 7, 14, 1735328473) /*■■■■ 31 ■■■■*/
b = .part2( b, c, d, a, 12, 20, 2368359562) /*■■■■ 32 ■■■■*/
a = .part3( a, b, c, d, 5, 4, 4294588738) /*■■■■ 33 ■■■■*/
d = .part3( d, a, b, c, 8, 11, 2272392833) /*■■■■ 34 ■■■■*/
c = .part3( c, d, a, b, 11, 16, 1839030562) /*■■■■ 35 ■■■■*/
b = .part3( b, c, d, a, 14, 23, 4259657740) /*■■■■ 36 ■■■■*/
a = .part3( a, b, c, d, 1, 4, 2763975236) /*■■■■ 37 ■■■■*/
d = .part3( d, a, b, c, 4, 11, 1272893353) /*■■■■ 38 ■■■■*/
c = .part3( c, d, a, b, 7, 16, 4139469664) /*■■■■ 39 ■■■■*/
b = .part3( b, c, d, a, 10, 23, 3200236656) /*■■■■ 40 ■■■■*/
a = .part3( a, b, c, d, 13, 4, 681279174) /*■■■■ 41 ■■■■*/
d = .part3( d, a, b, c, 0, 11, 3936430074) /*■■■■ 42 ■■■■*/
c = .part3( c, d, a, b, 3, 16, 3572445317) /*■■■■ 43 ■■■■*/
b = .part3( b, c, d, a, 6, 23, 76029189) /*■■■■ 44 ■■■■*/
a = .part3( a, b, c, d, 9, 4, 3654602809) /*■■■■ 45 ■■■■*/
d = .part3( d, a, b, c, 12, 11, 3873151461) /*■■■■ 46 ■■■■*/
c = .part3( c, d, a, b, 15, 16, 530742520) /*■■■■ 47 ■■■■*/
b = .part3( b, c, d, a, 2, 23, 3299628645) /*■■■■ 48 ■■■■*/
a = .part4( a, b, c, d, 0, 6, 4096336452) /*■■■■ 49 ■■■■*/
d = .part4( d, a, b, c, 7, 10, 1126891415) /*■■■■ 50 ■■■■*/
c = .part4( c, d, a, b, 14, 15, 2878612391) /*■■■■ 51 ■■■■*/
b = .part4( b, c, d, a, 5, 21, 4237533241) /*■■■■ 52 ■■■■*/
a = .part4( a, b, c, d, 12, 6, 1700485571) /*■■■■ 53 ■■■■*/
d = .part4( d, a, b, c, 3, 10, 2399980690) /*■■■■ 54 ■■■■*/
c = .part4( c, d, a, b, 10, 15, 4293915773) /*■■■■ 55 ■■■■*/
b = .part4( b, c, d, a, 1, 21, 2240044497) /*■■■■ 56 ■■■■*/
a = .part4( a, b, c, d, 8, 6, 1873313359) /*■■■■ 57 ■■■■*/
d = .part4( d, a, b, c, 15, 10, 4264355552) /*■■■■ 58 ■■■■*/
c = .part4( c, d, a, b, 6, 15, 2734768916) /*■■■■ 59 ■■■■*/
b = .part4( b, c, d, a, 13, 21, 1309151649) /*■■■■ 60 ■■■■*/
a = .part4( a, b, c, d, 4, 6, 4149444226) /*■■■■ 61 ■■■■*/
d = .part4( d, a, b, c, 11, 10, 3174756917) /*■■■■ 62 ■■■■*/
c = .part4( c, d, a, b, 2, 15, 718787259) /*■■■■ 63 ■■■■*/
b = .part4( b, c, d, a, 9, 21, 3951481745) /*■■■■ 64 ■■■■*/
a = .a(a_,a); b=.a(b_,b); c=.a(c_,c); d=.a(d_,d)
end /*j*/
$=!||'80'x||copies('0'x,plus%8-1)reverse(right(d2c(8*#),4,'0'x))||'00000000'x
do j=0 to length($)%64-1 /*process message (lots of steps)*/
a_=a; b_=b; c_=c; d_=d
chunk=j*64
do k=1 for 16 /*process the message in chunks. */
!.k=reverse(substr($,chunk+1+4*(k-1),4))
end /*k*/
a=.part1(a,b,c,d, 0, 7,3614090360) /* 1*/
d=.part1(d,a,b,c, 1,12,3905402710) /* 2*/
c=.part1(c,d,a,b, 2,17, 606105819) /* 3*/
b=.part1(b,c,d,a, 3,22,3250441966) /* 4*/
a=.part1(a,b,c,d, 4, 7,4118548399) /* 5*/
d=.part1(d,a,b,c, 5,12,1200080426) /* 6*/
c=.part1(c,d,a,b, 6,17,2821735955) /* 7*/
b=.part1(b,c,d,a, 7,22,4249261313) /* 8*/
a=.part1(a,b,c,d, 8, 7,1770035416) /* 9*/
d=.part1(d,a,b,c, 9,12,2336552879) /*10*/
c=.part1(c,d,a,b,10,17,4294925233) /*11*/
b=.part1(b,c,d,a,11,22,2304563134) /*12*/
a=.part1(a,b,c,d,12, 7,1804603682) /*13*/
d=.part1(d,a,b,c,13,12,4254626195) /*14*/
c=.part1(c,d,a,b,14,17,2792965006) /*15*/
b=.part1(b,c,d,a,15,22,1236535329) /*16*/
a=.part2(a,b,c,d, 1, 5,4129170786) /*17*/
d=.part2(d,a,b,c, 6, 9,3225465664) /*18*/
c=.part2(c,d,a,b,11,14, 643717713) /*19*/
b=.part2(b,c,d,a, 0,20,3921069994) /*20*/
a=.part2(a,b,c,d, 5, 5,3593408605) /*21*/
d=.part2(d,a,b,c,10, 9, 38016083) /*22*/
c=.part2(c,d,a,b,15,14,3634488961) /*23*/
b=.part2(b,c,d,a, 4,20,3889429448) /*24*/
a=.part2(a,b,c,d, 9, 5, 568446438) /*25*/
d=.part2(d,a,b,c,14, 9,3275163606) /*26*/
c=.part2(c,d,a,b, 3,14,4107603335) /*27*/
b=.part2(b,c,d,a, 8,20,1163531501) /*28*/
a=.part2(a,b,c,d,13, 5,2850285829) /*29*/
d=.part2(d,a,b,c, 2, 9,4243563512) /*30*/
c=.part2(c,d,a,b, 7,14,1735328473) /*31*/
b=.part2(b,c,d,a,12,20,2368359562) /*32*/
a=.part3(a,b,c,d, 5, 4,4294588738) /*33*/
d=.part3(d,a,b,c, 8,11,2272392833) /*34*/
c=.part3(c,d,a,b,11,16,1839030562) /*35*/
b=.part3(b,c,d,a,14,23,4259657740) /*36*/
a=.part3(a,b,c,d, 1, 4,2763975236) /*37*/
d=.part3(d,a,b,c, 4,11,1272893353) /*38*/
c=.part3(c,d,a,b, 7,16,4139469664) /*39*/
b=.part3(b,c,d,a,10,23,3200236656) /*40*/
a=.part3(a,b,c,d,13, 4, 681279174) /*41*/
d=.part3(d,a,b,c, 0,11,3936430074) /*42*/
c=.part3(c,d,a,b, 3,16,3572445317) /*43*/
b=.part3(b,c,d,a, 6,23, 76029189) /*44*/
a=.part3(a,b,c,d, 9, 4,3654602809) /*45*/
d=.part3(d,a,b,c,12,11,3873151461) /*46*/
c=.part3(c,d,a,b,15,16, 530742520) /*47*/
b=.part3(b,c,d,a, 2,23,3299628645) /*48*/
a=.part4(a,b,c,d, 0, 6,4096336452) /*49*/
d=.part4(d,a,b,c, 7,10,1126891415) /*50*/
c=.part4(c,d,a,b,14,15,2878612391) /*51*/
b=.part4(b,c,d,a, 5,21,4237533241) /*52*/
a=.part4(a,b,c,d,12, 6,1700485571) /*53*/
d=.part4(d,a,b,c, 3,10,2399980690) /*54*/
c=.part4(c,d,a,b,10,15,4293915773) /*55*/
b=.part4(b,c,d,a, 1,21,2240044497) /*56*/
a=.part4(a,b,c,d, 8, 6,1873313359) /*57*/
d=.part4(d,a,b,c,15,10,4264355552) /*58*/
c=.part4(c,d,a,b, 6,15,2734768916) /*59*/
b=.part4(b,c,d,a,13,21,1309151649) /*60*/
a=.part4(a,b,c,d, 4, 6,4149444226) /*61*/
d=.part4(d,a,b,c,11,10,3174756917) /*62*/
c=.part4(c,d,a,b, 2,15, 718787259) /*63*/
b=.part4(b,c,d,a, 9,21,3951481745) /*64*/
a=.a(a_,a); b=.a(b_,b); c=.a(c_,c); d=.a(d_,d)
end /*j*/
return c2x(reverse(a))c2x(reverse(b))c2x(reverse(c))c2x(reverse(d))
/*─────────────────────────────────────subroutines──────────────────────*/
.part1: procedure expose !.; parse arg w,x,y,z,n,m,_; n=n+1
return .a(.lR(right(d2c(_+c2d(w)+c2d(.f(x,y,z))+c2d(!.n)),4,'0'x),m),x)
.part2: procedure expose !.; parse arg w,x,y,z,n,m,_; n=n+1
return .a(.lR(right(d2c(_+c2d(w)+c2d(.g(x,y,z))+c2d(!.n)),4,'0'x),m),x)
.part3: procedure expose !.; parse arg w,x,y,z,n,m,_; n=n+1
return .a(.lR(right(d2c(_+c2d(w)+c2d(.h(x,y,z))+c2d(!.n)),4,'0'x),m),x)
.part4: procedure expose !.; parse arg w,x,y,z,n,m; n=n+1
return .a(.lR(right(d2c(c2d(w)+c2d(.i(x,y,z))+c2d(!.n)+arg(7)),4,'0'x),m),x)
.h: procedure; parse arg x,y,z; return bitxor(bitxor(x,y),z)
.i: return bitxor(arg(2),bitor(arg(1),bitxor(arg(3),'ffffffff'x)))
.a: return right(d2c(c2d(arg(1))+c2d(arg(2))),4,'0'x)
.f: procedure; parse arg x,y,z
return bitor(bitand(x,y),bitand(bitxor(x,'ffffffff'x),z))
.g: procedure; parse arg x,y,z
return bitor(bitand(x,z),bitand(y,bitxor(z,'ffffffff'x)))
.lR: procedure; parse arg _,#; if #==0 then return _ /*left rotate.*/
?=x2b(c2x(_)); return x2c(b2x(right(?||left(?,#),length(?))))
return c2x( reverse(a) )c2x( reverse(b) )c2x( reverse(c) )c2x( reverse(d) )
/*──────────────────────────────────────────────────────────────────────────────────────*/
.a: return right(d2c(c2d(arg(1)) + c2d(arg(2))), 4, '0'x)
.h: return bitxor(bitxor(arg(1), arg(2)), arg(3))
.i: return bitxor(arg(2), bitor(arg(1), bitxor(arg(3), 'ffffffff'x)))
.f: return bitor(bitand(arg(1),arg(2)), bitand(bitxor(arg(1), 'ffffffff'x), arg(3)))
.g: return bitor(bitand(arg(1),arg(3)), bitand(arg(2), bitxor(arg(3), 'ffffffff'x)))
.Lr: procedure; parse arg _,#; if #==0 then return _ /*left rotate.*/
?=x2b(c2x(_)); return x2c(b2x(right(? || left(?, #), length(?))))
.part1: procedure expose !.; parse arg w,x,y,z,n,m,_; n=n+1
return .a(.Lr(right(d2c(_+c2d(w)+c2d(.f(x,y,z))+c2d(!.n)),4,'0'x),m),x)
.part2: procedure expose !.; parse arg w,x,y,z,n,m,_; n=n+1
return .a(.Lr(right(d2c(_+c2d(w)+c2d(.g(x,y,z))+c2d(!.n)),4,'0'x),m),x)
.part3: procedure expose !.; parse arg w,x,y,z,n,m,_; n=n+1
return .a(.Lr(right(d2c(_+c2d(w)+c2d(.h(x,y,z))+c2d(!.n)),4,'0'x),m),x)
.part4: procedure expose !.; parse arg w,x,y,z,n,m,_; n=n+1
return .a(.Lr(right(d2c(c2d(w)+c2d(.i(x,y,z))+c2d(!.n)+_),4,'0'x),m),x)

View file

@ -0,0 +1,243 @@
**FREE
Ctl-opt MAIN(Main);
Ctl-opt DFTACTGRP(*NO) ACTGRP(*NEW);
dcl-pr QDCXLATE EXTPGM('QDCXLATE');
dataLen packed(5 : 0) CONST;
data char(32767) options(*VARSIZE);
conversionTable char(10) CONST;
end-pr;
dcl-c MASK32 CONST(4294967295);
dcl-s SHIFT_AMTS int(3) dim(16) CTDATA PERRCD(16);
dcl-s MD5_TABLE_T int(20) dim(64) CTDATA PERRCD(4);
dcl-proc Main;
dcl-s inputData char(45);
dcl-s inputDataLen int(10) INZ(0);
dcl-s outputHash char(16);
dcl-s outputHashHex char(32);
DSPLY 'Input: ' '' inputData;
inputData = %trim(inputData);
inputDataLen = %len(%trim(inputData));
DSPLY ('Input=' + inputData);
DSPLY ('InputLen=' + %char(inputDataLen));
// Convert from EBCDIC to ASCII
if inputDataLen > 0;
QDCXLATE(inputDataLen : inputData : 'QTCPASC');
endif;
CalculateMD5(inputData : inputDataLen : outputHash);
// Convert to hex
ConvertToHex(outputHash : 16 : outputHashHex);
DSPLY ('MD5: ' + outputHashHex);
return;
end-proc;
dcl-proc CalculateMD5;
dcl-pi *N;
message char(65535) options(*VARSIZE) CONST;
messageLen int(10) value;
outputHash char(16);
end-pi;
dcl-s numBlocks int(10);
dcl-s padding char(72);
dcl-s a int(20) INZ(1732584193);
dcl-s b int(20) INZ(4023233417);
dcl-s c int(20) INZ(2562383102);
dcl-s d int(20) INZ(271733878);
dcl-s buffer int(20) dim(16) INZ(0);
dcl-s i int(10);
dcl-s j int(10);
dcl-s k int(10);
dcl-s multiplier int(20);
dcl-s index int(10);
dcl-s originalA int(20);
dcl-s originalB int(20);
dcl-s originalC int(20);
dcl-s originalD int(20);
dcl-s div16 int(10);
dcl-s f int(20);
dcl-s tempInt int(20);
dcl-s bufferIndex int(10);
dcl-ds byteToInt QUALIFIED;
n int(5) INZ(0);
c char(1) OVERLAY(n : 2);
end-ds;
numBlocks = (messageLen + 8) / 64 + 1;
MD5_FillPadding(messageLen : numBlocks : padding);
for i = 0 to numBlocks - 1;
index = i * 64;
// Read message as little-endian 32-bit words
for j = 1 to 16;
multiplier = 1;
for k = 1 to 4;
index += 1;
if index <= messageLen;
byteToInt.c = %subst(message : index : 1);
else;
byteToInt.c = %subst(padding : index - messageLen : 1);
endif;
buffer(j) += multiplier * byteToInt.n;
multiplier *= 256;
endfor;
endfor;
originalA = a;
originalB = b;
originalC = c;
originalD = d;
for j = 0 to 63;
div16 = j / 16;
select;
when div16 = 0;
f = %bitor(%bitand(b : c) : %bitand(%bitnot(b) : d));
bufferIndex = j;
when div16 = 1;
f = %bitor(%bitand(b : d) : %bitand(c : %bitnot(d)));
bufferIndex = %bitand(j * 5 + 1 : 15);
when div16 = 2;
f = %bitxor(b : %bitxor(c : d));
bufferIndex = %bitand(j * 3 + 5 : 15);
when div16 = 3;
f = %bitxor(c : %bitor(b : Mask32Bit(%bitnot(d))));
bufferIndex = %bitand(j * 7 : 15);
endsl;
tempInt = Mask32Bit(b + RotateLeft32Bit(a + f + buffer(bufferIndex + 1) + MD5_TABLE_T(j + 1) :
SHIFT_AMTS(div16 * 4 + %bitand(j : 3) + 1)));
a = d;
d = c;
c = b;
b = tempInt;
endfor;
a = Mask32Bit(a + originalA);
b = Mask32Bit(b + originalB);
c = Mask32Bit(c + originalC);
d = Mask32Bit(d + originalD);
endfor;
for i = 0 to 3;
if i = 0;
tempInt = a;
elseif i = 1;
tempInt = b;
elseif i = 2;
tempInt = c;
else;
tempInt = d;
endif;
for j = 0 to 3;
byteToInt.n = %bitand(tempInt : 255);
%subst(outputHash : i * 4 + j + 1 : 1) = byteToInt.c;
tempInt /= 256;
endfor;
endfor;
return;
end-proc;
dcl-proc MD5_FillPadding;
dcl-pi *N;
messageLen int(10);
numBlocks int(10);
padding char(72);
end-pi;
dcl-s totalLen int(10);
dcl-s paddingSize int(10);
dcl-ds *N;
messageLenBits int(20);
mlb_bytes char(8) OVERLAY(messageLenBits);
end-ds;
dcl-s i int(10);
%subst(padding : 1 : 1) = X'80';
totalLen = numBlocks * 64;
paddingSize = totalLen - messageLen; // 9 to 72
messageLenBits = messageLen;
messageLenBits *= 8;
for i = 1 to 8;
%subst(padding : paddingSize - i + 1 : 1) = %subst(mlb_bytes : i : 1);
endfor;
for i = 2 to paddingSize - 8;
%subst(padding : i : 1) = X'00';
endfor;
return;
end-proc;
dcl-proc RotateLeft32Bit;
dcl-pi *N int(20);
n int(20) value;
amount int(3) value;
end-pi;
dcl-s i int(3);
n = Mask32Bit(n);
for i = 1 to amount;
n *= 2;
if n >= 4294967296;
n -= MASK32;
endif;
endfor;
return n;
end-proc;
dcl-proc Mask32Bit;
dcl-pi *N int(20);
n int(20) value;
end-pi;
return %bitand(n : MASK32);
end-proc;
dcl-proc ConvertToHex;
dcl-pi *N;
inputData char(32767) options(*VARSIZE) CONST;
inputDataLen int(10) value;
outputData char(65534) options(*VARSIZE);
end-pi;
dcl-c HEX_CHARS CONST('0123456789ABCDEF');
dcl-s i int(10);
dcl-s outputOffset int(10) INZ(1);
dcl-ds dataStruct QUALIFIED;
numField int(5) INZ(0);
// IBM i is big-endian
charField char(1) OVERLAY(numField : 2);
end-ds;
for i = 1 to inputDataLen;
dataStruct.charField = %BitAnd(%subst(inputData : i : 1) : X'F0');
dataStruct.numField /= 16;
%subst(outputData : outputOffset : 1) = %subst(HEX_CHARS : dataStruct.numField + 1 : 1);
outputOffset += 1;
dataStruct.charField = %BitAnd(%subst(inputData : i : 1) : X'0F');
%subst(outputData : outputOffset : 1) = %subst(HEX_CHARS : dataStruct.numField + 1 : 1);
outputOffset += 1;
endfor;
return;
end-proc;
**CTDATA SHIFT_AMTS
7 12 17 22 5 9 14 20 4 11 16 23 6 10 15 21
**CTDATA MD5_TABLE_T
3614090360 3905402710 606105819 3250441966
4118548399 1200080426 2821735955 4249261313
1770035416 2336552879 4294925233 2304563134
1804603682 4254626195 2792965006 1236535329
4129170786 3225465664 643717713 3921069994
3593408605 38016083 3634488961 3889429448
568446438 3275163606 4107603335 1163531501
2850285829 4243563512 1735328473 2368359562
4294588738 2272392833 1839030562 4259657740
2763975236 1272893353 4139469664 3200236656
681279174 3936430074 3572445317 76029189
3654602809 3873151461 530742520 3299628645
4096336452 1126891415 2878612391 4237533241
1700485571 2399980690 4293915773 2240044497
1873313359 4264355552 2734768916 1309151649
4149444226 3174756917 718787259 3951481745