MD5/Implementation: Difference between revisions

Content added Content deleted
(Added RPG implementation)
Line 3,403: Line 3,403:
out = 57EDF4A22BE3C955AC49DA2E2107B67A
out = 57EDF4A22BE3C955AC49DA2E2107B67A
</pre>
</pre>

=={{header|RPG}}==
Based on my Java implementation. Uses free-form RPG and a CTDATA section to hold lookup tables. Converts input from EBCDIC to ASCII before hashing.

<lang RPG>**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</lang>

Sample output:
<pre> DSPLY Input:
abcdefghijklmnopqrstuvwxyz
DSPLY Input=abcdefghijklmnopqrstuvwxyz
DSPLY InputLen=26
DSPLY MD5: C3FCD3D76192E4007DFB496CCA67E13B</pre>


=={{header|Seed7}}==
=={{header|Seed7}}==