ebourg / jsign

Java implementation of Microsoft Authenticode for signing Windows executables, installers & scripts
https://ebourg.github.io/jsign
Apache License 2.0
250 stars 107 forks source link

"No signature found"/"No signature was present in the subject" when signing exe #93

Open markawightman75 opened 3 years ago

markawightman75 commented 3 years ago

Hi,

Firstly - thanks for your amazing work on jsign. It's exactly what we need!

We're trying to sign a Windows exe using a SHA512 key stored in Google KMS and with an EV certificate from GlobalSign, but the digital signature on the exe has the "No signature was present in the subject" message, and verifying with SignTool reports "No signature found".

I'm running jsign from code, having cloned the repo a couple of days ago.

We created a key like this:

gcloud kms keys create focal-point-code-signing-key \
--keyring code-signing-ring \
--location europe-west2 \
--purpose asymmetric-signing \
--protection-level hsm \
--default-algorithm rsa-sign-pss-4096-sha512

gcloud kms keys versions \
get-public-key 1 \
--location europe-west2 \
--keyring code-signing-ring \
--key focal-point-code-signing-key \
--output-file ./focal-point-code-signing-key.pub

and a CSR using https://github.com/mattes/google-cloud-kms-csr, which we used to get our certificate from GlobalSign. The certificate itself has a signature algorithm of sha256WithRSAEncryption but my understanding is that this doesn't need to match the signature algorithm we use to sign the exe?

We're using the following parameters with jsign:

--storetype "GOOGLECLOUD" \
--storepass <token>
--keystore projects/waives-service/locations/europe-west2/keyRings/code-signing-ring
--alias projects/waives-service/locations/europe-west2/keyRings/code-signing-ring/cryptoKeys/focal-point-code-signing-key/cryptoKeyVersions/1
--tsaurl http://timestamp.globalsign.com/tsa/r6advanced1
--tsmode RFC3161
--alg SHA-512
--certfile /home/mark/code/code-signing/focal-point-code-signing-certificate.cer
<file-to-sign.exe>

Do you have any ideas about what could be going on, or suggestions about how we could investigate? We don't currently have a thread to pull on.

Really appreciate all your work, and any suggestions you might have!

Thanks,

Mark

markawightman75 commented 3 years ago

Here's a screenshot of the exe properties.

image

I'm slightly suspicious of "No signature was present in the subject" also appearing in the certificate information for our certificate:

image

ebourg commented 3 years ago

Thank you for the feedback. Would you be able to sign the wineyes.exe file from the Jsign test resources and send it to ebourg@apache.org please? I'll get a look.

markawightman75 commented 3 years ago

Thanks Emmanuel, much appreciated - I've emailed it to you.

ebourg commented 3 years ago

I looked at the signed file but I fail to see what's wrong. Would you be able to sign it with signtool and see if there is the same error? If it works with signtool a side by side comparison of the two signatures will certainly unveil the cause of the issue. I suggest disabling the timestamping to simplify the comparison.

markawightman75 commented 3 years ago

Hi Emmanuel. Thanks for looking. Yes, we'll try what you suggest. Are you able to point at any instructions for how to sign with SignTool when our private/public key is in Google KMS? We've failed to find any guide on how to do this!

ebourg commented 3 years ago

Good question, I assume there is a PKCS#11 library somewhere for Google KMS but I haven't found one yet.

ebourg commented 3 years ago

Maybe using this ? https://github.com/nextgens/authenticode-sign-action https://github.com/nextgens/CloudSignTool https://github.com/nextgens/CloudSignTool/releases/download/1.0.0/SignTool.exe

markawightman75 commented 3 years ago

Thanks, yes I've tried CloudSignTool and am getting the same result. This suggests it isn't a JSign issue, but I'm at a loss to understand where the issue could be. I think I'll have to go back to GlobalSign and see if they have any suggestions.

ebourg commented 3 years ago

There's propably an issue with the certificate then. Let me know if you find out the issue, that may help others in the future.

markawightman75 commented 3 years ago

Thanks Emmanuel, yes I will.

opub commented 2 years ago

@markawightman75 did you ever get this resolved? I am getting the same error with a GlobalSign EV certificate. It seems related to the 4096 key size.

maxpain commented 2 years ago

@markawightman75 How did you resolve this problem?

woohgit commented 2 years ago

@markawightman75 I'm having exactly the same issue. Any updates on your side? Did you ever get this resolved?

maxpain commented 2 years ago

@markawightman75 I'm having exactly the same issue. Any updates on your side? Did you ever get this resolved?

I resolved this problem by changing the sequence of certificates in the chain.

woohgit commented 2 years ago

@maxpain In what order?

  1. your cert
  2. their cert (GlobalSign Root CA?)
maxpain commented 2 years ago

@maxpain In what order?

  1. your cert
  2. their cert (GlobalSign?)
image

I got all 3 certificates from GlobalSign.

maxpain commented 2 years ago

Example:

jsign --storetype GOOGLECLOUD \
        --storepass "$(gcloud auth print-access-token)" \
        --keystore projects/codesigning/locations/europe-central2/keyRings/CodeSigning \
        --alias ev4096 \
        --certfile full-chain.pem \
        --tsaurl http://timestamp.globalsign.com/tsa/r6advanced1 \
        --tsmode RFC3161 \
        example_app.exe
woohgit commented 2 years ago

@maxpain Are all certs have 4096 bit length?

maxpain commented 2 years ago

@maxpain Are all certs have 4096 bit length?

I don't know. How to check?

woohgit commented 2 years ago

@maxpain Are all certs have 4096 bit length?

I don't know. How to check?

cat intermediate1.cer | openssl x509 -text -noout

Check the RSA Public-key (XXXX bit) part of the output.

maxpain commented 2 years ago
image
woohgit commented 2 years ago
image

Thanks!

woohgit commented 2 years ago
image

And how did you generate the CSR which was signed by GlobalSign? I assume you're also using Cloud HSM (AWS or Google)

maxpain commented 2 years ago

And how did you generate the CSR which was signed by GlobalSign? I assume you're also using Cloud HSM (AWS or Google)

I used this: https://github.com/mattes/google-cloud-kms-csr

woohgit commented 2 years ago

And how did you generate the CSR which was signed by GlobalSign? I assume you're also using Cloud HSM (AWS or Google)

I used this: https://github.com/mattes/google-cloud-kms-csr

Sorry for the questions but one more last: What kind of keys do you have in HSM. What's the key type / algorithm? I suspect we're using a not properly supported version on Google Cloud KMS HSM

maxpain commented 2 years ago
Screenshot 2021-12-16 at 12 29 55 Screenshot 2021-12-16 at 12 29 59
woohgit commented 2 years ago
Screenshot 2021-12-16 at 12 29 55 Screenshot 2021-12-16 at 12 29 59

Perfect, and what's the algorithm inside if you click on the ev4096 key?

Mine looks like this:

2021-12-16_19-36

maxpain commented 2 years ago
image
woohgit commented 2 years ago
image

Million thanks!

woohgit commented 2 years ago

@maxpain I can verify that it works with 4096 bit RSA key (PKCS#1 v1.5 padding - SHA256 Digest)

But it does not work with Google KMS HSM - 4096 bit RSA key (PSS Padding - SHA265 Digest). Maybe it's related to the original issue.

cc @ebourg @markawightman75

ebourg commented 2 years ago

The signing certificate should come first in the chain file, but there might be a problem with PSS padding too, I'm not sure. My Google Gloud trial is over so I can't test. Could anyone confirm that the error "No signature was present in the subject" is only triggered by a misordered chain file, regardless of the padding?

MTSym commented 2 years ago

I still do have the same problem.

Here is a complete step by step what i did maybe this will shed some light:

Notes:

1) Create an HSM Key with 4096 bit RSA key (PSS Padding - SHA265 Digest) 2) Change and build https://github.com/mattes/google-cloud-kms-csr tool as stated in the notes and use the information to create the CSR 3) Use the CSR to optain the global-sign certificate + intermidiate1/intermidiate2 certs 4) Create an full-chain.pem by combining the OSXXXXXXXX certs with the intermidiate certs. First OSX then intermidiate 1 then intermidiate 2 5) Use Jsign to sign the file (in my case an .msi)

