My signed executable is blocked in Internet Explorer even if it's signed with SHA2 - code-signing-certificate

I've created and signed a new executable file (the file is signed with double signature SHA1 and SHA256 and timestamped).
Since 1/1/2016 if I try to download it from Internet Explorer (or Microsoft Edge) I get an error (saying the signature is corrupted).
Smartscreen also tells that the file is not signed.
If I look at the file from the properties, it has the two signatures.
Can you help me out understanding what's the problem?
Here's the link for the download PhraseExpander setup file
Thanks.

This is what I wrote here:
valid certificate is corrupt with IE
I still doesn't have a solution, because I am not able to request a SHA-2 certificate. But you can't download any application from web with a SHA-1 certificate, anymore.

Class 3 certificates are a step above the Class 2. Class 2 does not require “Extended Validation”. However the “EV” code signing certificates combine all of the regular benefits of digitally-signed code with a rigorous extended validation process. They represent the gold standard for authentication and security in code signing certificates. EV code signing certificates adhere to strict validation standards from the CA/Browser Forum and to Microsoft specifications. Enhanced authentication is provided via an encrypted token containing the private key.

Related

Unable to sign VBA with valid Sectigo Code Signing certificate - but signing .msi works fine

I bumped into the same issue as this topic: Unable to sign VBA with valid Sectigo Code Signing certificate
Basically, I have a Sectigo EV code signing certificate with a USB-stick that I need to plug in in order to sign my code. I am using that for signing my excel add-in in Visual Studio (DLLs) and the .msi file that we build from that with signtool:
signtool sign /tr http://timestamp.comodoca.com /td sha256 /fd sha256 /d Prog2Installer.msi /a C:\Users\hello\source\repos\ME\Prog2\bin\Release\Prog2mInstaller.msi
That works fine, I get a pop-up asking me for my password and it signs ok.
But now I also want to use my certificate to sign my excel/VBA xlsm file. When I plug in my USB key I can select the certificate in VBE (named "Installed by Sectigo Browser extension"), but when I save the file, I get the same feedback as the referenced post:
There is a problem with the digital certificate. The VBA project could not be signed. The signature will be cancelled
I checked the certmgr, can see the certificate there, but can't export as .pfx, only as .cer (so no private keys, as they reside on the USB stick I assume). I also added those 3 timestamp items that were suggested in the referenced post, but still nothing.
Sectigo/Comodo seem to have no clue (tried their helpdesks), I hope that anyone here can advice me what to do to get this to work?
I had a response from Sectigo - who had contacted the certificate token manufacturer. It looks like this is indeed Microsoft's problem - requiring an MD5 hash when signing VBA code - even though that's no longer considered secure.
As a workaround, if you are using Safenet AND if your token still supports MD5, you can make the following registry changes:
Find the registry key "HKEY_LOCAL_MACHINE\SOFTWARE\SafeNet\Authentication\SAC"
Add a new registry key "Crypto"
Add a new string value to this key - "Disable-Crypto"
Give "Disable-Crypto" a value "None"
Then, add the signature to VBA in the usual way. In my case, when saving the file, it asks for the token password three times before completing the save.
Full details - inluding more information about the issue
Unless there is a change to the MD5 requirement for signing VBA code, it will not be possible to sign VBA code at all in the future (i.e. no certificate providers will support it). Therefore, I suggest that people contact Microsoft to urge them to act on this issue.
I had some phone conversations with their helpdesk. My summary of those conversations: it's Microsofts problem... I didn't file anything with MSFT but as I needed a working certificate, I went for the EV code signing for my DLL/Visual studio (works fine) and bought a simple code signing certificate to sign my VBA/Excel. After a bit of fiddling it simply works. So I pay 580 USD/year vs 400 USD/year but have a working solution.
So I'm a Schrodinger Sectigo customer now, being both happy & unhappy at the same time.

X.509 certificate difference between S/MIME and HTTPS (LetsEncrypt)

