Help setting up self-signed certificate to suppress prompts?

6,049 views
Skip to first unread message

Bernie

unread,
Jan 24, 2017, 9:56:22 PM1/24/17
to qz-print
Hi,

I've been looking at the following links to see how I could use a self-signed certificate to suppress the QZ Tray prompts with my PHP website, but I'm getting confused on what steps I need to take to do this.

http://stackoverflow.com/questions/40168017/suppress-localhost-wants-to-access-connected-printers-untrusted-website-when-a/40275815#40275815

https://qz.io/wiki/2.0-signing-messages

1. I see in v2.0.2, I have to add "authcert.override=override.crt" to the "qz-tray.properties" file, so I would have to do this to every local client of QZ Tray that I install?

2. I'm able to create a self-signed certificate through my Plesk panel that creates a "private key (*.key)" and a "certificate (*.crt)" files, but I'm not sure what exactly I need to do next?  Do I still have to follow the 4 steps in this https://qz.io/wiki/2.0-signing-messages link when using a self-signed certificate?

Thank you!

Tres Finocchiaro

unread,
Jan 24, 2017, 11:22:53 PM1/24/17
to Bernie, qz-print
so I would have to do this to every local client of QZ Tray that I install?

Correct, unless you compile yourself and bundle it in.   See the advanced section of the compiling tutorial for more information.  This was covered in the stackoverflow article you linked as well.

 I'm able to create a self-signed certificate through my Plesk panel that creates a "private key (*.key)" and a "certificate (*.crt)" files, but I'm not sure what exactly I need to do

I would recommend you download openssl and create these files manually.  The private key should be in PKCS#1 format, similar to that which ships with the product in <install dir>/assets/signing.

-Tres

--
You received this message because you are subscribed to the Google Groups "qz-print" group.
To unsubscribe from this group and stop receiving emails from it, send an email to qz-print+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Bernie

unread,
Jan 25, 2017, 12:11:30 AM1/25/17
to qz-print, olim...@gmail.com
Hi Tres,

Ok, I just have to install QZ Tray on one PC; so just to make it easier I'll just manually edit the "qz-tray.properties" file and add "authcert.override=override.crt" to it.

1. I have OpenSSL already installed on my server, what command would I need to enter in SSH to generate a private key in PKCS#1 format?

2. 
Once I've generated my own version of the "private-key.pem", what would the next step be to use this self-signed certificate with QZ Tray to suppress prompts?  Would I just copy/paste my version of the "private-key.pem" into the local PC copy of QZ Tray under the "C:/Program Files/QZ Tray/demo/assets/signing/" directory?

3. I see in the "sign-message.php" file, a section where a password has to be listed; would I need to list a password value here?  If so, where would I get this password value from?

Thank you, again!
To unsubscribe from this group and stop receiving emails from it, send an email to qz-print+u...@googlegroups.com.

Bernie

unread,
Jan 25, 2017, 11:16:17 PM1/25/17
to qz-print, olim...@gmail.com
Hi Tres,

1. With OpenSSL I will have to generate the private key (*.pem) in PKCS#1 and also a self-signed certificate (*.cer) in x509 format?

2. I've gone further through the documentation and I think I have a good understanding of how this should all work but can you confirm if I'm on the right track based on the steps below?

I'm following the code I see in "sample.html" for the following steps:

a. Once I have my *.pem and *.cer files created; then my developer would first have to call the following code from my website to load certificate (*.cer) , right?

qz.security.setCertificatePromise(function(resolve, reject) {
     
//Preferred method - from server
     $
.ajax("/var/www/vhosts/domain.com/httpdocs/qz/certificate.cer").then(resolve, reject);

b. Then the next step would be to use the following code, either GET or POST, to supply the signature?

qz.security.setSignaturePromise(function(toSign) {
         
return function(resolve, reject) {
         
//Preferred method - from server
         $
.ajax("/var/www/vhosts/domain.com/httpdocs/qz/sign-message.php?request=" + toSign).then(resolve, reject);

c.  Then in the "sign-message.php" file I have to list the private key name under $KEY; which I will have saved under the same directory as the "sign-message.php" file, and I won't need to include $PASS because the private key I generate won't be password protected?
 
/var/www/vhosts/domain.com/httpdocs/qz/private-key.pem

d. Then we would use "qz.websocket.connect" to connect the website/browser to the local PC copy of QZ Tray?

e. When the "localhost wants to connect to QZ" pop-up shows then click on the "Remember my decision" check box, and then I can use the "allowed.dat" file under the %appdata%\qz directory to copy to other PCs to avoid this pop-up from showing; right?

f. Finally, put "authcert.override=override.crt" inside the "C:\Program Files\QZ Tray\qz-tray.properties" file to prevent other pop-ups from showing?

Thank you for your help understanding how this whole process works!

Tres Finocchiaro

unread,
Jan 25, 2017, 11:18:47 PM1/25/17
to Bernie, qz-print
Yes, all steps correct, except F and E need to be swapped since you can't click "Always Allow" on an untrusted connnection

-Tres
To unsubscribe from this group and stop receiving emails from it, send an email to qz-print+unsubscribe@googlegroups.com.

Bernie

unread,
Jan 26, 2017, 12:18:38 AM1/26/17
to qz-print, olim...@gmail.com
Hi Tres,

Ok, great...thank you for confirming this! :)

1. Should I have "certificate.cer", "private-key.pem" and "sign-message.php" all under the same directory on my server?

2. Will extension *.cer work or should I change it to *.txt since this is how I see it shown on the QZ site?

3. I've been trying to do research in what I need to run in OpenSSL to create a private key (*.pem) in PKCS#1 and also a self-signed certificate (*.cer) in x509 format but I can't seem to get this working.  I tried using the following command and entered in all the certificate information but I don't think a PKCS#1 key was created.

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes

Is there something I'm missing in the above command?

Thank you, again!

Tres Finocchiaro

unread,
Jan 26, 2017, 12:28:46 AM1/26/17
to Bernie, qz-print
1. Best practices would place private-key.pem i an inaccessible directory (like any private key).  preferably out of your webroot entirely.
2. File extension generally doesn't matter.
3. I would add a subject to the cert, the rest looks right.
To unsubscribe from this group and stop receiving emails from it, send an email to qz-print+unsubscribe@googlegroups.com.

Bernie

unread,
Jan 26, 2017, 10:36:29 AM1/26/17
to qz-print, olim...@gmail.com
Hi Tres,

Ok, thank you!

In the "sample.html" demo file, I see you used this "alternate method 2 - direct" method for "setCertificatePromise". 

In this section, I see you list the "certificate" and "intermediate certificate"; is it necessary to include the "intermediate certificate"? 

The reason I ask is when I create my "private key" and "certificate" in OpenSSL, it doesn't include the "intermediate certificate" for me.

Thank you!

Tres Finocchiaro

unread,
Jan 26, 2017, 11:26:55 AM1/26/17
to Bernie, qz-print
In this section, I see you list the "certificate" and "intermediate certificate"; is it necessary to include the "intermediate certificate"?  

You're fine.  That wording is for premium clients.  If you're self-signed, there's no intermediate involved;  The ROOT is the only certificate.

-Tres
To unsubscribe from this group and stop receiving emails from it, send an email to qz-print+unsubscribe@googlegroups.com.

Bernie

unread,
Jan 26, 2017, 11:59:21 AM1/26/17
to qz-print, olim...@gmail.com
Ok, that makes sense...thank you!

1. I'm trying to better understand what "authcert.override={certificate_name}.crt" actually does?  Does this suppress the "localhost wants to connect to QZ..." pop-up or is it suppressing the "localhost wants to print/access..." pop-up messages?

2. When I add the above to my client "qz-tray.properties" file, do I also have to have my "{certificate_name}.crt" file saved in the "C:\Program Files\QZ Tray\" directory too?

3. In the "sample.html" page, I notice for the
"localhost wants to print/access..." pop-up messages, when I click on "Remember my decision" the "Allowed" button gets greyed out; is this happening because in the "sample.html" file you use the "alternate method - unsigned" method for "setSignaturePromise"?

Thank you, again!

Tres Finocchiaro

unread,
Jan 26, 2017, 12:05:38 PM1/26/17
to Bernie, qz-print
1. I'm trying to better understand what "authcert.override={certificate_name}.crt" actually does?  Does this suppress the "localhost wants to connect to QZ..." pop-up or is it suppressing the "localhost wants to print/access..." pop-up messages?

It doesn't suppress anything.  It simply allows you to break our certificate chain and roll out your own.  By default, QZ Tray ships with the following chain of trust:

QZ Industries, LLC ROOT 100 YEAR
    - QZ Industries, LLC CA 20 YEAR
      - Certificate sold via buy.qz.io

The software trusts ROOT, therefore it trusts everything that stems from it.  This is basic PKI and we just take advantage of it.  It's the same way that SSL certs work as well as many others.
 
2. When I add the above to my client "qz-tray.properties" file, do I also have to have my "{certificate_name}.crt" file saved in the "C:\Program Files\QZ Tray\" directory too?

Yes, or wherever the param points to.
 

3. In the "sample.html" page, I notice for the "localhost wants to print/access..." pop-up messages, when I click on "Remember my decision" the "Allowed" button gets greyed out; is this happening because in the "sample.html" file you use the "alternate method - unsigned" method for "setSignaturePromise"?

No, this is because the configuration is incorrect.  A proper configuration will let you click that box. 
To unsubscribe from this group and stop receiving emails from it, send an email to qz-print+unsubscribe@googlegroups.com.

Tres Finocchiaro

unread,
Jan 26, 2017, 1:17:08 PM1/26/17
to Bernie, qz-print
is this happening because in the "sample.html" file you use the "alternate method - unsigned" method for "setSignaturePromise"?

Sorry, this is partially true, yes.  But both setSignaturePromise AND setCertificatePromise must be configured properly.

Bernie

unread,
Jan 26, 2017, 4:57:05 PM1/26/17
to qz-print, olim...@gmail.com
Hi Tres,

In theory, I can try testing out my self signed certificate and private key with the demo version; right?

This is what I tried doing, in the "sample.html" file for "setCertificatePromise" I used the same "alternate method 2 - direct" method and added my certificate there instead.  I think this part works properly because when I go to the "sample.html" page, I'm able to see my certificate show in the pop-up box and I can successfully connect; so that's good.

1. However, one thing I did notice is if I click on "Remember this decision" it greys out the "Allow" button; this didn't happen with the QZ certificate; so I'm not sure why this is happening with my certificate?

Next, in the "sample.html" file for "setSignaturePromise" I set the following up:

qz.security.setSignaturePromise(function(toSign) {
       
return function(resolve, reject) {
           
//Preferred method - from server

            $
.ajax("xampp/htdocs/qz_tray/demo/assets/signing/sign-message.php?request=" + toSign).then(resolve, reject);

           
//Alternate method - unsigned
           
//resolve();
       
};
   
});

Then in the "sign-message.php" I setup the following:

// Sample key.  Replace with one used for CSR generation
$KEY
= 'private-key.pem';

$req
= $_GET['request'];
$privateKey
= openssl_get_privatekey(file_get_contents($KEY));

I also added "authcert.override=certificate.crt" to the following to the "C:\xampp\htdocs\qz_tray\qz-tray.properties" file and it's showing this.  Also, my "certificate.crt" file is in this same "C:\xampp\htdocs\qz_tray\" directory.

wss.alias=qz-tray
wss
.keystore=C:\\Program Files\\QZ Tray\\auth\\qz-tray.jks
wss
.keypass=1ab0l2j9tc
wss
.storepass=1ab0l2j9tc
wss
.host=0.0.0.0
authcert
.override=certificate.crt

Applying the above changes, I'm able to connect with my certificate but when I try to use "Final All Printers" button nothing happens.

2. Am I missing anything above that is causing this not to work properly?

Thank you, again!

Tres Finocchiaro

unread,
Jan 26, 2017, 5:06:16 PM1/26/17
to olimits7, qz-print
I find it very unlikely that your certificate is correct but the option to remember is grayed out.

It is much more likely that you are receiving a second due to an invalid signature.  The Java logs should confirm.

In regards to your code the URL looks to be invalid at a glance.    Remember it is Javascript calling the Ajax request so the URL must be something one can navigate to directly.

Try to navigate to xampp/htdocs/qz_tray/demo/assets/signing/sign-message.php?request=foo

Bernie

unread,
Jan 26, 2017, 5:17:14 PM1/26/17
to qz-print, olim...@gmail.com
Ok, I'm able to navigate to the following:  http://localhost/qz_tray/demo/assets/signing/sign-message.php?request=foo and it shows the following on the page:  https://gyazo.com/9477c8b49f75937ab479d5e6d8f96d17

I see the following in the log:

2017-01-26 17:10:19,619 [INFO] Allowed OVH to connect to QZ
2017-01-26 17:10:22,969 [INFO] Connection closed: 1001 - null
2017-01-26 17:10:22,969 [INFO] Closing all communication channels for OVH
2017-01-26 17:10:23,860 [INFO] Connection opened from /0:0:0:0:0:0:0:1:49841 on socket port 8182
2017-01-26 17:10:23,917 [DEBUG] Message: {"certificate":"-----BEGIN CERTIFICATE----------END CERTIFICATE-----\n","promise":{},"timestamp":1485468623889,"uid":"x32t85"}
2017-01-26 17:10:23,932 [WARN] Problem verifying certificate with CRL

Bernie

unread,
Jan 26, 2017, 10:19:50 PM1/26/17
to qz-print, olim...@gmail.com
Hi Tres,

Ok, I finally got this working properly with my self-signed certificate / private key and everything seems to be working the way it should.  I no longer get any popups and I'm able to use the "Remember my decision" option now.

Thank you again for all your help figuring this all out! :)

Thank you!

jus...@boxc.com

unread,
Apr 10, 2017, 12:38:57 PM4/10/17
to qz-print, olim...@gmail.com
How did you end up resolving this?

quad...@gmail.com

unread,
Apr 20, 2017, 8:08:40 AM4/20/17
to qz-print, olim...@gmail.com, jus...@boxc.com
This discussion helped a lot, especially knowing that intermediate certificate is not required when you use your own self-signed ones.

So symmarizing everything in one place:

1) generate your private key and certificate by running command like this:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 3650 -nodes

You have either to install openssl for windows or cygwin or just use linux system.
Finally you'll have 2 files:
key.pem - which is private key
and cert.pem - which I guess is public certificate (you can rename it to cert.pem.crt and see its details by windows certificate viewer)

2) Either compile your own build
https://qz.io/wiki/compiling using your certificate cert.pem.crt
The final build command is
ant nsis -Dauthcert.use=ant/cert/cert.pem.crt (place your certificate in appropriate folder)

OR

run your existing installed QzTray using your certificate (using bat file)

javaw -DtrustedRootCert=D:\projects\cert.pem.crt -jar "d:\Install\Progs\Qz\qz-tray.jar"

3) Using qz demo samples - update setCertificatePromise
with something like this
$.ajax("http://domian.dev/qz/certificate.cer").then(resolve, reject);
or $.ajax("http://domian.dev/qz/certificate.cer.txt").then(resolve, reject);

and make sure the web url is accessible as direct link ( http://domian.dev/qz/certificate.cer.txt )

4) Update setSignaturePromise with

$.ajax(" http://domian.dev/qz/sign-message.php?request=" + toSign).then(resolve, reject);

In sign-message.php
use your private.key you've generated at step 1

$KEY = 'key.pem'; // for your security place the private key in non-accessible directory from web
$PASS = '';
$req = $_GET['request'];
$privateKey = openssl_get_privatekey(file_get_contents($KEY), $PASS);
//.........

That's it, if you configured everything properly , you'll be able to remember your allowed choice in popup window.

jus...@boxc.com

unread,
Apr 20, 2017, 9:52:16 AM4/20/17
to qz-print, olim...@gmail.com, jus...@boxc.com, quad...@gmail.com
I managed to figure it out the following day. Instead of compiling or running QZ Tray with a trusted cert override I configured the new "authcert.override" property in the "qz-tray.properties" file to point to the self-signed public cert on the file system. I also took the sha1 hash of the public cert and manually added it to the "allowed.dat" file by duplicating the existing row. The file is tab delimited so formatting is crucial. I did a hard restart (soft reload won't work) of QZ Tray and now I don't receive authorization prompts. All of the other aforementioned steps are accurate, though.
Message has been deleted

FLORENTIN Calvin

unread,
Dec 15, 2017, 9:26:30 AM12/15/17
to qz-print
Hello Bernie,

Can I contact you on your gmail adress ?
I have some questions for you,

Best regards

mande...@gmail.com

unread,
Jan 18, 2019, 11:27:36 PM1/18/19
to qz-print

Hi, I tried this getting no PopUP, but nothing printing. If i remove Cert.cer then getting pop up and able to print.

Tres Finocchiaro

unread,
Jan 21, 2019, 10:57:49 AM1/21/19
to mande...@gmail.com, qz-print
We don't offer (nor permit on this mailing list) assistance with bypassing the QZ Tray certificate.

That said, for issues with signing:
  • Please read https://qz.io/wiki/2.0-signing-messages carefully.
    • Test the signing controller by URL, make sure its' plain, base64 text coming back
  • Use the console logs to verify that the certificate and signature are coming through https://qz.io/wiki/faq#console-logs
  • If using a client-side signing technique (e.g. sign-message.js) make sure you only have  qz.security.setCertificatePromise()   and  qz.security.setSignaturePromise()   defined once and only once.  Sometimes people forget to comment-out the one bundled with sample.html when integrating with a separate JS file.
  • If you're making code changes to a JavaScript file, force refresh (CTRL + F5, etc) to make sure your changes are taking effect immediately.




Reply all
Reply to author
Forward
0 new messages