-
Notifications
You must be signed in to change notification settings - Fork 0
Signing Messages
- ✅ 2.1 | ✅ 2.0 | ⛔ 1.9 | ...
- Use a Trusted Certificate (
digital-certificate.txt) and a private key (private-key.pem) to achieve silent printing*.
| Component | Format | Description |
|---|---|---|
private-key.pem |
PKCS#8 |
🔑 Private key used for signing |
private-key.pfx |
PKCS#12 |
🔑 Optionally replaces .pem file for .NET environments |
digital-certificate.txt |
x509 |
🔒 Trusted certificate* |
- A language capable of reading an RSA private key and generating an SHA1 base64 encoded signature hash.
- Signing examples are available here:
assets/signing
- Certificate
- Signature
- [Signing Script]((#server-side-signing-method)
- Troubleshooting
-
Generate a Trusted Certificate (
digital-certificate.txt). -
Edit
qz.security.setCertificatePromise()to use your Trusted Certificate. -
Edit
qz.security.setSignaturePromise()to use your server-side signing method. -
Edit
sign-message.phpto sign print requests with your private key.
Examples in other languages can be find indemo/assets/signingof QZ Tray.
A sample certificate chain is provided with the demo, labeled as "localhost". This will display a trusted message on load of the page.
-
Edit the
setCertificatePromise()provided in thesample.htmlfile. -
Replace the "localhost" certificate chain with your Trusted Certificate by changing the
$.ajax(...)line to match the address of the certificate.The Trusted Certificate generated by QZ Industries, LLC is
digital-certificate.txtqz.security.setCertificatePromise(function(resolve, reject) { $.ajax({ url: "path/to/digital-certificate.txt", cache: false, dataType: "text" }).then(resolve, reject); });
Note:
$.ajaxis a jQuery function and can be replaced with any ajax library of choice (xhr,PageMethods, etc).
The function setSignaturePromise() is used for proving a JavaScript callback method for signing each privileged method to prevent anonymous printing. This is a security measure to ensure the identity of websites can be verified by the software.
These methods are invoked on any privileged function, which includes finding attached devices, printing, or sending/reading data from a USB or serial device.
Change the $.ajax(...) line to match the address of your php file.
qz.security.setSignaturePromise(function(toSign) {
return function(resolve, reject) {
$.ajax("assets/signing/sign-message.php?request=" + toSign).then(resolve, reject);
};
});qz.security.setSignaturePromise(function(toSign) {
return function(resolve, reject) {
$.post("assets/signing/sign-message.php", {request: toSign}).then(resolve, reject);
};
});.NET conveniently exposes a promise-friendly PageMethods object which is capable of calling a server-side .NET function by name directly from JavaScript. This assumes a server-side signing example has already been setup in C#, VB.NET, etc.
qz.security.setSignaturePromise(function (toSign) {
return function (resolve, reject) {
PageMethods.SignMessage(toSign, resolve, reject);
};
});A server-side signing method must be used in combination with the AJAX call. This signing will happen with your company's private key.
- This private key MUST be 2048-bit
- If generated by QZ Industries, LLC the file name will be
private-key.pem
Trusted websites with a valid public key chain pair and a properly configured qz.security.setSignaturePromise AJAX function will unlock QZ Tray's ability to communicate silently (print, read serial ports, usb devices, etc). Non-signed requests (Untrusted websites) will continue to show a warning dialog.
In this example we go over how to accomplish this in php by editing the sign-message.php file that is provided with the software (demo/assets/signing/sign-message.php). Examples in other languages including: Ruby, Python, JavaScript, C#, J#, Java, ASP and VB can be found here.
-
Change the line
$KEY = 'private-key.pem';to match the name of your private key -
Edit the line:
$req = $_GET['request'];appropriately to edit the method you are using in the AJAX call (GETorPOST)<?php // ######################################################### // # PHP Signing # // ######################################################### // Sample key. Replace with one used for CSR generation $KEY = 'private-key.pem'; $req = $_GET['request']; //GET method //$req = $_POST['request']; //POST method $privateKey = openssl_get_privatekey(file_get_contents($KEY)); $signature = null; openssl_sign($req, $signature, $privateKey); if ($signature) { header("Content-type: text/plain"); echo base64_encode($signature); exit(0); } echo '<h1>Error signing message</h1>'; exit(1); ?>
-
If these changes have been done correctly, you will be able to suppress this dialog box:

This will no longer come from an untrusted source.

The new certificate should look similar to this (trusted, valid, fingerprint, and contains your information):

-
If the browser console says
Invalid JSON, try changing your HTTP headers in the sign-message example to usetext/plaininstead ofapplication/json. In PHP, this is done via:- header('Content-Type: application/json'); + header('Content-Type: text/plain');
Note: This technique will vary depending on the server-side language being used.
The console error: key is too short for SigAlg: keylen=99,sha1 is a result of an incompatible private key with the JavaScript signing library, jsrsasign, used in client-side signing. The private-key.pem downloaded from our website needs to be converted using the below openssl command:
openssl rsa -in private-key.pem -out private-key-updated.pem
The console error: ReferenceError: RSAKey is not defined generally indicates that the jsrsasign-all-min.js URL has changed. We recommend that you download this file to prevent future updates causing issues.
To override the Trusted Root certificate:
-
Launch QZ Tray using manually specified certificate (since 1.9.7)
java -Xms512M -DtrustedRootCert=override.crt -jar qz-tray.jar
-
Or alternately via
qz-tray.properties(since 2.0.2)authcert.override=override.crt