Introduction
Welcome to PKI Proxy, an easy-to-use solution for sharing private keys over the network.
PKI Proxy works by sharing local private keys files securely across the network. Common key formats are supported including hardware security module (HSM)-based private keys, PFX files, and certificates installed to the Windows stores. PKI Proxy provides access to restricted or single-copy-only keys to remote signers.
Description
PKI Proxy consists of two principal modules:
- The sharing application that runs on the system that will host the private key, such as a corporate signing server.
- The PKCS#11 driver that the signing applications use to access the sharing application.
Features
PKI Proxy offers the following features:
- Works with remote certificates as if they were present on your local system.
- All PKCS#11-capable signers supported, including jarsigner, Acrobat, and SignTool.
- Most modern HSM deployments supported.
- Communication protocol based on open standards.
- Efficient, secure, and scalable solution.
Additional Information
You will always find the latest information about PKI Proxy at our web site: www.nsoftware.com. We offer free, fully-functional 30-day trials for all of our products, and our technical support staff are happy to answer any questions you may have during your evaluation.
Please direct all technical questions to support@nsoftware.com. To help support technicians assist you as quickly as possible, please provide an detailed and accurate description of your problem, the results you expected, and the results that you received while using our product. For questions about licensing and pricing, and all other general inquiries, please contact sales@nsoftware.com.
Thank You!
Thank you for choosing PKI Proxy. We realize that you have a choice among tools, and that by choosing us you are counting on us to be a key component in your business. We work around the clock to provide you with ongoing enhancements, support, and innovative products; and we will always do our best to exceed your expectations!
Running PKI Proxy
Getting Started
Setting up PKI Proxy involves configuring the two sides of the communication channel:
- The Web API that will be sharing the keys.
- The PKCS#11 driver that the applications will be using to access the shared key.
Configuring the Server
The PKI Proxy Service is responsible for making local signing keys available to applications residing outside the system.
To share a certificate, first configure the Transport Layer Security (TLS) settings for PKI Proxy on the Settings tab, and then create a user on the Users tab. Finally, move to the Certificates tab and click the 'New...' button to create a new certificate share. Select the certificate you want to share and provide an optional alias (e.g., 'Driver signing'), and then select users that will have access to the certificate and click OK to complete the setup.
Configuring the Client
The clients use the PKI Proxy PKCS#11 driver to access the shared certificate remotely. The driver takes PKCS#11 requests from third-party applications, such as jarsigner, and translates them to calls to the PKI Proxy Web API.
The PKI Proxy PKCS#11 driver is installed alongside the PKI Proxy application in the 'pkcs11' directory. Two versions of the driver are provided: for 32- and 64-bit applications. Both drivers are fully portable and do not depend on any third-party components; you can simply copy them to the client system(s) to be able to use them.
The driver is configured through a configuration file, which should have the same name as the driver DLL but have a .conf extension and reside in the same directory. For instance pkiproxy_pkcs11.conf should be placed next to pkiproxy_pkcs11.dll.
Use the following format for the configuration file:
# This file contains settings for the PKI Proxy PKCS#11 driver. # Please adjust the following parameters to match the actual settings # of the PKI Proxy sharing application. # The online location of the shared certificate. # # Please check that the endpoint is reachable and/or # allowed through the firewall if accessing # the certificate over the Internet. Location = https://127.0.0.1:9266 # Access credentials: These credentials should match the credentials # configured in the PKI Proxy server application. KeyId = User KeySecret = User_Secret_Access_Key # TrustedTLSCerts should match the fingerprint of the Transport Layer Security (TLS) certificate, # as configured in the PKI Proxy service. For instance: # # TrustedTLSCerts = 68D2E3D6A0FE5FEA72E25AD56706270F9F8B182A TrustedTLSCerts = TLS_Fingerprint_From_PKI_Proxy # The optional PIN setting configures the driver to request a PIN # from any application that uses the PKCS#11 driver. When set, a # connecting application must specify the PIN that matches the value # set here. If not set (default), no PIN is required. # # Note: This PIN is exchanged only between the connecting application # and the PKCS#11 driver. It is not used to access the shared certificate. #PIN = 12345 # Log file location uncomment to enable logging. # # Provide the required verbosity level. Possible values are as follows: # 0 - None # 1 - Error # 2 - Warning # 3 - Info (Default) # 4 - Verbose # 5 - Debug #LogFile = C:\temp\pkiproxy.log #LogDetail = 5
Security
General Security Notes
PKI Proxy enables signing operations using keys stored remotely to the signing device, and implements multiple layers of security that provide strong protection for your data.
Secure at Rest
Your private keys never leave their storage location, regardless if that location is a private key store, on a USB token or in a hardware security module (HSM). PKI Proxy communicates with HSMs directly, allowing it to perform security operations without exposing the signing key.
Any sensitive data used by PKI Proxy are encrypted using DPAPI and stored securely in the registry. Only the profile owner can decrypt this data.
Secure in Transit
All data in flight are encrypted because connections between the PKI Proxy PKCS#11 driver and the Web API use Transport Layer Security (TLS). The server is built from our own components and features an extremely small surface area.
Access Control and Authentication
The PKI Proxy Web API authenticates clients using a preshared pair of KeyId and KeySecret credentials. Certificate authorization is an allowlist, so signing applications can access only the certificates for which permission has been specifically granted. The PKI Proxy server can be configured to operate in an interactive mode, requiring a user confirmation for every signing request.
The application also creates a detailed log of all operations, which can be configured on the Settings tab.
Driver Configuration
General Information
The PKI Proxy PKCS#11 driver provides a standardized client-side access mechanism to certificates shared using the PKI Proxy Web API. Any third-party application that knows how to work with PKCS#11 can be used with this driver to perform signing.
PKI Proxy includes two versions of the driver, which are applicable for 32- and 64-bit applications:
- pkcs11/win32/pkiproxy_pkcs11.dll
- pkcs11/win64/pkiproxy_pkcs11.dll
When referencing the driver, please use the driver version that matches the architecture of your application.
Installing the Driver
Generally, there are no requirements for PKCS#11 drivers to be installed to a specific location, so it can be used from the default installation directory. However, some applications may require that you copy the driver to one of the standard locations (such as C:\Windows\System32) or add the installation directory to the PATH environment variable.
Configuring the Driver
The driver can be configured by creating a configuration file and placing it in the same folder as the DLL, with the file name matching the name of the driver DLL and a '.conf' extension. For instance, pkcs11/win32/pkiproxy_pkcs11.conf.
Following is an example of the contents of the configuration file:
# This file contains settings for the PKI Proxy PKCS#11 driver. # Please adjust the following parameters to match the actual settings # of the PKI Proxy sharing application. # The online location of the shared certificate. # # Please check that the endpoint is reachable and/or # allowed through the firewall if accessing # the certificate over the Internet. Location = https://127.0.0.1:9266 # Access credentials: These credentials should match the credentials # configured in the PKI Proxy server application. KeyId = User KeySecret = User_Secret_Access_Key # TrustedTLSCerts should match the fingerprint of the Transport Layer Security (TLS) certificate, # as configured in the PKI Proxy service. For instance: # # TrustedTLSCerts = 68D2E3D6A0FE5FEA72E25AD56706270F9F8B182A TrustedTLSCerts = TLS_Fingerprint_From_PKI_Proxy # The optional PIN setting configures the driver to request a PIN # from any application that uses the PKCS#11 driver. When set, a # connecting application must specify the PIN that matches the value # set here. If not set (default), no PIN is required. # # Note: This PIN is exchanged only between the connecting application # and the PKCS#11 driver. It is not used to access the shared certificate. #PIN = 12345 # Log file location uncomment to enable logging. # # Provide the required verbosity level. Possible values are as follows: # 0 - None # 1 - Error # 2 - Warning # 3 - Info (Default) # 4 - Verbose # 5 - Debug #LogFile = C:\temp\pkiproxy.log #LogDetail = 5
Signing Files
General Information
The PKI Proxy PKCS#11 driver is a standard PKCS#11 driver. Configuring a third-party application usually means providing a path to the PKI Proxy PKCS#11 driver DLL that matches the platform the application has been compiled for. Some applications may also require parameters, such as the slot number or some form of certificate identifier.
Signing with Jarsigner
Before following these steps, ensure that PKI Proxy has already been configured to share a certificate and that the local PKI Proxy PKCS#11 driver has been configured to use it. See Running PKI Proxy for details about configuring PKI Proxy and the PKCS#11 driver.
Using jarsigner with PKI Proxy is no different than using it with any other PKCS#11 driver. The syntax is as follows:
jarsigner -tsa http://timestamp.digicert.com -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg jarsigner.config -storepass fakepass -sigalg SHA256withRSA MyApp.jar "My Certificate"
The -tsa parameter tells jarsigner to use timestamp.digicert.com to timestamp the created signature. A timestamp provides a trusted third-party certification of the signature's creation time.
The -keystore, -storetype, and -providerClass parameters together tell jarsigner to use the PKCS#11 mechanism for signing.
The -providerArg parameter should point to a configuration file that provides the settings for the Sun PKCS#11 provider. Note that it is not the PKI Proxy driver configuration file; it is a separate file that must be created to direct jarsigner to the PKI Proxy PKCS#11 driver. See the following jarsigner.config example (on Windows, note that the paths must use double backslashes, as shown):
name = PKIProxy library = "C:\\Program Files\\PKI Proxy\\pkcs11\\win64\\pkiproxy_pkcs11.dll" description = PKI Proxy PKCS#11 driver slot = 0
The -sigalg parameter specifies the signature algorithm to use
The library setting should point to the 64-bit PKI Proxy PKCS#11 driver. The slot should always be 0 for the current version of PKI Proxy.
MyApp.jar specifies the jar file to sign.
"My Certificate" is the label or alias of the certificate that needs to be used for signing. The exact format of the label and its contents is specific to a particular security device. In some cases, it matches the common name of the certificate subject; in others, it is a general tag such as "Default Signing ID". You can use the keytool utility included with the JRE to find the label of your signing certificate. Use the same configuration parameters that you pass to jarsigner:
keytool -list -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg jarsigner.config -storepass fakepass
Provided that the PKI Proxy driver is configured properly and is referenced correctly in jarsigner.config, you should get the following output from the keytool call:
Keystore type: PKCS11 Keystore provider: SunPKCS11-PKIProxy Your keystore contains 1 entry Demo Certificate R3 | Demo Certificate R3, PrivateKeyEntry, Certificate fingerprint (SHA-256): AD:4E:D1:E0:39:C7:94:5E:48:A1:D3:60:17:A0:64:5F:E6:88:B5:E9:84:87:A5:98:25:DE:24:21:83:E9:53:A5
The Demo Certificate R3 | Demo Certificate R3 in the previous output is the label that you need to pass to jarsigner:
jarsigner -verbose -tsa http://timestamp.digicert.com -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg jarsigner.config -storepass fakepass -sigalg SHA256withRSA MyApp.jar 'Demo Certificate R3 | Demo Certificate R3'
Adding the -verbose parameter will make the previous call output the following:
requesting a signature timestamp TSA location: http://timestamp.digicert.com updating: META-INF/MYAPP.SF updating: META-INF/MYAPP.RSA signing: manifest.mf signing: myapp/MyAppFirstClass.class signing: myapp/MyAppSecondClass.class ... >>> Signer X.509, CN=SecureBlackbox Demo Certificate R3, O="/n software, Inc.", EMAILADDRESS=sales@nsoftware.com, L=Chapel Hill, ST=NC, C=US [trusted certificate] >>> TSA X.509, CN=DigiCert Timestamp 2022 - 2, O=DigiCert, C=US [certificate is valid from 21/09/2022, 01:00 to 21/11/2033, 23:59] X.509, CN=DigiCert Trusted G4 RSA4096 SHA256 TimeStamping CA, O="DigiCert, Inc.", C=US [certificate is valid from 23/03/2022, 00:00 to 22/03/2037, 23:59] X.509, CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US [certificate is valid from 01/08/2022, 01:00 to 09/11/2031, 23:59] jar signed.
Call jarsigner with the -verify parameter to check the integrity of the created signature, as follows:
jarsigner -verify MyApp.jar -verbose
The output will be as follows:
s 1341616 Wed Dec 14 13:58:36 GMT 2022 META-INF/MANIFEST.MF 1340173 Wed Dec 14 14:38:40 GMT 2022 META-INF/MYAPP.SF 7629 Wed Dec 14 14:38:40 GMT 2022 META-INF/MYAPP.RSA sm 5690 Thu Dec 01 12:51:34 GMT 2022 manifest.mf sm 2249 Thu Dec 01 12:51:34 GMT 2022 myapp/MyAppFirstClass.class ... s = signature was verified m = entry is listed in manifest k = at least one certificate was found in keystore - Signed by "CN=Demo Certificate R3, O="/n software, Inc.", EMAILADDRESS=sales@nsoftware.com, L=Chapel Hill, ST=NC, C=US" Digest algorithm: SHA-256 Signature algorithm: SHA256withRSA, 2048-bit key Timestamped by "CN=DigiCert Timestamp 2022 - 2, O=DigiCert, C=US" on Wed Dec 14 14:38:48 UTC 2022 Timestamp digest algorithm: SHA-256 Timestamp signature algorithm: SHA256withRSA, 4096-bit key jar verified.
Signing with Authenticode
Before following these steps, ensure that PKI Proxy has already been configured to share a certificate and that the local PKI Proxy PKCS#11 driver has been configured to use it. See Running PKI Proxy for details about configuring PKI Proxy and the PKCS#11 driver.
Microsoft uses a proprietary Authenticode format for signing executable files.
For ease of use, PKI Proxy includes a utility called pkpsigntool, which is capable of creating Authenticode signatures and also includes support for PKCS#11 drivers. The Microsoft SignTool utility does not include direct support for PKCS#11 drivers. Please see the Microsoft SignTool page for details about using SignTool.
Use the following syntax with the included pkpsigntool utility to sign an executable with a certificate shared by PKI Proxy:
pkpsigntool sign /d "PKI Proxy Signature" /fd sha256 /f "C:\Program Files\PKI Proxy\pkcs11\win64\pkiproxy_pkcs11.dll" /tr http://timestamp.server.com /td sha256 /ac ca.pem /ac root.pem App.exe
The /d parameter specifies the short description string that is embedded into the signature.
The optional /duparameter may be used to provide a link to a web page providing a longer description.
The /fd parameter specifies the digest algorithm to use for signing. For instance sha256.
The /f parameter provides a path to the PKCS#11 driver to use for signing. Specify the path to the 64-bit PKI Proxy PKCS#11 driver here.
The /tr parameter specifies the timestamp server to use when timestamping the created signature. A timestamp provides a trusted third-party certification of the signature creation time. Authenticode supports two forms of timestamps. Use the /t flag to specify a so-called 'legacy' timestamping service, or /tr to specify an RFC 3161-compatible timestamping service. Because most modern environments use RFC 3161-compatible services, it is safe to assume the use of the /tr flag.
The /td parameter specifies the digest algorithm to use for timestamping (e.g., sha256).
The /ac parameter allows passing any additional certificates that may make sense in the signature. Typically, this flag is used to pass the certificates that make up the signing certificate chain.
The /n parameter allows selecting a certificate by its name. This is useful when multiple certificates are available. This may be set to the alias value as defined in PKI Proxy, or the common name of the certificate. For instance, if the subject includes CN=My Certificate, this may be set to the value My Certificate. This parameter is optional.
The /i parameter allows selecting a certificate by its issuer's name. This is useful when multiple certificates are available. This may be set to the common name of the certificate's issuer. For instance, if the issuer certificate's subject includes CN=DigiCert EV Code Signing CA, this may be set to the value DigiCert EV Code Signing CA. This parameter is optional.
The /sha1 parameter allows selecting a certificate by its SHA-1 hash value (as a hex-encoded string). This is useful when multiple certificates are available. This is commonly referred to as the thumbprint when viewing the certificate details within Windows, such as d81a01d4f47797faab50400e85817dc974f4b3f3. This parameter is optional.
The /u parameter optionally specifies the Enhanced Key Usage (EKU) OID that must be present in the signing certificate. The value must be an OID. For instance, the code-signing key usage OID is 1.3.6.1.5.5.7.3.3. This parameter is optional.
The /p parameter specifies a PIN, if required. If the driver is configured to require a PIN from connecting applications, the PIN can be specified by setting this parameter (e.g., /p 12345).
Provided that the PKI Proxy driver is configured properly, you should get the following output from the above pkpsigntool call:
Opening PKCS#11 storage... Storage opened, looking for a nonempty slot... Token found in slot #0 (AKS ifdh 0) Logged in, looking for the certificate Requesting an RFC 3161 timestamp from http://timestamp.server.com Timestamp received and embedded into the signature SUCCESS: App.exe All files have been processed successfully
You can verify that the signature was added successfully by right-clicking on the signed executable in Windows Explorer, selecting Properties from the pop-up menu, and checking the Digital Signatures tab on the dialog that appears.
Signing with Adobe
Before following these steps, ensure that PKI Proxy has already been configured to share a certificate and that the local PKI Proxy PKCS#11 driver has been configured to use it. See Running PKI Proxy for details about configuring PKI Proxy and the PKCS#11 driver.
PKI Proxy can be used to sign PDFs from Adobe Acrobat or Reader. Please use the following steps to make the remote certificate available for signing in Adobe Acrobat or Reader.
Adobe PKCS#11 Configuration
Adobe products can use third-party PKCS#11 drivers only when working in nonprotected mode. To start the Adobe application in nonprotected mode, navigate to Edit -> Preferences -> Security (Enhanced), and uncheck the Enable Protected Mode at startup box at the top, and then restart the application.
After restarting the Adobe application, navigate to Edit -> Preferences -> Signatures, and click the More... button opposite the "Identities and Trusted Certificates" section. In the dialog that appears, click on the PKCS#11 Modules and Tokens item in the tree on the left, and click on the Attach Module button at the top. Navigate to the PKI Proxy driver location (normally C:\Program Files\PKI Proxy\pkcs11\win32). Make sure to select the win32 version of the driver to match the architecture of the Acrobat executable.
After selecting PKI Proxy's win32 PKCS#11 driver, the virtual device should be added to the list under the PKCS#11 Modules and Tokens branch. The titles of the elements may differ and depend on the type of the certificate being shared. For instance:

