-
-
Notifications
You must be signed in to change notification settings - Fork 112
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
Manifest file signing #118
Comments
This file format isn't supported by Jsign. As I understand it's a different signing scheme, even signtool doesn't support it. These files are signed with the Manifest Generation and Editing Tool (mage.exe) from Visual Studio. For the reference, I've played a bit with this tool and signed a manifest, it looks like this:
Files with this signature don't have a Digital Signature tab in the file properties (at least on Windows 10). This kind of signature isn't an Authenticode signature. Even if Jsign is focused on Authenticode I don't mind supporting this format as well. But I won't have the time to work on it. If someone is interested in implementing it, I'll be happy to review and integrate it. |
The generation of XML signatures in Java is documented here: |
Tried to reach out to you in email, but never heard back. |
I've played a bit with the XML signature API, the code snippet below is enough to sign a file but I don't think it makes a valid manifest signature yet:
KeyStore keystore = new KeyStoreBuilder().keystore("keystore.p12").storepass(password).build();
PrivateKey privateKey = (PrivateKey) keystore.getKey(alias, password.toCharArray());
Certificate[] chain = keystore.getCertificateChain(alias);
PublicKey publicKey = keystore.getCertificate(alias).getPublicKey();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
Document document = builder.parse(new FileInputStream("application.manifest"));
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM");
DigestMethod digestMethod = factory.newDigestMethod(DigestMethod.SHA256, null);
Transform transform = factory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null);
Reference ref = factory.newReference("", digestMethod, Collections.singletonList(transform), null ,null);
CanonicalizationMethod c14n = factory.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null);
SignatureMethod signatureMethod = factory.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", null);
SignedInfo signedInfo = factory.newSignedInfo(c14n, signatureMethod, Collections.singletonList(ref));
// key info
KeyInfoFactory keyInfoFactory = factory.getKeyInfoFactory();
KeyValue keyValue = keyInfoFactory.newKeyValue(publicKey);
X509Data x509Data = keyInfoFactory.newX509Data(Arrays.asList(chain));
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Arrays.asList(keyValue, x509Data));
XMLSignature signature = factory.newXMLSignature(signedInfo, keyInfo, null, "StrongNameSignature", null);
signature.sign(new DOMSignContext(privateKey, document.getDocumentElement()));
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(System.out)); |
I'm trying to figure this out myself. My use case is signing ClickOnce installers. The msrel:RelData element is definitely going to be required for that use case because that is where the Authenticode signature is, and Authenticode is the reason to sign ClickOnce installers in the first place. The manifest has two signatures, one strong name signature which is used for integrity checking and the other Authenticode signature which is used for authentication. I'm not an expert in this, this is just what I've figured out so far. I suppose they're both signed by the same key because they have equal publicKeyToken values. |
Thank you for the info, I didn't realize there were two signature schemes. I've found some references about strong name signatures: It's not clear to me if the strong name signature is expected to be created first with a different tool (sn.exe) and a specific key, and then Jsign would add the Authenticode signature, or if both signatures should be created by Jsign with the same key. |
That is not clear to me either. I'm not sure it needs to use the same key ... I'm not that familiar with dot net. In my previous reply I thought it did have to use the same key, because they have the same publicKeyToken, but I learned yesterday that the publicKeyToken is unrelated to the key you use for signing. It's a value that is taken from an XML attribute in the manifest of the assembly you're signing, at least for ClickOnce installers. If you have an existing DLL or EXE that is a dot net assembly, you can also get it by running |
I guess I just answered my own question. If you needed to use the same key, then the publicKeyToken value would change when you sign the ClickOnce installer, because you're signing it with your own key, not the vendor's key. But it doesn't. So the strong name signature I think is taken care of by the machinery of dot net and the important signature is the Authenticode signature. |
I have been investigating a similar use-case and microsoft recommends to do strong naming with a self-signed key, so I don't see why that would also be used for authenticode signatures as you would want to have a key backed by a Certificate Authority there. |
https://docs.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference
https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests
We are trying to sign such file, using jsign 4.0, with the above error.
It is an application manifest.
The text was updated successfully, but these errors were encountered: