project QadFinancials > class TOpenSSL > method SignStringUsingOpenSSL

Description

This method will receive a string and create a signature for it based on the private key. The private key is stored in an encrypted way and will be decrypted before calling the OpenSSL program.
A small batch file will be created to run the OpenSSL


Parameters


icStringToSigninputcharacterA signature will be created for this string using the private key.
icOpenSSLDirinputcharacterLocation of OpenSSL.exe
iiSessionIdinputintegerSession ID
ocSignatureForInputStringoutputcharacterThe signature that was created for the input string using OpenSSL with a private key.
ocMessageoutputcharacterMessage to display in calling procedure.
oiReturnStatusoutputintegerReturn status of the method.


Internal usage


QadFinancials
method BCInvoice.PreSave
method BDInvoice.PreSave


program code (program6/topenssl.p)

assign ocSignatureForInputString = "".
/* ================================================================== */
/* State the Session-ID                                               */
/* needed to make it possible to set debug level                      */
/* ================================================================== */
assign viSessionId           = iiSessionId
       viSessionInTOpenSSLId = iiSessionId.

/* ================================================== */
/* Leave this method when there is nothing to encrypt */
/* or when the calling handle was not passed          */
/* ================================================== */
if icStringToSign = "" or
   icStringToSign = ?  
then return.

/* ==================================================================== */
/* Check if we are using a windows based or Unix based operating system */
/* ==================================================================== */
if opsys <> "UNIX" and 
   opsys <> "WIN32"
