Back in time the _CIPHER MI instruction was the only immediately available function to produce an MD5 (Message Digest) or SHA-1 (Secure Hash Algorithm) hash value. Now that the SHA-1 algorithm has been deprecated, it appears that the _CIPHER MI instruction does not support the SHA-256 hash algorithm.
IBM probably decided to focus their effort on the more recent Calculate Hash (Qc3CalculateHash) API.
As documented, the Qc3CalculateHash API supports the MD5 as well as SHA-1 to SHA-512 hash algorithms, and will probably continue to be enhanced, if and when new algorithms are implemented. I have written a very simple Calculate Hash Value (CLCHASHVAL) command for the purpose of demonstrating how to call he Qc3CalculateHash API. The command processing program could easily be adapted to more specific requirements, given the need.
The Calculate Hash Value command is based on the following source members:
CBX277 RPGLE Calculate Hash Value - CPP CBX277S RPGLE Encrypt and Decrypt Data - services CBX277B SRVSRC Encrypt and Decrypt Data - services CBX277H PNLGRP Calculate Hash Value - Help CBX277X CMD Calculate Hash Value CBX277M CLP Calculate Hash Value - Build command
Compiling and running the CL-program CBX277M will create the utility for you, once you’ve copied the other source members to their respective default source files. The source members are located in the zip file ClcHashVal.zip available here:
Download the save file containing the source code.
Postscript: I have added the Calculate File Hash Value (CLCFILHASH) command to the download zip-file. The CLCFILHASH command is similar to the CLCHASHVAL command, but will produce the hash value based on the content of a specified input stream file name. You’ll find compilation instructions in each of the respective source file headers:
CBX2772 RPGLE Calculate File Hash Value - CPP CBX2772H PNLGRP Calculate File Hash Value - Help CBX2772X CMD Calculate File Hash Value
Hi Carten
sorry for disturbing you .. i have downloaded the zip ClcHashVal.zip, but running the command CLCHASHVAL, i find the result different from some online hash calculator;
example if i run CLCHASHVAL CALCDATA(ABC) HASHALG(*SHA256)
Input . . . : ABC
Hash value . :
5202BF40821662BF1AD7D9C9B558056775D9D6BF8AA1C00492BCA8556B02772F
but if go to for example to https://www.xorbin.com/tools/sha256-hash-calculator
the result is
b5d4045c3f466fa91fe2cc6abe79232a1a57cdf104f7a26e716e0a1e2789df78
where am i wrong ?
Thanks in advance
LikeLike
Hi Angiolo,
Thanks for your e-mail! The difference in the results you’re seeing, is due to two different character sets being involved. Cryptographic processing is always based on the binary value of an input string – even if you see it as characters.
The CLCHASHVAL command running on a System i, is therefore acting on an EBCDIC character set when you specify the input value ‘ABC’ – which is equal to the hexadecimal value x’C1C2C3’.
https://en.wikipedia.org/wiki/EBCDIC
And this site https://www.xorbin.com/tools/sha256-hash-calculator being a web-page, is seeing the UTF-8 representation for the same letters – so here ‘ABC’ amounts to x’414243’.
https://en.wikipedia.org/wiki/UTF-8
This topic is explained in more detail here:
https://www.di-mgt.com.au/cryptoInternational2.html
If you run the following command you should see the result you’d expect:
CLCHASHVAL CALCDATA(X’414243′) HASHALG(*SHA256)
– Because now the CLCHASHVAL is processing the same binary value as the http://www.xorbin.com site does.
Let me know if you have any questions, or need me to elaborate further.
LikeLike
Hello,
I am trying to build the tool and when doing crtsrvpgm it tells me Definition not found for symbol ‘CLCHASHVAL’.
Definition not found for symbol ‘CVTCHRHEX’.
Any idea to make it working ?
thanks in advance
take care
jp
LikeLike
It seems to me that you’re trying to compile the CPP source CBX277, rather than service program CBX277S. Are you using the CBX277M CL-program to create all the objects involved in the CLCHASHVAL command?
LikeLike
YES I am using the cbx277M cl pour build the tool and when the clp is doing
CRTSRVPGM with EXPORT(*SRCFILE)
Definition not found for symbol ‘CVTCHRHEX’.
Definition not found for symbol ‘RMVALGCTX’.
I ‘ve got error
CPF5D05
LikeLike
also, when compiling I’ve got this problem now
* * * * * E N D O F E X T E R N A L R E F E R E N C E S * * * * *
5770WDS V7R2M0 140418 RN IBM ILE RPG JPD/CBX277
M e s s a g e S u m m a r y
Msg id Sv Number Message text
*RNF8044 20 1 Source records exist but no array or table definition found
*RNF7023 40 1 The Compiler cannot determine how the program can end.
LikeLike
Hello JP,
There seems to be a mistake somewhere – the service program source is name CBX277S but the above reference points to CBX277: 5770WDS V7R2M0 140418 RN IBM ILE RPG JPD/CBX277
Please send the full compilation list to flensburg@novasol.dk – then I’ll have a closer look.
LikeLike
Hello
I found both problem
It is my mistake, i ddn’t copy the right source from your example
thx a lot
and take care !
jp
LikeLike
Hello,
Can you provide an example with Qc3CalculateSignature using the SHA-1 algorithm and an RSA private key?
LikeLike
Hello Rui,
I’ll respond to your private e-mail.
LikeLike
Hello Carsten –
I am using your example with calculate hash, but I didn’t know if you had an example of Qc3CalculateSignature using a private key? I am having to create an OAUTH header in an HTTP api. Thanks.
LikeLike
Hello Joshua,
I can send you an example using a private key with the Qc3CalculateSignature API and the associated public key with the Qc3VerifySignature API to demonstrate the usage of the two APIs – would that be useful?
LikeLike
Hello Carsten – I came across your fantastic article. I got your CLCHASHVAL program working first time and it’s something I’ve been looking for, so thank you for this. I do have one question about you command. Is there a particular reason why the hash value is all in upper case? My understanding is that the hash value is case-sensitive. Can you provide some insights?
Thank you for the great work!
LikeLike
Hello Eddie,
Thanks for your note. The hash value is actual a binary value – every byte can be in the value range of x’00’ to x’FF’, many of which are neither possible to display or print. In order to display and enter those values I therefore convert the hash value to hex nibbles (4 bit values) ‘0’ to ‘F’. An 8 byte hash value is consequently shown as an 16 byte nibble string. Let me know if you have any further questions.
LikeLike