Encode Base64 doesn't return the correct value

Discussions relating to writing software in ILE RPG (RPG IV). This includes both fixed and free format RPG.
hmauricio
Posts: 7
Joined: Fri Jul 01, 2022 3:09 pm

Encode Base64 doesn't return the correct value

Post by hmauricio »

Hello Scott,
i'm using your encode/decode service program to encode a signature returned from the Qc3CalculateSignature API, this is
for generate an Hash for tax purposes, what's happening is that sometimes the returned encoded value is not correct.

I'm enconding the *Hex variable returned from the API, and sometimes not always, the returned value is not correct,
but just the last 3 characters, it ends with "==" the rest of the string is Ok.

I dont know if you can help me on this.

Hex Signature returned from the API: 088A95B2D16E2386B8E0E605715211EE785FF92CE539514904ECEEE815BB73F0D7DC58F2A6B9ECE7B22ED7F453AC69EF55CAC47386CEEF6E0821835D1C8545B91D69F36F7AE74E6F661377AD773CEFD2922C36451FC527AD6B5DB766740AE0F0B4F2B46997C494CE099060A2987EB14B7B465557EF3E1623EEC884DEB9DAA1

Expected Value after Base64 Encode:
CIqVstFuI4a44OYFcVIR7nhf+SzlOVFJBOzu6BW7c/DX3Fjyprns57Iu1/RTrGnvVcrEc4bO724IIYNdHIVFuR1p8296505vZhN3rXc879KSLDZFH8UnrWtdt2Z0CuDwtPK0aZfElM4JkGCimH6xS3tGVVfvPhYj7siE3rnaoUA=

Encoded string received from Encode Service program:
CIqVstFuI4a44OYFcVIR7nhf+SzlOVFJBOzu6BW7c/DX3Fjyprns57Iu1/RTrGnvVcrEc4bO724IIYNdHIVFuR1p8296505vZhN3rXc879KSLDZFH8UnrWtdt2Z0CuDwtPK0aZfElM4JkGCimH6xS3tGVVfvPhYj7siE3rnaoQ==

As you can see only the last characters are wrong, but as i said before this only happends in some signatures, the majority are Ok.

Best Regards
Helder
Scott Klement
Site Admin
Posts: 636
Joined: Sun Jul 04, 2021 5:12 am

Re: Encode Base64 doesn't return the correct value

Post by Scott Klement »

How can I reproduce the problem?
hmauricio
Posts: 7
Joined: Fri Jul 01, 2022 3:09 pm

Re: Encode Base64 doesn't return the correct value

Post by hmauricio »

Hello Scott,

i've a program that receives a string to be encoded, it call's the Qc3CalculateSignature API and sends that string to
calculate the signature, then with the received signature i'm calling your service program to encode to Base64.

This is the string received that as to be encripted, this string is the one that generates the strings i've sent you before.

I don't know if this helps, i really don't know how you can reproduce the problem, just if you run my program in my PC.

Received string:
2022-05-06;2022-05-06T07:43:08;GR GR1/89922;245.41;h2S0asnn1XUkapcodcE0qE+Fl7f0wC80uX3QXhY1eKfmBYwrY9Bc6+MIu6imSMc4dfZ/BYHqJY76lxfipg3WpRwbeIagen3wqXs5l+dH3icrNam8xO/BOYwLgABSrUO9CbJblI96iYhJa4tb1EvH0fjL5h50OmIdxlYpNdm3Vbo=

Best regards
jonboy49
Posts: 200
Joined: Wed Jul 28, 2021 8:18 pm

Re: Encode Base64 doesn't return the correct value

Post by jonboy49 »

What's really needed is to see how you do the call to Scott's routine. The variable definitions etc. Repeating the same basic stuff you showed before doesn't help.
hmauricio
Posts: 7
Joined: Fri Jul 01, 2022 3:09 pm

Re: Encode Base64 doesn't return the correct value

Post by hmauricio »

The call :

base64_encode(%addr(signature)
: %len(%trimr(signature))
: %addr(hashg)
: %size(hashg));

Variables definition:
dcl-s signature char(512) ccsid(*hex);
Dcl-S hashg Char(2732) inz(' ');

