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
icStringToSign | input | character | A signature will be created for this string using the private key. |
icOpenSSLDir | input | character | Location of OpenSSL.exe |
iiSessionId | input | integer | Session ID |
ocSignatureForInputString | output | character | The signature that was created for the input string using OpenSSL with a private key. |
ocMessage | output | character | Message to display in calling procedure. |
oiReturnStatus | output | integer | Return status of the method. |
Internal usage
QadFinancials
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 */