ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Qc3CalculateSignature rsassa-pss

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Qc3CalculateSignature rsassa-pss

    I am working on integrating to amazon pay v2 and have most of it ready I am stuck on creating my signature with a salt length of 20. Does not seem to be an option in the api, do I need to use a different api first?



    I am able to verify amazon output using my public certificate in python. But when I try and generate it in rpg the output is the same every time which it shouldn't be and it will not verify. I need to use a salt length of 20 to create a randomized output that will verify.

    Code:
    from Crypto.Signature import pss
    from Crypto.Hash import SHA256
    from Crypto.PublicKey import RSA
    import base64
    
    #amazon message works
    message = b'AMZN-PAY-RSASSA-PSS\n346fe3fb1b84bac499c3f7dd1300fd34c3f7635eba8930fd682692a94d88f248'
    signature = base64.b64decode('E8uc9hOs+w5Y3+2KZlNRaP6npwsfV+hjosibPj7z5yDEqjUGLJ2h8KkT+EYk/Lbeb7QDWPots2c7g2oxNYkRrWZko+HcmgzNT/hM1mvjHADB5wZJzfNuy9TerTKZ4xYrJRKmWNzptjKSJYqhCuO0ZMK1OvStc2cSTpBNPQ2dDVcLNnIsIqyxBJlwPNrC3b8xkK36wpF/rcqUJ4osWBvAZFGtLTpSEbdSlzUno5PdgPyisiXZqmaf1Wv74I7bbR4WPZTXHDa0B3tZGrklhBgJU1tcqMX7dmPUzqUrQcNTPwPA2qIYXJ6uk3iZST768lB/sUleuq7MA7bfU6EmU0rwfg==')
    print(signature)
    
    #my test does not
    #message = b'test'
    # signature = base64.b64decode('rIDc/qoQ+0mLBYN1ym0zEh7Qz2bt11KZKN1iLBOcaKHtWhhhdsPQ7HeweEc8uq8HVCFPamWWKRrg7mYhbaQXPNLU2VzRnlVY0S8K530fSN8jIGVbN9qa8vrM11WOWoE5glKlZM8qDGzCQUEpqmU+kBC8TA5tlbbMCuRZu2vH9t8qxCjEXDd78lERLLyCnAg5k0ykyHCDo4soTNLGb3UzjMg5kkQN+HQFHxyXUAlaDec3Z+xLlWBGmj+3ANcSQ/u6qjA0pWWvqIrEYkX1PXgmnrzPz9oDSyRB82piOLzESiPt6w/scdWmPSeKVgi5tXRVhxTMqBwqYEVCbUnc5AOoTg==')
    # print(signature)
    
    key = RSA.import_key(open('C:/Users/jerry.dahlheimer/Desktop/temp project files/mis-86272 amazon pay v2/publicKey.pub').read())
    h = SHA256.new(message)
    verifier = pss.new(key,salt_bytes=20)
    
    try:
        verifier.verify(h, signature)
        print("The signature is authentic.")
    except (ValueError, TypeError):
        print ("The signature is not authentic.")​
    Rpg code
    Code:
           // header specifications
           /Include qcpysrc,copyhspec
           ctl-opt bnddir('BASE64');
    
           // include procedure definitions
           /Include qcpysrc,copyallprc
           /Include qcpysrc,copypsds
    
           /copy qrpgsrc,base64_h
           /COPY QSYSINC/QRPGLESRC,QUSEC
           /COPY QSYSINC/QRPGLESRC,QC3CCI
    
    
           dcl-c HASH_ALGORITHM_SHA256 3;
    
           dcl-c CRYPTO_ALGORITHM_RSA 50;
           Dcl-C ANY_CSP '0';
    
           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;
    
           Dcl-S publickey varchar(50);
           Dcl-S privateKey varchar(2000);
           dcl-s output varchar(52);
    
           Dcl-S base64 char(3200);
    
    
           dcl-S E@Encrypt char(2000);
           dcl-s wwEncLen int(10);
    
           dcl-s payload varchar(10000) ccsid(*hex);
           dcl-ds keyDescription likeds(t_KEYD0400);
           dcl-ds algorithmDescription likeds(t_ALGD0400);
           dcl-s signature char(512) ccsid(*hex);
           dcl-s signatureLength int(10);
    
           keyDescription = *allx'00';
           keyDescription.keystoreFile = 'TESTKEY';
           keyDescription.keystoreLibrary = 'MISJD';
           keyDescription.recordLabel = 'testkey';
    
           algorithmDescription = *allx'00';
           algorithmDescription.publicKeyCipherAlgorithm = CRYPTO_ALGORITHM_RSA;
           algorithmDescription.pkaBlockFormat = '1';
           algorithmDescription.signingHashAlgorithm = HASH_ALGORITHM_SHA256;
    
           GetAttributes();
    
           payload = 'test';
    
           Qc3CalculateSignature(
           payload :
           %len(payload) :
           'DATA0100' :
           algorithmDescription :
           'ALGD0400' :
           keyDescription :
           'KEYD0400' :
           ANY_CSP :
           '' :
           signature :
           %size(signature) :
           signatureLength :
           qusec
             );
    
             //  output = signature;
           //  dsply output;
    
           wwEncLen = base64_encode(%addr(signature)
           : signatureLength
           : %addr(base64)
           : %size(base64));
    
             E@Encrypt = %subst(base64:1:wwEncLen);
    
    
           Exec Sql
             Set Option Commit = *None;
    
           Exec Sql
             Insert Into Holdxml
               Values
                 (Trim(:E@encrypt));
    
    
           *inlr = *on;
           return;
    
           Dcl-Proc GetAttributes;
    
             Exec Sql
               Select Trim(Appubkey),
                      Trim(Apprivkey)
                 Into :Publickey,
                      :Privatekey
                 From Amzpayf01
                 Fetch First Row Only;
    
           End-Proc;
      ​

  • #2
    Hi, I don't know which is you base64_encode, why don't you try with sql function?

    The BASE64_ENCODE scalar function returns the Base64 encoded version of a binary value.


    Does the variable base64 has to be with ccsid(819)?

    Bye

    Comment


    • #3
      It is from klement and I have always used it as I had issues with the sql function at one point in time and since stuck with it and has worked with other amazon apis. But I changed it out and it creates the same output. The salt I think is key as it generates a random output and that is a requirement of Amazon.

      Code:
      Exec Sql
               Insert Into Holdxml
                 Values
                   (QSYS2.BASE64_ENCODE(:signature));

      Comment


      • #4
        Does the api Qc3CalculateSignature return some error?

        You don't check Qusec.

        Comment


        • #5
          No error. I was checking it in debug. The signature verifies in python if I remove the salt and change to pkcs1. So I am still leaning towards the signature signing needs to be updated to use a salt value.

          Code:
          verifier = pss.new(key,salt_bytes=20)
          
          verifier = PKCS1_PSS.new(key)

          Comment

          Working...
          X