Looking at LetsEncrypt FAQ page, they have clearly stated that email encryption and code signing require a different type of certificate and therefore they are not supported by LetsEncrypt.
My understanding is that https and S/MIME both require X.509 certificates. What is the difference between certificates these two technologies require?
Among other things (like the encryption key), an X.509 certificate also specifies what it may be used for. X.509 certificates for HTTPS and S/MIME usage basically have different usages.
The structure of an X.509 certificate is fairly complex. Its possible usage depends on attributes and extensions within the certificate, and require that specific combinations of them with specific values must be present.
For example, an S/MIME certificate, requires a Key Usage attribute with something like Encrypt, Verify, Wrap, Derive, a Key Usage extension that must have the Critical attribute set to Yes and include a Usage attribute with Key Encipherment plus in the Extended Key Usage extension (sic!) it should list the Purpose attribute value Email Protection.
Note that Key Usage extension Data Encipherment is not required, because in S/MIME, the data contents are encrypted by a random symmetric key which then is encrypted with the private key from the certificate. This is called hybrid encryption and it is done for performance and scalability reasons.
The certificate requirements even extend into the certificate chain, meaning that the certificate must be signed by another certificate that has been issued to sign certificates for that usage.
Note that the above example may not be 100% correct, because the subject is so complex, and I don't fully understand every aspect of it myself. I found this quote which I think describes the situation fairly well:
I think a lot of purists would rather have PKI be useless to anyone in
any practical terms than to have it made simple enough to use, but
potentially "flawed". — Chris Zimman
Resources that helped me:
X.509 Style Guide by Peter Gutmann: an attempt to shed light on the relations of attributes and extensions and their interpretations
RFC 4262 - X.509 Certificate Extension for Secure/Multipurpose Internet Mail Extensions (S/MIME) Capabilities

Method to verify a signed archive's X.509 CoT

I am trying to understand the key high level details behind verifying trust when downloading an archive.
This is my understanding of how it could be done:
On the Software Developer side:
Obtain a certificate from a public CA like verisign
Generate a hash of your archive and then encrypt this string using the private key from your certificate, this is the "signature"
Host the archive for download, along with a separate file which contains the public key from your certificate + the signature generated in step 2.
On the (user) client side:
Download and unpack the archive, download the signature + public key file
Decrypt the downloaded signature using the downloaded public key, save this value
Iterate through the public root certificates embedded within your operating system. For each root certificate, decrypt the signature value and compare the result to the result in step 5.
Once a match is found in 6, you have verified that the author's private key descends from the chain of trust of the CA which you found matched in step 6.
This all assumes that the software developer used a CA for which we have an embedded root certificate in our clients OS.
Questions:
Is the above method sound, or am I overlooking key details?
Given a blank slate client that you control, if I wanted to combine the public key + signature + archive into a single file that I could make the client understand and parse, are there any widely supported formats to leverage for organizing this data?
Aside from being a little too specific on Developer (2) (that describes how RSA signatures work, but ECDSA is perfectly well suited to this task) that sounds rather like Authenticode minus some EKU restrictions. This leads me to ask "why not use Authenticode signing?".
The structure I'd consider is the PKCS#7/CMS SignedData format. It can describe multiple signatures from multiple certificates (sign it ECDSA-brainpoolP320t1-SHA-3-512 for anyone who can read it as well as RSA-2048-SHA-2-256 for most of us, and DSA-1024-SHA-1 for anyone whose computer was built in 2001).
For data file you can just use SignedData normally, for executables it's harder since there are semantic portions (so you have to squirrel it away somewhere and use indirect signing).
If you do your signing with .NET, PKCS#7/CMS SignedData is available for both signing and verifying via System.Security.Cryptography.Pkcs.SignedCms (though you probably have to define your own chain trust rules outside of that class).

How can you test that an SSL client library is properly verifying the certificate of the server to which it connects?

I want to ensure that client libraries (currently in Python, Ruby, PHP, Java, and .NET) are configured correctly and failing appropriately when SSL certificates are invalid. Shmatikov's paper, The Most Dangerous Code in the World:
Validating SSL Certificates in Non-Browser Software, reveals how confusing SSL validation is so I want to thoroughly test the possible failures.
Based on research a certificate is invalid if:
It is used before its activation date
It is used after its expiry date
It has been revoked
Certificate hostnames don't match the site hostname
Certificate chain does not contain a trusted certificate authority
Ideally, I think I would have one test case for each of the invalid cases. To that end I am currently testing an HTTP site accessed over HTTPS, which leads to a failure that I can verify in a test like so:
self.assertRaises(SSLHandshakeError, lambda: api.call_to_unmatched_hostname())
This is incomplete (only covering one case) and potentially wrong, so...
How can you test that non-browser software properly validates SSL certificates?
First off, you'll need a collection of SSL certificates, where each has just one thing wrong with it. You can generate these using the openssl command line tool. Of course, you can't sign them with a trusted root CA. You will need to use your own CA. To make this validate correctly, you'll need to install your CA certificate in the client libraries. You can do this in Java, for example, using the control panel.
Once you have the certificates, you can use the "openssl s_server" tool to serve an SSL socket using each one. I suggest you put one certificate on each port.
You now have to use the client library to connect to a port, and verify that you get the correct error message.
I know that Python by default does no certificate validation (look at the manual for httplib.HTTPSConnection). However, m2crypto does do validation. Java by default does do validation. I don't know about other languages.
Some other cases you could test:
1) Wildcard host names.
2) Certificate chaining. I know there was a bug in old browsers where if you had a certificate A signed by the root, A could then sign B, and B would appear valid. SSL is supposed to stop this by having flags on certificates, and A would not have the "can sign" flag. However, this was not verified in some old browsers.
Good luck! I'd be interested to hear how you get on.
Paul
Certificate hostnames don't match the site hostname
This is probably the easiest to check, and failure (to fail) there is certainly a good indication that something is wrong. Most certificates for well-known services only use host names for their identity, not IP addresses. If, instead of asking for https://www.google.com/, you ask for https://173.194.67.99/ (for example) and it works, there's something wrong.
For the other ones, you may want to generate your own test CA.
Certificate chain does not contain a trusted certificate authority
You can generate a test certificate using your test CA (or a self-signed certificate), but let the default system CA list be used for the verification. Your test client should fail to verify that certificate.
It is used before its activation date, It is used after its expiry date
You can generate test certificates using your test CA, with notBefore/notAfter dates that make the current date invalid. Then, use your test CA as a trusted CA for the verification: your test client should fail to validate the certificate because of the dates.
It has been revoked
This one is probably the hardest to set up, depending on how revocation is published. Again, generate some test certificates that you've revoked immediately, using your own test CA.
Some tools expect to be configured with a set of CRL files next to the set of trusted CAs. This requires some setup for the test itself, but very little online setup: this is probably the easiest. You can also set up a local online revocation repository, e.g. using CRL distribution points or OCSP.
PKI testing can be more complex than that more generally. A full test suite would require a fairly good understanding of the specifications (RFC 5280). Indeed, you may need to check the dates for all intermediate certificates, as well as various attributes for each certificate in the chain (e.g. key usage, basic constraints, ...).
In general, client libraries separate the verification process into two operations: verifying that the certificate is trusted (the PKI part) and verifying that it was issued to the entity you want to connect to (the host name verification part). This is certainly due to the fact these are specified in different documents (RFC 3280/5280 and RFC 2818/6125, respectively).
From a practical point of view, the first two points to check when using an SSL library are:
What happens when you connect to a known host, but with a different identifier for which the certificate isn't valid (such as its IP address instead of the host)?
What happens when you connect to a certificate that you know cannot be verified by any default set of trusted anchors (for example, a self-signed certificate or from your own CA).
Failure to connect/verify should happen in both cases. If it all works, short of implementing a full PKI test suite (which require a certain expertise), it's often the case that you need to check the documentation of that SSL library to see how these verifications can be turned on.
Bugs aside, a fair number of problems mentioned in this paper are due to the fact that some library implementations have made the assumption that it was up to their users to know what they were doing, whereas most of their users seem to have made the assumption that the library was doing the right thing by default. (In fact, even when the library is doing the right thing by default, there is certainly no shortage of programmers who just want to get rid of the error message, even if it makes their application insecure.)
I would seem fair to say that making sure the verification features are turned on would be sufficient in most cases.
As for the status of a few existing implementations:
Python: there was a change between Python 2.x and Python 3.x. The ssl module of Python 3.2 has a match_hostname method that Python 2.7 doesn't have. urllib.request.urlopen in Python 3.2 also has an option to configure CA files, which its Python 2.7 equivalent doesn't have. (This being said, if it's not set, verification won't occur. I'm not sure about the host name verification.)
Java: verification is turned on by default for both PKI and host name for HttpsUrlConnection, but not for the host name when using SSLSocket directly, unless you're using Java 7 and you've configure its SSLParameters using setEndpointIdentificationAlgorithm("HTTPS") (for example).
PHP: as far as I'm aware, fopen("https://.../") won't perform any verification at all.

What is the main purpose of openssl's SSL_CTX_use_certificate_file?

The man page did not clearly specify this. But looking at openssl's apps implementations, SSL_CTX_use_PrivateKey* calls are usually made after SSL_CTX_use_certificate_file succeeded. I assume this is mostly used at the server side.
I recently confused the above function with SSL_CTX_load_verify_locations wherein you could specify a CA certificate file and path. It turned out that SSL_CTX_load_verify_locations is the one I needed to verify a server certificate which is signed by a Trusted Authority.
SSL_CTX_use_certificate_file() is used to load the certificates into the CTX object either in PEM or DER format. The certificates can be chained ultimately ending at the root certificates. SSL_CTX_use_certificate_file API loads the first certificate into the CTX context;not the entire chain of certificates. If you prefer that thorough check of certificates is needed then you need to opt for SSL_CTX_use_certificate_chain_file()
http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=/com.ibm.ztpf-ztpfdf.doc_put.cur/gtpc2/cpp_ssl_ctx_use_certificate_file.html

Resources