then do:
    assign ocMessage      = Substitute(#T-8'The operating system used (&1) is not supported for Invoice Certification.':255(611501895)T-8#, string(opsys))
           oiReturnStatus = -1.
    return.
end. /* if opsys <> "UNIX" and */

/* ======================================================== */
/* Check if we need to retrieve and decrypt the private key */
/* ======================================================== */
if vcPrivateKey = "" or
   vcPrivateKey = ?
then do:
    /* ================================== */
    /* Retrieve the encrypted private key */
    /* ================================== */
    assign vcEncryptedPrivateKey = "B64:yKJSccZ0xHaByxEELzytyNqhm4RGN5So6p3WFE+nXHWHC4dIW78PskYKiVdKGDb5HZWNzZKzLEB+1GC3AVLyTggC5x2wR0Ngd3fPcGJaY9a+QQhvy9s/B0vGtddrVMsB1zAyDPIYZinnDC/anmKscz/YWKS31bSWXlcgM1YODpWwfuhaO2VblVEZqaV7ZBCC6k2bIxqNDJNexfiIpm71le9l2iVMUOty8rgzEJ5PhQVZRyEa5VUq5owSxuNEMAa+qooHI7rZ5nHcWZPLh1usxa9DSNdCdg9ILJuxOGTvGV93n9gDNjo+qCh24vDePHcYvOSwAOQjMnx1nbsfIqgWJw5myfk8XLbZr/TXIQJmDyFkmEOyE/rTMQG4/bM25psBj+ShT+f36pE+mG54k0B1Dkbe5UxJiX+Tu6LJZNdCPHq5s4TQPhKZ79SBR3B3yhN1FXQhrOYp8iLM8LYYhx+keubI9xdcR6sDBQLMXolynp7Eg8ayxEPRjN2LlcqljxqG6sRzfKTJ9PdXnN7o80ySL3/xwn5Y7zMRj6xvFE+nO82rZcZxST/p/wULeaGFyxQ1w2A5allith7RbDumxRbi81OE5ugbGV/MGavsO9e/gpxnkZI0KrOWZLX61B+YLwpPNY0B/9MYVS8Fvk6lac/xnjgJTtoks5WZhYxB9qJ6FezF3LBiweeMTzH7ebU/etlb3zl2ukicfMlYtMDbh6a4SfKbXQFhNRg/Lhi0XcrIIDBiFSOdsN5TwIxn5hcRuebLreOmSeulUJKajaLGZMvjJU57sxKsqGL7ZYGw/oXxJ8YusiEE3DeLfexTO7IQsp0ybIGAOxPq6oZRo+4e4kdjL8rwwsWKC0KvFLrJphcfmLM1cJcmMs+YDezMg/Pw9JN9++UvplwLPCpXSDmgcPMfPUkr5Oq2pyk7YKJ6O7K8x5S1/BOP+2HsiKs7VW5rJWpFy3DbFccWKKKMcpGoyY3/HnCYsJrvB3dhAthTZbZLpLUXei3j3h/I0o9GzmZB3JIRuR17Yhp6bqqF8m4uyaZ1N4O44AJcBrvyU9S7T0ChOuYOmNAEEPuMFEyIKrZU/f3S1roJxAVVR6/uHzT5uB/qj3AkU6iHhOU5eed3+C6tFUTLNXdl0DpUkb0XMmig9hNF5wMc5HVXtLdvFSuGYaRw6GRoi+YZTpzBj2PoCFTPfkI=". 
                                /* "B64:yKJSccZ0xHaByxEELzytyNqhm4RGN5So6p3WFE+nXHX4ozZSiXve6bRBGubGpw6JQGbwnBjrkINCrPEpfJczMIg2NOXeVtr/f1SR2Gq937SUShgl8u22hqWw2yLp/jHRw0c2l819jQsAIoVzKC89LmqHS/UJHGFVZiyIY//Cn2Gt1ppDqkYOPKlMiUaDYMsSUY9s8L6C4SMdxt1EtyXGDgXjVVw9/h8z2sKu9B5SUPPhcev6Cu+BNN+fP55mLBMj8nI+iNvFOhj+JfiZU3fSif7CmKSwr675jTl6WqqEMLdUJIUN6FxeR8hfo6ZhSU5d0BLnETF/TQVrBSrfIPJZz4YaRR9XkhICBEO7r4nuYmsN7MreZzgRXCrU3ZXF5bbQh3xHOq1ZOY/NyruqoLBLX6+BRbA3OsJyvDhoAwIFx/dFfzvbyyJn+gJHdQS4Qry/LWdrMMTvktGZh5Qy0Zh4ngg9EUGW+tp7FzWNIFHOEUlc/IwUiYRUr2+XGWSfw3csrU4AfeCvD8uZV70hN1u1HW5o6t6duE22cgjEBgnNQaOiYBvYNFKuUIDeIvPanQUAsrRB67tIBO+huC56ShuIUHECR6hE6WwKlk+72UqdfHwHow0tcUzXU7FZW1sApt+H0MZHAFqjxavqXOOOmphw+gT4rtrIlHk+1GXALZvKRwXU1jkIUW1I1LkVKK41+uQLnfhviQ4236Be8fE7pjifhQV7pObFlLxT29acqKBnTdMz5f9LhGSLtrwTprMjwt8X1OBJvaUplTJiPf0OkXo1mi1UZQ9qbaCnuKVgI3WFqqFxc/Z6P6d4da5UCHNcUIrBVh8fUQv7r+tooLPUTjSMcm7L3IgC9NN+hYX/+UouWKd+ojzwmcAUA7IRXAiPfAKclsQeCvYQ/DvbN18TH5T4eSLl0GqREgyY0TRkDGA7rJ6HWZ2xXgIGD/+yrcBbdUS+PfNfWPzy0AkVjZS4wkz98gSjNWxV2EQU7zNI6m94yMV54K5/hoQyflBJ18QZJwqcbeypE3HfQ535WESZ/0CR2eFaV3ltB1JfhhxTlTfKZ1gzzJo5LWoKCfmBgrmlY8S+i6PPf95q23fdYRicI97+YF/vnyocx1Bwktw3q6PKdABQpztPcHfQk9l0uCK6NaykRSVNjXHxp+h5G1Mp6gODAm6R+MB1O3/4H/V7gRDXIRA=". */

    /* ========================================================================== */
    /* Disable Logging to prevent that the private key ends up in the ct-log file */
    /* ========================================================================== */
    <I-52 {tFcOpenInstance
         &CLASS                = "Session"
         &SESSIONID            = "iiSessionId"}>
 
    <M-94 run GetIntegerValue
       (input  'SessionDebugLevel':U (icName), 
        output viCurrentDebugLevel (oiValue), 
        output viExternalReturnStatus (oiReturnStatus)) in Session>
 
    <M-27 run SetDebugLevel  (input  0 (iiDebugLevel)) in Session>

    <I-60 {tFcCloseInstance
         &CLASS           = "Session"}>
         
    if viExternalReturnStatus < 0 or (viExternalReturnStatus > 0 and oiReturnStatus = 0)
    then assign oiReturnStatus = viExternalReturnStatus.

    /* ======================= */
    /* Decrypt the private key */
    /* ======================= */
    assign vhFcComponent = ?.
    <M-55 run MainBlock  () in TCrypt>
    assign vhCrypthandle = vhFcComponent.
    
    <M-20 run DecryptString
       (input  vcEncryptedPrivateKey (icInputString), 
        output vcPrivateKey (ocOutputString), 
        output viExternalReturnStatus (oiReturnStatus)) in TCrypt>
 
    run gipr_DeleteProcedure in vhCrypthandle.
    delete procedure vhCrypthandle.
    
    /* ====================== */
    /* reset the ct-log value */
    /* ====================== */
    <I-23 {tFcOpenInstance
         &CLASS                = "Session"
         &SESSIONID            = "iiSessionId"}>
            
    <M-88 run SetDebugLevel  (input  viCurrentDebugLevel (iiDebugLevel)) in Session>

    <I-37 {tFcCloseInstance
         &CLASS           = "Session"}>

    if viExternalReturnStatus < 0 or (viExternalReturnStatus > 0 and oiReturnStatus = 0)     
    then assign oiReturnStatus = viExternalReturnStatus.
    if viExternalReturnStatus < 0
    then return.    
end. /* if vcPrivateKey = "" or */

/* ============================ */
/* Save the decoded private key */
/* ============================ */
assign vcPrivateKeyFile = SESSION:TEMP-DIRECTORY + "QPKSSL" + string(mtime).
output stream sInvCertific to value(vcPrivateKeyFile).
put stream sInvCertific unformatted vcPrivateKey.
output stream sInvCertific close.

/* ======================= */
/* Save the string to sign */
/* ======================= */
assign vcInvoiceKeyFile = SESSION:TEMP-DIRECTORY + "invoicekey" + string(mtime).
output stream sInvCertific to value(vcInvoiceKeyFile).
put stream sInvCertific unformatted icStringToSign.
output stream sInvCertific close.

/* ====================== */
/* Run OpenSSL using Unix */
/* ====================== */
if opsys = "UNIX"
then do:
    assign vcCommand = 
        "openssl dgst -sha1 -sign " +
        "~"" + vcPrivateKeyFile + "~"" + " " + 
        "~"" + vcInvoiceKeyFile + "~"" +
        " | " + "openssl enc -base64".
end. /* if opsys = "Unix" */
/* ================================================= */
/* Create a batch file to run the OpenSSL in Windows */
/* ================================================= */
else do:
    assign vcCommand = SESSION:TEMP-DIRECTORY + "Encrypt.bat".
    output stream sInvCertific to value(vcCommand).
    put stream sInvCertific unformatted
        "@echo off" skip
        "set PATH=" + icOpenSSLDir + ";%PATH%" skip
        "set OPENSSL_CONF=" + icOpenSSLDir + "openssl.cfg" skip
        "openssl dgst -sha1 -sign " 
        "~"" vcPrivateKeyFile "~"" " "
        "~"" vcInvoiceKeyFile "~""
        " | openssl enc -base64".
    output stream sInvCertific close.
end. /* if opsys = "WIN32" */

/* ======================================================================================= */
/* run the encryption program                                                              */
/* Because we use the import statement, we loose the LF or CR that might be in the output. */
/* That is exactly what we want, because the signature is one line of 172 characters       */
/* ======================================================================================= */
input stream sInvCertific through value(vcCommand).
repeat on error undo, throw:
    import stream sInvCertific unformatted vcImport.
    assign ocSignatureForInputString = ocSignatureForInputString + vcImport.
end. /* repeat: */
input stream sInvCertific close.

/* ====================================================================================================== */                                                                                                          
/* Delete the decoded private key again                                                                   */
/* When an error occurred, we won't give a detailed error message, since the file holds our unencoded key */
/* ====================================================================================================== */
os-delete value(vcPrivateKeyFile).
assign viOSError = os-error.

if viOSError <> 0
then do:
    assign ocMessage      = Substitute(#T-50'An OS Error (&1) occurred.  Please contact your system administrator.':255(556808544)T-50#, viOSError)
           oiReturnStatus = 1.
    return.           
end. /* if viOSError <> 0 */

/* ================================= */
/* Check if the string was encrypted */
/* ================================= */
if ocSignatureForInputString = "" or 
   ocSignatureForInputString = ?  or
   length(ocSignatureForInputString, "CHARACTER") <> 172
then do:
    assign ocMessage      = #T-84'Unable to sign the string.  Please contact your system administrator.':255(245043598)T-84# + chr(10) +
                            substitute(#T-74'Details: &1':255(134924763)T-74#, string(ocSignatureForInputString)) + chr(10) +
                            substitute(#T-96'String to sign: &1':255(633142903)T-96#, icStringToSign)
           oiReturnStatus = -3.
    return.           
end. /* if ocEncryptedString = "" or */