java -jar jsign.jar --storetype GOOGLECLOUD \
  --storepass $(gcloud auth print-access-token) \
  --keystore KEYSTORE_NAME \
  --alias KEY_VERSION_PUBLIC_NAME \
  --certfile full-chain.pem \
  --replace \
  --tsaurl http://timestamp.globalsign.com/tsa/r6advanced1 \
  --tsmode RFC3161 \
  my.msi

The version 1 is the key with PSS Padding. Which resulted in the same error

6) Create a version 2 with PKCS Padding (Change the default algorithm and create new version) 7) Sign the file with the same command as above only referencing another version in the alias

Still the same problem so for me neither of the Algorithms nor creating a fullchain-pem worked. Unfortunately. @maxpain @woohgit It would be great if you could check the order i did the things and correct me if you see any differences from your's

@ebourg If you need anything please let me know.

woohgit commented 2 years ago

Hey @MTSym

The PSS will never work as it's not supported by Windows. The only key that confirmed and works is the:

Do you get any error from jsign when signing or when creating the CSR?

MTSym commented 2 years ago

@woohgit It did not get any errors from jsign nor cloud-kms-csr tools. The only thing where i get an error is when I try to use the PKCS1 algorithm for the CSR and try to retrieve the certificate from global sign with it. As it seems that global sign does not support the PKCS1.

I am also not sure if it does make a difference when when I use one to generate the certificate and the other for signing.

Did you use the PKCS1 algorithm for generating the CSR to retrieve the certificate from global sign?

woohgit commented 2 years ago

If you're using RSASA-PKCS1 v1_5 HSM key, you need to use x509.SHA256WithRSA with the CSR.

GlobalSign and generally the CSRs should be CSR.

Don't use neither of these:

MTSym commented 2 years ago

@woohgit I hope it does not offend you but consider yourself hugged a million times.

I am not the most experienced one with crypto algorithms and that change for the CSR was the missing piece for everything. It is now a valid signature.

Thank you very much for providing the solution.

woohgit commented 2 years ago

@MTSym Glad that I could help :)

vmal-altium commented 1 year ago

In my case, the message "No signature was present in the subject" was triggered by a mismatch (my bad) between the private key (stored in AWS KMS, but I think it is not relevant here) and the signing certificate. Maybe we should try to detect that situation where the key is wrong or the certificate is not the correct one?

For RSA, one can compare the modulus of the key/certificate; if the key is not accessible directly, maybe a public key can be derived (that is the case for AWS KMS), and then compared to the certificate?

ebourg commented 1 year ago

@vmal-altium With b2b47a98bd1242426e867f2d320dcd34dc9427d6 an error is displayed if the public key and the private key don't match

javierguzman commented 11 months ago

I am facing a similar issue, specifically, I am getting the error "Signature verification failed, the private key doesn't match the certificate". After reading this thread I have not seen a pattern to solve the original issue. I am using the same key type as @maxpain

What I have done is:

  1. Create key in keyring within Google Cloud Platform
  2. Create CSR using that key
  3. Feed CSR to Digicert and obtained 1 pem file with 3 certs within
  4. Use that pem file with jsign

I would really appreciate if someone can give me a hint or point me out in the right direction.

Thank you in advance and regards

ebourg commented 11 months ago

@javierguzman Check the order of the certificates in the pem file, your signing certificate should come first

javierguzman commented 11 months ago

Thanks @ebourg, indeed I have tried with my certificate first, second by intermediate and then root. I have tried other orders without success.

However, I have realized that my key on GCP has a public key which is the same used on CSR. But the certificates I have got from Digicert has another public key...I believe all of them should have the same public key, right? Meaning is Digicert giving me wrong certificates??

ebourg commented 11 months ago

That's correct, the public key on the certificate and the CSR should be the same. The certificate is simply your public key combined with metadata, all signed by the CA.

javierguzman commented 11 months ago

I can confirm I have managed to solve it. I contacted Digicert support and indeed my order was generating the certs using an old CSR. Thanks to support I got the certs using the right CSR and it is working. So for everybody in future, check your GCP key, your CSR and your certs, all have the same public key. Thanks @ebourg again for your help, now I can start setting this up on CI.

ebourg commented 11 months ago

Thank you for sharing your experience, happy signing :)