Q: I have a business requirement to generate an SHA-1 hash of a string (e.g., '1/256/9475529/1224081689/jeffp22115'). I think the Calculate Hash (Qc3CalculateHash) API will do this, but I've tried it, and I can't get it to work right. Can you give me an example?
A: Yes, I will provide you with an example, but first let me talk a little about the common mistakes that might be the reason it didn't work for you. Aside from the chance that you made a mistake in your code, I can think of two reasons that might explain why it's not working for you. First, most software that generates a hash actually converts the hash to hex when it displays it to you. This API, however, gives the hash to you in its raw binary form, which might look strange to you. Second, the hash is calculated on the raw values of the bytes fed into the API. So if you're comparing a hash run over EBCDIC data to a hash generated on an ASCII machine, they won't match. The solution, of course, is to convert your data to ASCII before generating the hash.
Here's an example of generating a hash. Because I don't know if you're comparing it to an EBCDIC or ASCII hash, I provide the output in both character sets:
H DFTACTGRP(*NO) ACTGRP('KLEMENT') BNDDIR('QC2LE')
D Qc3CalculateHash...
D PR ExtProc('Qc3CalculateHash')
D InputData * value
D InputDataLen 10i 0 const
D InputDataFmt 8a const
D AlgDesc 16a const
D AlgFmt 8a const
D CryptoSP 1a const
D CryptoDev 1a const options(*omit)
D Hash 64a options(*varsize:*omit)
D ErrorCode 32767a options(*varsize)
D ALGD0500_t ds qualified
D based(Template)
D HashAlg 10i 0
D QDCXLATE PR ExtPgm('QDCXLATE')
D len 5p 0 const
D data 32702a options(*varsize)
D table 10a const
D cvthc PR ExtProc('cvthc')
D target 65534A options(*varsize)
D src_bits 32767A options(*varsize) const
D tgt_length 10I 0 value
D ErrorNull ds qualified
D BytesProv 10i 0 inz(0)
D BytesAvail 10i 0 inz(0)
D HASH_MD5 c 1
D HASH_SHA1 c 2
D HASH_SHA256 c 3
D HASH_SHA384 c 4
D HASH_SHA512 c 5
D data s 80A
D len s 10i 0
D alg ds likeds(ALGD0500_t)
D binhash s 20a
D hexhash s 40a
/free
data = '1/256/9475529/1224081689/jeffp22115';
len = %len(%trimr(data));
alg.HashAlg = HASH_SHA1;
Qc3CalculateHash( %addr(data)
: len
: 'DATA0100'
: alg
: 'ALGD0500'
: '0'
: *OMIT
: binhash
: ErrorNull );
cvthc( hexhash: binhash: %len(binhash)*2);
dsply ('EBCDIC: ' + hexhash);
QDCXLATE(len: data: 'QTCPASC');
Qc3CalculateHash( %addr(data)
: len
: 'DATA0100'
: alg
: 'ALGD0500'
: '0'
: *OMIT
: binhash
: ErrorNull );
cvthc( hexhash: binhash: %len(binhash)*2);
dsply ('ASCII: ' + hexhash);
*inlr = *on;
/end-free
This program uses the Qc3CalculateHash API to calculate the SHA1 hash. It then uses the cvthc() MI function to create a hex representation of the hash to display on the screen.
The QDCXLATE API is used to convert the hash from EBCDIC to ASCII, and the process is repeated.
For the sake of keeping the code simple, I'm displaying the hash values using RPG's DSPLY opcode. In a real application, of course, you'd use the hash in your calculations, or if you need to display it on the screen, you'd output a web page or a display file.
Good luck!