× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



I have cobbled together an application to calculate the MD5 hash from a
native i file. I used Scott's code from iSeriesNetwork, which worked on IFS
files, converted that to use native files, and then added in the CCSID
conversion from Bruce's example found here:
http://archive.midrange.com/midrange-l/200006/msg01334.html
The current end result is shown below.

I am using WinHasher on the PC side to calculate the MD5 hash there.

The file is FTP'd from the i to a Windows server, and we need to ensure that
the file is unadulterated. By default, the FTP handles the conversion to
ASCII.

I have, so far, been unable to get a match on the MD5 hashes. One thing I
noticed is that the file on the Windows server has the linefeed/carriage
return characters after the last non-blank character in each line. The file
being transferred has fixed-length records, but the text data on each line
varies in length, so I calculate the length before each call to CIPHER.

Do I need to append linefeed/carriage return characters to the end of the
%trimmed string that I pass to CIPHER in my RPG program? If so, what are
they? I can't make out the hex representation in Textplorer. And it's been
way too many years since I've cared about linefeed/carriage return
characters. I'd hazard a guess that Textplorer is trying to show me
x'0C0A', but I can't say for certain.

Also, is there an "end of file" character that I need to consider.

TIA,
Dan

H DFTACTGRP(*NO) BNDDIR('QC2LE')

fDOC1PS if e disk

/copy md5klement,ifsio_h

D SetupConversn PR
D ToAscii 256a

*
* _CIPHER MI builtin. Allows access to cryptographic
* functions in the licensed internal code.
*
D cipher PR extproc('_CIPHER')
D receiver * value
D control * value
D source * value

D Convert PR extproc('_XLATEB')
D * value
D * value
D 10u 0 value

D HASH C const(5)
D MD5 C const(x'00')
D SHA1 C const(x'01')
D ONLY C const(x'00')
D FIRST C const(x'01')
D MIDDLE C const(x'02')
D FINAL C const(x'03')

*
* These control how the system creates a hash
*
D HashCtrl DS qualified
D Function 5I 0 inz(HASH)
D HashAlg 1A inz(MD5)
D Sequence 1A inz(FIRST)
D Length 10I 0 inz
D Output 1A inz(x'00')
D Reserved 7A inz(x'00000000000000')
D CtxPtr * inz(%addr(WorkArea))

D WorkArea S 160A inz(*loval)

*
* MI builtin to create a hex dump of a spot in memory
*
D hexdump PR EXTPROC('cvthc')
D output 40A
D input 20A
D output_len 10I 0 value

D ReadBuf S *
D BufSize s 10I 0
D Len s 10I 0
D fd s 10I 0
D BinHash S 20A inz(*loval)
D HexHash s 40A
D p_BinHash s * inz(%addr(BinHash))
D ToAscii s 256a

/free
*inlr = *on;

SetupConversn( ToAscii ) ;

hashCtrl.Sequence = FIRST;

dou %eof( DOC1PS ) ;
read DOC1PS ;
if not %eof( DOC1PS ) ;
hashCtrl.Length = %len( %trimr( DOC1OUT ) ) ;
Convert( %addr( DOC1OUT )
: %addr( ToAscii )
: %size( DOC1OUT ) ) ;
ReadBuf = %addr( DOC1OUT ) ;

cipher( %addr(p_BinHash)
: %addr(HashCtrl)
: %addr(ReadBuf) );

hashCtrl.Sequence = MIDDLE;
endif;
enddo;


// At the very end, call cipher with Sequence=FINAL
// to get back the MD5 hash

hashCtrl.Sequence = FINAL;
hashCtrl.Length = 0;

cipher( %addr(p_BinHash)
: %addr(HashCtrl)
: %addr(ReadBuf) );


// Apps that use MD5 hashes usually want them to be
// hexidecimal and lowercase. Here, that is done...

hexdump( HexHash : BinHash : %size(HexHash) );
HexHash = %xlate('ABCDEF': 'abcdef': HexHash);

dsply ('MD5 hash is ' + %subst(HexHash:1:32));

/end-free


*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* SetupConversn(): This sets up and gets the conversion table
* for converting EBCDIC (37) to ASCII (819)
*
* Taken from
http://archive.midrange.com/midrange-l/200006/msg01334.html

*

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P SetupConversn
B
D SetupConversn
PI
D r_To819
256a


D CCSID1 s 10i 0
inz(37)
D ST1 s 10i 0
inz(0)
D StartMap s
256
D L1 s 10i 0
inz(%size(StartMap))
D CCSID2 s 10i 0
inz(819)
D ST2 s 10i 0
inz(0)
D GCCASN s 10i 0
inz(0)
D L2 s 10i 0
inz(%size(To819))
D To819 s
256
D L3 s 10i
0
D L4 s 10i
0
D FB s
12
D
ds
D x 5i
0
D LowX 2
2
* Get all single byte ebcdic hex
values
C 0 do 255
x
C eval %subst(StartMap:x+1:1) = LowX
C enddo
* Get conversion table for 819 from 37
C call 'QTQCVRT'
C parm CCSID1
C parm ST1
C parm StartMap
C parm L1
C parm CCSID2
C parm ST2
C parm GCCASN
C parm L2
C parm To819
C parm L3
C parm L4
C parm FB
*
C eval r_To819 = To819

P E

As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.