Calculate an SHA-1 Hash

Article ID: 57351

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!

ProVIP Sponsors

ProVIP Sponsors