The variable "Signature" is the result of the API
Qc3CalculateSignature(
StringHash :
%len(stringHash) :
'DATA0100' :
algorithmDescription :
'ALGD0400' :
keyDescription :
'KEYD0400' :
ANY_CRYPTO_SRV :
'' :
signature :
%size(signature) :
signatureLength :
stdError
);
Hope this helps.

Thankyou for your reply.
hmauricio
Posts: 7
Joined: Fri Jul 01, 2022 3:09 pm

Re: Encode Base64 doesn't return the correct value

Post by hmauricio »

For better undeestanding of what i'm doing, this is the full code.
//------------------------------------------------
CTL-Opt Option(*NoDebugIO:
*SRCSTMT);
CTL-Opt DFTACTGRP(*NO);
// CTL-Opt BNDDIR('QC2LE');
CTL-Opt BNDDIR('BASE64');
//------------------------------------------------
// E N T R Y P A R M S **
//-----------------------------------------------
DCL-PI *N; //hashgen_ap;
keyencrip char(32);
stringent char(250);
stringsai char(200);
END-PI;
//-----------------------------------------------
// The QUSEC Source Contains the Common Error Code Data Structure.
//-----------------------------------------------
/End-free
D/COPY QSYSINC/QRPGLESRC,QUSEC
D stdError DS qualified
D QUSEC likeDs(QUSEC)
D outError 1024A
/free
/copy BASE64_H
//-----------------------------------------------
dcl-c HASH_ALGORITHM_SHA1 2;
dcl-c HASH_ALGORITHM_SHA256 3;

dcl-c CRYPTO_ALGORITHM_RSA 50;

dcl-ds t_ALGD0400 len(12) qualified template;
publicKeyCipherAlgorithm int(10) pos(1);
pkaBlockFormat char(1) pos(5);
signingHashAlgorithm int(10) pos(9);
end-ds;

dcl-ds t_KEYD0400 len(56) qualified template;
keystoreFile char(10);
keystoreLibrary char(10);
recordLabel char(32);
end-ds;

dcl-pr Qc3CalculateSignature extproc(*dclcase);
inputData char(30000) options(*varsize) const;
inputDataLength int(10) const;
inputDataFormat char(8) const;
algorithmDescription char(32000) options(*varsize) const;
algorithmDescriptionFormat char(8) const;
keyDescription char(30000) options(*varsize) const;
keyDescriptionFormat char(8) const;
cryptoServiceProvider char(1) const;
cryptoDeviceName char(10) const;
signature char(512) ccsid(*hex) options(*varsize);
signatureLengthProvided int(10) const;
signatureLengthReturned int(10);
errorCode like(qusec);
end-pr;
//------------------------------------------------
// Stand alone fields definition
//------------------------------------------------
dcl-ds keyDescription likeds(t_KEYD0400);
dcl-ds algorithmDescription likeds(t_ALGD0400);
//dcl-ds qusec likeds(t_qusec) inz;
dcl-s signature char(512) ccsid(*hex);
dcl-s signatureLength int(10);
dcl-s StringHash varchar(65534) ccsid(*hex);
// dcl-s StringHash char(512) ccsid(*hex);
Dcl-S hashg Char(2732) inz(' '); //ccsid(819);
// Dcl-S hashg char(23096) inz(' ') ccsid(1208);
//
dcl-c ANY_CRYPTO_SRV Const('0');
dcl-c SWF_CRYPTO_SRV Const('1');
dcl-c HWD_CRYPTO_SRV Const('2');
dcl-s CRYPTO_SRV Char(10) inz(' ');
dcl-s outstring Char(50) inz(' ');
dcl-s wait Char(1) inz(' ');
dcl-s AsciiData char(750) ccsid(819);
//------------------------------------------------
// MAIN ROUTINE
//------------------------------------------------
Exsr CvtRecStr; // Converte string recebida no PARM
Exsr KeyDesDef; // Trata DS KeyDescription
Exsr AlgDesDef; // Trata DS AlgorithmDescription
Exsr CallAPI; // Chama API Qc2CalculateSignature
// Se existiu erro, mostra erro no ecra
F If stdError.qusec.qusbavl > 0;
| outstring = stdError.qusec.qusei;
X Else;
| Exsr CvtBase64; // Converte p/base64
E Endif;
*inlr = *on;
//------------------------------------------------
// CvtRecStr - Converte a string recebida de EBCDIC-ASCII-HEX
//------------------------------------------------
begsr CvtRecStr;
clear stringsai;
AsciiData = %Trim(stringent); // EBDCDIC -> ASCII
StringHash = %Trim(AsciiData); // ASCII -> HEX
Endsr;
//------------------------------------------------
// KeyDesDef - Trata campos DS KeyDescription
//------------------------------------------------
begsr KeyDesDef;
keyDescription = *allx'00';
keyDescription.keystoreFile = 'TESTE_KEY';
keyDescription.keystoreLibrary = '*LIBL';
keyDescription.recordLabel = %trim(keyencrip);
Endsr;
//------------------------------------------------
// AlgDesDef - Trata campos DS AlgorithmDescription
//------------------------------------------------
begsr AlgDesDef;
algorithmDescription = *allx'00';
algorithmDescription.publicKeyCipherAlgorithm = CRYPTO_ALGORITHM_RSA;
algorithmDescription.pkaBlockFormat = '1';
algorithmDescription.signingHashAlgorithm = HASH_ALGORITHM_SHA1;
Endsr;
//------------------------------------------------
// CallAPI - Chama API Qc2CalculateSignature
//------------------------------------------------
begsr CallAPI;
Qc3CalculateSignature(
StringHash :
%len(stringHash) :
'DATA0100' :
algorithmDescription :
'ALGD0400' :
keyDescription :
'KEYD0400' :
ANY_CRYPTO_SRV :
'' :
signature :
%size(signature) :
signatureLength :
stdError
);
Endsr;
//------------------------------------------------
// CvtBase64 - Converte signature para Base64
//------------------------------------------------
begsr CvtBase64;
Clear hashg;
base64_encode(%addr(signature)
: %len(%trimr(signature))
: %addr(hashg)
: %size(hashg));
stringsai = %Trim(hashg); // Parametro saida
Endsr;
//------------------------------------------------
/End-free


