Question & Answer
Question
Example of how to use Qc3CalculateHMAC with ILE RPG IV program.
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.ibm.com/docs/en/i/7.5?topic=ssw_ibm_i_75/apis/qc3calhm.html
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.
Example ILE RPG IV HMACRPG1:
Type command, press Enter.
===> CALL HMACRPG1
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
Compile using CRTBNDRPG.
Call program from command line.
Call program from command line.
Type command, press Enter.
===> CALL HMACRPG1
Display the generated spoolfile QPPGMDMP and examine variable $HEX
This is a partial snippet of the QPPGMDMP spoolfile :
Internal Indicators:
LR '0' MR '0' RT '0' 1P '0'
NAME ATTRIBUTES VALUE
$HEX CHAR(64) '39B0B5FE1C9A5EAB64E714BCEBCD938EC49E9C0038AA53D344355F68AE6CDAC8'
VALUE IN HEX 'F3F9C2F0C2F5C6C5F1C3F9C1F5C5C1C2F6F4C5F7F1F4C2C3C5C2C3C4F9F3F8C5C3F4F9C5F9C3F0F0'X
41 'F3F8C1C1F5F3C4F3F4F4F3F5F5C6F6F8C1C5F6C3C4C1C3F8'X
BINARYHMAC CHAR(32) ' ^§Ú ª;¿ÀX ¯ÔòlþDÆæ ¡ëLà ¬ÇÞ%¹H'
VALUE IN HEX '39B0B5FE1C9A5EAB64E714BCEBCD938EC49E9C0038AA53D344355F68AE6CDAC8'X
DATALEN UNS(10) 16 '00000010'X
[{"Type":"MASTER","Line of Business":{"code":"LOB68","label":"Power HW"},"Business Unit":{"code":"BU070","label":"IBM Infrastructure"},"Product":{"code":"SWG60","label":"IBM i"},"ARM Category":[{"code":"a8m3p000000hB4rAAE","label":"API"},{"code":"a8m0z0000000CHtAAM","label":"Programming ILE Languages"}],"ARM Case Number":"","Platform":[{"code":"PF012","label":"IBM i"}],"Version":"All Versions"}]
Was this topic helpful?
Document Information
Modified date:
25 November 2024
UID
nas8N1021175