IBM Support

Qc3CalculateHMAC API example

Question & Answer


Question

Example of how to use Qc3CalculateHMAC.

Answer

Note: The following code is provided as-is, IBM accepts no responsibility for it's correctness or use. Assistance modifying the example for your needs would be provided by lab services.


This sample program hardcodes the data to be hashed and the key:

Data - stringtobehashed
Key - hashkeyhashkeyaahashkeyhashkeyaa

Note: The minimum key length for SHA-256 is 32 bytes per the API document:
https://www-01.ibm.com/support/knowledgecenter/ssw_ibm_i_71/apis/qc3calhm.htm

Before calculating the HMAC hash, the data is converted to CCSID 1208 with iconv() to replicate results that would be seen if you are comparing the data with a hash received from a Web site that is using Unicode data rather than EBCDIC:

     H DFTACTGRP(*NO)                  
     H debug
      * Copyright (c) 2006,2011 Scott C. Klement                            
      * All rights reserved.                                              
      *                                                                    
      * Redistribution and use in source and binary forms, with or without  
      * modification, are permitted provided that the following conditions
      * are met:                                                          
      * 1. Redistributions of source code must retain the above copyright  
      *    notice, this list of conditions and the following disclaimer.    
      * 2. Redistributions in binary form must reproduce the above copyright
      *    notice, this list of conditions and the following disclaimer in
      *    the documentation and/or other materials provided with the
      *    distribution.
                                                                               
      * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
      * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
      * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
      * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
      * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
      * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
      * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
      * OF SUCH DAMAGE.                                                    
      *                                                                    
      */                                                                    
         
     d iconv_t         DS                  qualified
     d                                     based(StructureTemplate)
     d   return_value                10I 0
     d   cd                          10I 0 dim(12)

     d QtqCode_T       DS                  qualified
     d  CCSID                        10I 0 inz
     d  ConvAlt                      10I 0 inz
     d  SubsAlt                      10I 0 inz
     d  ShiftAlt                     10I 0 inz
     d  InpLenOp                     10I 0 inz
     d  ErrorOpt                     10I 0 inz
     d  Reserved                      8A   inz(*ALLx'00')

     d iconv_code_t    DS                  qualified
     d  owner                         8a   inz('IBMCCSID')
     d  CCSID                         5a   inz('00000')
     D  ReservedTo
     d   ConvAlt                      3a   inz('000')
     D                                     overlay(ReservedTo)
     d   SubsAlt                      1a   inz('0')
     D                                     overlay(ReservedTo:*next)
     d   ShiftAlt                     1a   inz('0')
     D                                     overlay(ReservedTo:*next)
     d   InpLenOpt                    1a   inz('0')
     D                                     overlay(ReservedTo:*next)
     d   ErrorOpt                     1a   inz('0')
     D                                     overlay(ReservedTo:*next)
     d   ReservedFrom                12A   inz(*ALLx'00')
     D                                     overlay(ReservedTo:*next)

     d QtqIconvOpen    PR                  extproc('QtqIconvOpen')
     d                                     like(iconv_t)
     d    toCode                           likeds(QtqCode_t) const
     d    fromCode                         likeds(QtqCode_t) const

     D iconv_open      PR                  extproc('iconv_open')
     D                                     like(iconv_t)
     D   toCode                            like(iconv_code_t) const
     D   fromCode                          like(iconv_code_t) const

     d iconv           PR            10U 0 extproc('iconv')
     d   cd                                like(iconv_t) value
     d   inbuf                         *
     d   inbytesleft                 10U 0
     d   outbuf                        *
     d   outbytesleft                10U 0

     d QlgTransformUCSData...
     d                 PR            10U 0 extproc('QlgTransformUCSData')
     d   xformtype                   10i 0 value
     d   inbuf                         *
     d   inbytesleft                 10U 0
     d   outbuf                        *
     d   outbytesleft                10U 0
     d   outspacereq                 10U 0

     D ICONV_FAIL      C                   CONST(4294967295)

     D iconv_close     PR            10I 0 extproc('iconv_close')
     D   cd                                like(iconv_t) value
      *----------------------------------------

     d from37          s            256a
     d from37len       s             10u 0
     D outputbuf       s            256a
     D outputlen       s             10u 0

     d source          ds                  likeds(QtqCode_t)
     d                                     inz(*likeds)
     d target          ds                  likeds(QtqCode_t)
     d                                     inz(*likeds)
     d toEBC           ds                  likeds(iconv_t)

     D p_input         s               *
     D p_output        s               *
     D inputleft       s             10u 0
     D outputleft      s             10u 0

      *-------------hash parms----------------
     d binaryHMAC      s             32a
     d SHA_256         c                   const(3)
     D DataLen         s             10u 0
     d dataToHash      s            256a
     d $hex            s             64a
     d Nullfield       s            100a
     d MySalt          s             64a
     D SaltLen         s             10u 0
      *---------------------------------------------------------------------
      * Stand Alone Fields - BOTTOM
      *---------------------------------------------------------------------
     D ErrorCode       DS                  qualified
     D    bytesProv                  10i 0 inz(0)
     D    bytesAvail                 10i 0 inz(0)

     D WsErrorCode     DS                  qualified
     D    bytesProv                  10i 0 inz(0)
     D    bytesAvail                 10i 0 inz(0)

     D my_key          DS                  qualified
     D    Type                       10i 0 inz(SHA_256)
     D    Len                        10i 0
     D    Fmt                         1a   inz('0')
     D                                3a
     D    Value                      64a

     d cvthc           PR                  ExtProc('cvthc')
     d   target                   65534A   options(*varsize)
     d   src_bits                 32767A   options(*varsize) const
     d   tgt_length                  10I 0 value

     D GetHMAC         PR                  ExtProc('Qc3CalculateHMAC')
     D  datatohash                  256a   const options(*varsize)
     D  pinDataLen                   10i 0 const
     D  pinFormat                     8a   const
     D  palgDesc                     10i 0 const
     D  palgDescFmt                   8a   const
     D  pkeyDesc                  32767a   const options(*varsize)
     D  pkeyDescFmt                   8a   const
     D  pcryptoProv                   1a   const
     D  pcryptoDev                   10a   const
     D  pHMAC                        64a         options(*varsize)
     D  pErrorCode                32767a         options(*varsize)


      /FREE
       //data to hash
       from37 = 'stringtobehashed';

       //data to hash length
       from37len = %len(%trimr(from37));

        // set conversion from 37 to 1208
        // -----------------------------------------------

        source.CCSID = 37;
        target.CCSID = 1208;
        toEBC = QtqIconvOpen( target: source );

        if (toEBC.return_value = -1);
           // handle error...
        endif;

        // -----------------------------------------------
        //   Translate data.
        //
        //   the iconv() API will increment/decrement
        //   the pointers and lengths, so make sure you
        //   do not use the original pointers...
        // -----------------------------------------------

        p_input  = %addr(from37);
        inputleft = from37len;

        p_output = %addr(outputbuf);
        outputleft = %size(outputbuf);

        iconv( toEBC
             : p_input
             : inputleft
             : p_output
             : outputleft );

        // -----------------------------------------------
        //  if needed, you can calculate the length of
        //  the decoded data by subtracting the amount
        //  of space left in the buffer from the total
        //  buffer size.
        //
        //  At this point, 'outputbuf' should contain
        //  the EBCDIC data.
        // -----------------------------------------------

        outputlen = %size(outputbuf) - outputleft;
        DataToHash   = %subst(outputbuf:1:outputlen);
        DataLen = outputlen;
        //dump;

       //encode the hash key per API doc
       //The minimum length for an SHA-256 HMAC key is 32 bytes
       from37 = 'hashkeyhashkeyaahashkeyhashkeyaa';

       //hash key len
       from37len = %len(%trimr(from37));
        clear outputbuf;
        p_input  = %addr(from37);
        inputleft = from37len;

        p_output = %addr(outputbuf);
        outputleft = %size(outputbuf);

        iconv( toEBC
             : p_input
             : inputleft
             : p_output
             : outputleft );

        outputlen = %size(outputbuf) - outputleft;
        MySalt = %subst(outputbuf:1:outputlen);
        SaltLen = outputlen;
        //dump;

        // -----------------------------------------------
        //  you can call iconv() many more times if you
        //  want, using the same 'toEBC' table for
        //  translation.
        //   - -
        //  when you are completely done, call iconv_close()
        //  to free up memory.
        // -----------------------------------------------

        iconv_close(toEBC);
        //---------------------------------------------------------
        //            Calculate the SHA-256 HMAC hash
        //---------------------------------------------------------

        Nullfield = *allx'00';

        my_key.value = %TRIMR(MySalt) + Nullfield;

        my_key.len   =  SaltLen;

        monitor;
              GetHMAC( DataToHash
                          : DataLen
                          : 'DATA0100'
                          : SHA_256
                          : 'ALGD0500'
                          :  my_key
                          : 'KEYD0200'
                          : '0'
                          : *blanks
                          : binaryHMAC
                          : ErrorCode );
        on-error;
          WsErrorCode = ErrorCode;
          Dsply 'Error in Conversion';
        endmon;

        cvthc( $hex: binaryHMAC: %len(binaryHMAC)*2);
        //review the dump spool file to see HMAC in $hex parm
        dump;
        *inlr = '1';
        return;

        /end-free    

[{"Product":{"code":"SWG60","label":"IBM i"},"Business Unit":{"code":"BU054","label":"Systems w\/TPS"},"Component":"Programming (Languages- compilers- tools)","Platform":[{"code":"","label":"iSeries"},{"code":"PF012","label":"IBM i"}],"Version":"7.2;7.1","Edition":""},{"Product":{"code":"SSC5L9","label":"IBM i 7.2"},"Business Unit":{"code":"BU054","label":"Systems w\/TPS"},"Component":" ","Platform":[{"code":"","label":""}],"Version":"","Edition":""},{"Product":{"code":"SSC52E","label":"IBM i 7.1"},"Business Unit":{"code":"BU054","label":"Systems w\/TPS"},"Component":" ","Platform":[{"code":"","label":""}],"Version":"","Edition":""}]

Document Information

Modified date:
18 December 2019

UID

nas8N1021175