Best regards
Scott Klement
Site Admin
Posts: 636
Joined: Sun Jul 04, 2021 5:12 am

Re: Encode Base64 doesn't return the correct value

Post by Scott Klement »

This is the problem:

%len(%trimr(signature))

You can't use %trimr on a binary field. If the number x'40' happens to be at the end, it will remove it -- because it considers x'40' a blank -- which is exactly the difference between the two base64 string you posted at the start of this thread.

You have to pass the actual length of the signature, not calculate it by trimming blanks and seeing how long the result is.
hmauricio
Posts: 7
Joined: Fri Jul 01, 2022 3:09 pm

Re: Encode Base64 doesn't return the correct value

Post by hmauricio »

Thanks Scott,
i'll try that and get back to you.


Best regards
hmauricio
Posts: 7
Joined: Fri Jul 01, 2022 3:09 pm

Re: Encode Base64 doesn't return the correct value

Post by hmauricio »

Well Scott, i tried as you said, remove the %Trim, but the problem now is that now we've the blanks of the signature field on the encoded field as you can se, and besides that the encoded isnt correct either, the last characters should be UA= and not UB and then followed by all the blanks .

Encoded String:
CIqVstFuI4a44OYFcVIR7nhf+SzlOVFJBOzu6BW7c/DX3Fjyprns57Iu1/RTrGnvVcrEc4bO724IIYNdHIVFuR1p8296505vZhN3rXc879KSLDZFH8UnrWtdt2Z0CuDwtPK0aZfElM4JkGCimH6xS3tGVVfvPhYj7siE3rnaoUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEA=

Correct String:
CIqVstFuI4a44OYFcVIR7nhf+SzlOVFJBOzu6BW7c/DX3Fjyprns57Iu1/RTrGnvVcrEc4bO724IIYNdHIVFuR1p8296505vZhN3rXc879KSLDZFH8UnrWtdt2Z0CuDwtPK0aZfElM4JkGCimH6xS3tGVVfvPhYj7siE3rnaoUA=

Actual call:
base64_encode(%addr(signature)
: %len(signature)
: %addr(hashg)
: %size(hashg));

Helder
jonboy49
Posts: 200
Joined: Wed Jul 28, 2021 8:18 pm

Re: Encode Base64 doesn't return the correct value

Post by jonboy49 »

The signature length is being returned to by Qc3CalculateSignature. Any reason you cannot use that ?
Post Reply