Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PKCS#7 CMS signing and verification #526

Open
wants to merge 70 commits into
base: main
Choose a base branch
from
Open

Conversation

jonwltn
Copy link
Contributor

@jonwltn jonwltn commented Dec 11, 2024

This is a very rough, initial draft at adding PKCS#7 CMS signing and verification to KSE. There are lots of TODOs for proper error messaging and missing functionality.

I added a comment to #456 showing sample screenshots. This implementation only supports signing/verification, and I piggybacked off the existing KeyEntry Sign menu item, but if encryption and decryption are going to be added, it might make sense to add new top-level menu item for PKCS#7 CMS operations.

Things left to do:

  • Fix counter signing when using a timestamp server
  • Re-enable signature verification code
  • Establish trust to certs in the current or cacerts keystores during verification
  • Review all UI strings for clarity and accuracy
  • Clean up the code

Prompt for a file when the content for a detached signature cannot be
automatically identified.
Copy link
Owner

@kaikramer kaikramer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still a draft, but I thought it might be helpful to give feedback as early as possible.

You are doing well, but feel free to ask in the comments section if there are things that you would like to discuss.

@jonwltn
Copy link
Contributor Author

jonwltn commented Dec 28, 2024

Thank you for the review comments. They came at a good time. The commits that you reviewed are structurally nailed down, and I don't anticipate any major changes to the design. I'm mostly cleaning up the code and making certain that all my TODOs are addressed.

Here is a screenshot of the view signature form:
image

There are two ASN.1 buttons. The top one displays the ASN.1 for the selected signer info. The bottom one displays the ASN.1 for the entire PKCS#7 structure. I can either rename the button to "Signer ASN.1" or just remove the button entirely.

@kaikramer
Copy link
Owner

There are two ASN.1 buttons. The top one displays the ASN.1 for the selected signer info. The bottom one displays the ASN.1 for the entire PKCS#7 structure. I can either rename the button to "Signer ASN.1" or just remove the button entirely.

I like having the separate "Signer ASN.1" button because PKCS#7 structures can be quite confusing and being able to filter out the relevant parts is very convenient.

@jonwltn
Copy link
Contributor Author

jonwltn commented Jan 7, 2025

I want to always use the cacerts and Windows trusted root certs for verifying the Time Stamp Token certs since TSAs should be using trusted certs. I want to directly use AuthorityCertificates rather than the helper methods in AuthorityCertificatesAction, but the action super class handles the loading of cacerts. Thoughts?

For verifying signature trust, I am going to build a cert chain to a self-signed cert, if possible since the signature might not have all the certs if it's malformed, then verify the trust of the root of the chain. I think I can use X509CertUtil.establishTrust to build my chain by giving it the list of signature certs (which are not trusted). Then I can take the root from that chain and use X509CertUtil.establishTrust again to try to find a matching cert using the currently loaded keystore.

@kaikramer
Copy link
Owner

kaikramer commented Jan 7, 2025

I want to always use the cacerts and Windows trusted root certs for verifying the Time Stamp Token certs since TSAs should be using trusted certs. I want to directly use AuthorityCertificates rather than the helper methods in AuthorityCertificatesAction, but the action super class handles the loading of cacerts. Thoughts?

I agree with you that it's better to verify the timestamps regardless of the user settings. Even for the rare cases when a private TSA was used, a trust anchor is probably available in either cacerts or the OS truststore.

However, I'm not sure if I fully understand the question, because the action super class (you mean KeyStoreExplorerAction, right?) does not really provide much for loading cacerts - apart from the preferences with the file location but you can get the preferences always via PreferencesManager.getPreferences().

If you are referring to AuthorityCertificatesAction.loadCaCertificatesKeyStore(), which consists mostly of password input and error handling and that would be annoying to replicate in VerifySignatureAction and therefore you want to move it into its super class? If that is your suggestion, then I am not very happy about it, but I can live with it.

For verifying signature trust, I am going to build a cert chain to a self-signed cert, if possible since the signature might not have all the certs if it's malformed, then verify the trust of the root of the chain. I think I can use X509CertUtil.establishTrust to build my chain by giving it the list of signature certs (which are not trusted). Then I can take the root from that chain and use X509CertUtil.establishTrust again to try to find a matching cert using the currently loaded keystore.

If I understood you correctly then this should work just fine. Just keep in mind that you'll have to provide a matching self-signed trust anchor somewhere, otherwise establishTrust() will just return null. X509CertUtil.establishTrust() with the list parameter is currently private, but you can make it public if necessary.

Some possible sources to consider or take inspiration from:

  • The JDK class sun/security/pkcs/SignerInfo.java contains a getCertificateChain() method
  • BC might have something similar
  • There is also the RFC 5280 "Certificate Path Validation" algorithm (https://datatracker.ietf.org/doc/html/rfc5280#section-6), see VerifyCertificateAction

@jonwltn
Copy link
Contributor Author

jonwltn commented Jan 10, 2025

I did something wrong when rebasing my branch with the latest changes from main. Now this pull request includes all the files from the last 13 commits. GitHub recommends discarding all my commits, which I'm good with doing since I have another branch with all my changes.

@jonwltn
Copy link
Contributor Author

jonwltn commented Jan 10, 2025

Ok. This is ready to go. I have one last TODO regarding icons for the signer/counter signer when viewing a signature. Right now, there are no icons in the signer tree view.

What should I do about non-English translations? I've only provided English resource strings in this pull request.

@jonwltn jonwltn reopened this Jan 10, 2025
@jonwltn jonwltn marked this pull request as ready for review January 10, 2025 06:03
@@ -95,7 +95,7 @@ protected KeyStore getWindowsTrustedRootCertificates() throws CryptoException {
return windowsTrustedRootCertificates;
}

private KeyStore loadCaCertificatesKeyStore() {
protected KeyStore loadCaCertificatesKeyStore() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this method protected so that I could use it in the VerifySignatureAction subclass. This seemed like the best compromise.

return certs;
}

private Store<X509CertificateHolder> getTrustedCertsNoPrefs()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method and the following one are essentially duplicates of the super class methods, but they don't check for the user prefs. These certs are used for verifying the TSA timestamp token certs.

}
}

private Collection<X509Certificate> extractCertificates(KeyStore keystore) throws CryptoException {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This extract method is essentially the same as the one in X509CertUtil, but it also reads the certs in chain since the current keystore might have the verifying cert linked to a private key (e.g. signing user wanting to see if the signature if valid).

For other users that didn't sign the file checking for the cert chain is obviously unnecessary.


cell.setText(signer.getShortName());

// TODO JW Is an icon for signer tree cell renderer desired?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last TODO. If icons are something for the future, then I'll just remove the TODO and the commented out code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants