2
votes

I encountered a bit peculiar behavior when trying to automate compilation and signing of particular NSIS-based binary. Namely, makensis is run under wine to compile the executable, and afterwards the osslsigncode is used to sign the binary.

Executable seems to be built fine, as it works on Windows systems, however there's an issue (in the lack of better word) with the signing. As the code signing certificate is in PKCS#12 format, the command used is as suggested here:

osslsigncode sign -pkcs12 <pkcs12-file> -pass <pkcs12-password> \ -n "Your Application" -i http://www.yourwebsite.com/ \ -in yourapp.exe -out yourapp-signed.exe

I get "Succeeded" message from osslsigncode, as if the signing went OK, however when the binary is run on Windows (Win 7 in this case), UAC says:

Publisher: Unknown

The strange thing is that when I opened the extracted cert from original .p12 file, to view it's info, Windows was afterwards able to recognize the publisher and the digital signature, as if it somehow became aware of the certification path...?

Any advice would be appreciated.

EDIT 1
osslsigncode versions used: 1.5.2 and 1.7.1

EDIT 2
For the sake of comparison, I tried signing with SignTool, and apparently it works without any problem. So this looks like cert + osslsigncode issue, but I can't tell what is it exactly.

I also tried osslsigncode on the exact same EXE with another cert, and to make matters more interesting, it worked... (I noticed certification paths differ for the 2 certs).

Some cert details:

1) non-working cert
version: V3
public key: RSA 2048 bits
signature hash algorithm: sha1
signature algorithm: sha1RSA
certification path: USERTrust -> Comodo Code Signing CA 2 -> NonWorkingCert

2) working cert
version: V3
public key: RSA 2048 bits
signature hash algorithm: sha1
signature algorithm: sha1RSA
certification path: USERTrust -> UTN-UserFirst-Object -> Comodo Code Signing CA 2 -> WorkingCert

1
Strange. I'm having this same issue years later. Did you ever find an answer?Mikey A. Leonetti

1 Answers

4
votes

This cost me several hours of head-scratching, but I think I understand now.

  • Windows has its internal database of trusted certificates. These include root certificates (installed & updated by Windows) and additional intermediate CA certs which it has seen at various times (signed by a root cert or some other trusted cert).
  • When Windows/UAC checks an executable signature at launch, it looks in the local database for a trusted certificate which has signed the root of the certificates embedded in the executable signature.
  • If Windows can't find a trusted signing certificate (maybe because the embedded cert is signed with an intermediate cert, not a root cert, and the intermediate cert is not in the local database), it leads to Unknown Publisher.
  • If you view the "Digital Signatures" tab of the executable Properties, Windows goes one step further and tries automatically to download and install any valid intermediate certs which are trusted by one of its local certs. Once this intermediate cert has been added to Windows' local certificate storage, the signature check at executable launch will also start passing (ie correct Publisher is shown). (This MSDN answer explains the logic, although the root cause they describe - root cert not yet updated - is different.)

The solution is to pass the intermediate cert to osslsigncode along with the main cert. (H/T to Tor Project for confirming this.)

  • Find the correct intermediate CA cert. Can be done via openssl x509 -text -in cert.pem and then look for "Authority Information Access -> "CA Issuers" URI. Certificate identifiers (serial numbers, etc) can also be found in Windows under the "Digital Certificates" tab -> "View Certificate" -> "Certification Path".

    (Tip: Don't always trust the CA's support pages to have correct info for which intermediate cert to download, I wasted a lot of time after downloading the wrong intermediate certs from a CA's web page.)

  • Convert all certs to PEM format if necessary with openssl x509 -in my_intermediate_ca.crt -inform der -outform pem -out my_intermediate_ca.pem or similar.
  • Put the full CA chain into one PEM file, with the code signing cert first: cat mycert.pem my_intermediate_ca.pem > certchain.pem

    (If code signing cert is not first in the chain, Windows sees an invalid signature which is "signed" by the intermediate cert.)

  • Run osslsigncode -certs certchain.pem ...

    (Note: I also passed -h sha256 & -ts http://timestamp.digicert.com although I think everything will work with other combinations of options, also.)