Click on the middle entry (PKI Proxy Certificate Adapter- in the previous example), and then on the Login button at the top. If the driver configuration file (pkiproxy_pkcs11.conf) enables PIN protection for the driver, please provide the PIN when asked. If PIN protection is not enabled any value may be used. Your certificate is protected by the real credentials that you specify in the driver configuration file.
Next select the last entry in the list (PKI Proxy Certificate Adapter 0 in our example), after which you should see the certificate in the panel on the right. Click on the certificate entry, and then click the Usage Options button at the top and check the Use for Signing item (make sure a check appears next to the item).
Close all currently open dialogs to complete the setup process. Documents can now be signed.
PDF Signing
To sign a PDF document, open the document and navigate to the signing facility of your PDF application. In Adobe Reader, you can access this functionality by clicking the More Tools button on the panel on the right (at the very bottom), and then selecting the Certificates applet in the list. Doing so adds a Certificates panel at the top of the document view.
On the Certificates panel, click on the Digitally Sign button:

Draw the signature square with your mouse when asked. Select the shared certificate in the list that appears. It should have the PKCS#11 device marker in brackets to the left of its subject string. Click Continue.
Click Sign. When asked, specify the location where to save the signed document.
Signing with JavaScript (In Browser)
Before following these steps, ensure that PKI Proxy has already been configured to share a certificate and that the local PKI Proxy PKCS#11 driver has been configured to use it. See Running PKI Proxy for details about configuring PKI Proxy and the PKCS#11 driver.
PKI Proxy includes a Javascript module that can be used to access the Web API from Javascript code running within a web page. The module provides a collection of easy-to-use classes that encapsulate certificate browsing and signing functionality.
The Javascript module sends data to PKI Proxy for signing and returns the signature. PKI Proxy may run either locally on 127.0.0.1 or elsewhere on the Internet.
The following code snippet shows how to sign data in the browser with PKI Proxy:
// Provide user credentials keystore.setUserId(userId); keystore.setUserKeySecret(userSecret); // Open the shared key store await keystore.open('https://sharedkeys.mycompany.com/', 'open', ''); // Select the signing key await keystore.select('id=' + keyid, true, false, 0); // Prepare the input var buf = (new TextEncoder()).encode('Hello, world!'); // Specify the signing key crypto.setCryptoKey(keystore.getKeys().item(0)); // Specify the security mechanism to use crypto.setMechanism('sha256WithRSAEncryption'); // Sign the data. var res = await crypto.sign(buf, true);This snippet matches the following OpenSSL command, which uses a local private key:
$> openssl dgst -sign privkey.pem -keyform PEM -sha256 -out signature.bin data.txtThe signature produced by this code snippet can then be validated with the inverse OpenSSL command:
$> openssl dgst -verify pubkey.pem -keyform PEM -sha256 -signature signature.bin -binary data.txt
Please refer to the Javascript demo application in the demos\js directory of the installation for more information.
Signing with SecureBlackbox
Before following these steps, ensure that PKI Proxy has already been configured to share a certificate and that the local PKI Proxy PKCS#11 driver has been configured to use it. See Running PKI Proxy for details about configuring PKI Proxy and the PKCS#11 driver.
SecureBlackbox can use the PKI Proxy PKCS#11 driver to access remote certificates as if they were local. Just provide the path to the configured PKI Proxy driver where you would normally provide a path to a regular PKCS#11 driver.
The following code snippet illustrates the use of the PKI Proxy driver with SecureBlackbox:
Certificatestorage storage = new Certificatestorage(); // Opening the storage storage.Open("pkcs11://user:password@localhost/C:/Program%20Files/PKI%20Proxy/pkcs11/win32/pkiproxy_pkcs11.dll?readonly=true"); // Listing the certificates Certificate cert = null; for (int i = 0; i < storage.Certificates.Count; i++) { Console.WriteLine("Certificate " + (i + 1).ToString() + ": " + storage.Certificates[i].SubjectRDN); // Using the first certificate with a private key to do the signing if ((cert == null) && (storage.Certificates[i].PrivateKeyExists)) { cert = storage.Certificates[i]; Console.WriteLine("(using the above certificate for signing)"); } } // Signing an XML document if (cert != null) { Xadessigner signer = new Xadessigner(); signer.SigningCertificate = cert; signer.InputFile = "unsigned.xml"; signer.OutputFile = "signed.xml"; signer.IgnoreChainValidationErrors = true; signer.Sign(); Console.WriteLine("Signing succeeded\r\n"); signer.Dispose(); } else { Console.WriteLine("No suitable signing certificates found"); } // Closing the storage storage.Close(false); storage.Dispose();
Microsoft SignTool
Before following these steps, ensure that PKI Proxy has already been configured to share a certificate and that the local PKI Proxy PKCS#11 driver has been configured to use it. See Running PKI Proxy for details about configuring PKI Proxy and the PKCS#11 driver.
It is recommended to use the included pkpsigntool utility to simplify the authenticode signing process whenever possible. The following steps using the Microsoft SignTool utility should be used only if there is a specific reason to do so. Please see the Signing with Authenticode section for details on using pkpsigntool.
The Microsoft SignTool utility does not include direct support for PKCS#11 drivers. While signtool can be used with PKCS#11 drivers such as PKI Proxy, it requires several additional steps and requires the use of a separate PKCS#11 tool that is not part of PKI Proxy.
If pkpsigntool cannot be used and SignTool must be used, the first step is to generate the digest with signtool by using the /dg option. In the following example, the nsoftware.cer file is the public x509 certificate. The private key of the code signing certificate must correspond to this public certificate.
signtool.exe sign /dg c:\temp\sign /fd SHA256 /f c:\temp\sign\nsoftware.cer c:\temp\sign\test.exe
The output of the above command is a Base64-encoded digest. The digest must be formatted properly to be used. The value must first be Base64 decoded. For instance, using the Base64 utility from Cygwin:
Base64 -d c:\temp\sign\test.exe.dig > c:\temp\sign\test.exe.dig.bin
Next the decoded SHA-256 digest must be modified to include a prefix to indicate the hash algorithm that was used to calculate it. The prefixes are defined by PKCS#11. One way to accomplish this is to first prepare a "prefix" file that then can be concatenated with the digest file from the above command. To do this, create a file with the hex contents 3031300d060960864801650304020105000420.
Note: The file contents must be the bytes corresponding to the hex characters. Copying the hex string into a file will not result in the correct contents.
Once the SHA-256 prefix file has been created, it can be concatenated with the digest. For instance, using the cat cat command from Cygwin.
cat c:\temp\sign\sha256prefix.bin c:\temp\sign\test.exe.dig.bin > c:\temp\sign\test.exe.fmtdig.bin
The digest should now be properly prepared; however, a separate tool must be used to perform the signing. PKCS#11 tools may be obtained from the device manufacturer, or other tools like pkcs11-tool from OpenSC may be used. The PKCS#11 tool you choose must first be configured to use the PKI Proxy PKCS#11 driver. Consult the documentation for your tool provider for instructions on how to configure a PKCS#11 module (.dll).
Once the pkcs11 tool has been configured, it can be used to sign the digest. As an example, when using pkcs-tool from OpenSC the --list-objects operation may be used to determine the Id of the certificate that will be used. For instance:
pkcs11-tool --list-objects Using slot 0 with a present token (0x0) Public Key Object; RSA 2048 bits label: SIGN pubkey ID: 02 Usage: encrypt, verify, wrap Access: none Certificate Object; type = X.509 cert label: Certificate for Digital Signature subject: DN: C=US/postalCode=27517, ST=NC, L=Chapel Hill/street=101 europa dr ste 110, O=/N SOFTWARE INC., CN=/N SOFTWARE INC. ID: 02
In this case, the Id is 02.
To then sign the digest with pkcs11-tool, the following command can be used. The RSA-PKCS mechanism should be used, not the SHA256-RSA-PKCS mechanism. The latter will also attempt to calculate a hash, which has been done in previous steps using the /dg option.
pkcs11-tool --sign --id 02 -l --pin 123456 --mechanism RSA-PKCS -i c:\temp\sign\test.exe.fmtdig.bin -o c:\temp\sign\test.exe.dig.bin.signed Using slot 0 with a present token (0x0) Using signature algorithm RSA-PKCS
The output of the previous command is a binary file and must be Base64 encoded for signtool to use it. The Base64 tool from Cygwin can be used to accomplish this. For instance:
Base64 c:\temp\sign\test.exe.dig.bin.signed > c:\temp\sign\test.exe.dig.signed
To import the signed digest and complete the signing process with signtool the following command may be used:
signtool.exe sign /di "C:\temp\sign" C:\temp\sign\test.exe
If successful, an output message such as Successfully signed: C:\temp\sign\test.exe should be visible.
If timestamping is desired, the /tr option of the signtool utility may be used.
Advanced
PKI Proxy can be accessed by any tool or library that supports PKCS#11 operations. The included PKI Proxy PKCS#11 driver can be used like any other PKCS#11 driver.
In addition, the Web API may be used directly to perform common operations, such as signing without the need for PKCS#11 support. Requests are made using simple GET and POST requests. Responses are formatted as JSON, where applicable, or as signed binary data in the case of signing.
PKI Proxy Web API
PKI Proxy exposes a simple Web API to route signature information between the client systems and the shared certificate hosts. The PKI Proxy PKCS#11 driver communicates with the Web API to discover certificates and make signing requests.
The Web API publishes two primary endpoints:
Objects Endpoint
The /objects endpoint provides access to the virtual collection of objects available in the key store. The key store contains a set of certificates shared by the PKI Proxy application on the server system and the cryptographic keys associated with them.
A key store may publish objects of three types: certificates, public keys, and private keys. Each object is associated with a set of properties, such as its unique Id, type, human-friendly label, and its cryptographic capabilities.
Note: The PKI Proxy key store never exposes sensitive or private parameters. Even though there are private key objects, the parameters returned for such keys by PKI Proxy are metadata (their labels, cryptographic types, and supported operations).
Following is an example request and response to the /objects endpoint.
Request: GET /objects HTTP/1.1 Response: { "objects" : [ { "id" : "crtsig", "class" : "certificate", "label" : "Demo Signing Certificate", "value" : "30820303... D0EE", "subject" : "/CN=Demo Signing Cert/C=US", "issuer" : "/CN=Demo Root/C=US", "group" : "g_crtsig", "size" : 2122, "ops" : { "encrypt" : false, "decrypt" : false, "sign" : true, "verify" : false } }, { "id" : "crtsigpubkey", "class" : "publickey", "label" : "Demo Signing Certificate Public Key", "value" : "3082010A...0001", "mech" : "RSA", "group" : "g_crtsig", "size" : 1144, "ops" : { "encrypt" : true, "decrypt" : false, "sign" : false, "verify" : true } }, { "id" : "crtsigprivkey", "class" : "privatekey", "label" : "Demo Signing Certificate Private Key", "mech" : "RSA", "group" : "g_crtsig", "size" : 1345, "ops" : { "encrypt" : true, "decrypt" : true, "sign" : true, "verify" : true } } ] }
Sign Endpoint
The /sign endpoint conducts the signing operation with a specified key.
A client can request a signature by posting the hash of the data to be signed to the /sign endpoint, specifying the unique key identifier and the desired signature algorithm as query string parameters. After verifying the credentials, PKI Proxy passes the parameters to the actual signing engine (such as a connected hardware security module). The completed signature is passed back to the client in the POST response:
Request: POST /sign?key=crtsigprivkey&mech=sha256WithRSAEncryption HTTP/1.1 [data] Response: [signed-data]
Encrypt Endpoint
The /encrypt endpoint conducts the encryption operation with a specified key.
A client can request the service to encrypt data by posting it to the /encrypt endpoint, specifying the unique key identifier as a query string parameter. PKI Proxy ensures that the client credentials are correct and passes the parameters to the cryptographic engine. The encrypted data is then passed back to the client in the POST response:
Request: POST /encrypt?key=crtencpubkey HTTP/1.1 [data] Response: [encrypted-data]
Decrypt Endpoint
The /decrypt endpoint decrypts encrypted data with a specified key.
A client can post encrypted data to the /decrypt endpoint, specifying the unique key identifier in the query string, to have the service decrypt it. Just like the other two endpoints (i.e., /sign and /encrypt), /decrypt is protected with client credentials. If the decryption succeeds, PKI Proxy returns the decrypted data in its POST response:
Request: POST /decrypt?key=crtencprivkey HTTP/1.1 [data] Response: [decrypted-data]
The protocol uses industry-standard security technologies to guarantee confidentiality, integrity, and authenticity of the data. All HTTP requests and responses use encrypted Transport Layer Security (TLS) 1.2/1.3 with mandatory server authentication, and each request is signed with a pair of preshared credentials (KeyID and AccessKey) that provide client authentication.
Read more about the security mechanisms used by PKI Proxy in Security.