Closed jc-lab closed 3 years ago
Thank you very much, this looks excellent. Who should I credit?
Thank you for your positive response.
What is means, "Who should I credit?"? I am not good at English... :'(
I'd like to thank you in the changelog for this contribution, but I can't see your name.
Fixed! My name is Joseph Lee.
Note. b7e4066 commit: Fix infinite-loop for larger then 1MB in MSCabFile
@jc-lab I got quick look and it worked fine except for files with multiple signatures where the validation failed. I haven't checked yet if this case works with signtool and what the differences are with jsign.
I checked with signtool and .cab files can be signed multiple times. Also I noticed that the signature of the file signed in testReplaceSignature()
fails to validate. So it looks like there is something wrong when a file already signed is processed.
@ebourg If sign with signtool and then re-sign with withSignaturesReplaced(true), it works correctly. How did you test it? Can you show a test code that fails verification?
My test code:
@Test
public void testReplaceSignature2() throws Exception {
File sourceFile = new File("target/test-classes/cabinet-sample-1-already-signed/disk1/sample.cab");
File targetFile = new File("target/test-classes/cabinet-sample-1-replaced-signed-2/disk1/sample.cab");
FileUtils.copyFile(sourceFile, targetFile);
MSCabFile file = new MSCabFile(targetFile);
List<CMSSignedData> signatures = file.getSignatures();
assertNotNull(signatures);
assertEquals("number of signatures", 2, signatures.size());
AuthenticodeSigner signer = new AuthenticodeSigner(getKeyStore(), ALIAS, PRIVATE_KEY_PASSWORD)
.withDigestAlgorithm(DigestAlgorithm.SHA512)
.withProgramName("Minimal Package")
.withProgramURL("http://example.com")
.withSignaturesReplaced(true);
signer.sign(file);
file = new MSCabFile(targetFile);
signatures = file.getSignatures();
file.close();
assertNotNull(signatures);
assertEquals("number of signatures", 1, signatures.size());
assertNotNull(signatures.get(0));
assertEquals("Digest algorithm", DigestAlgorithm.SHA512.oid, signatures.get(0).getDigestAlgorithmIDs().iterator().next().getAlgorithm());
}
cabinet-sample-1-already-signed/disk1/sample.cab
download : https://pastebin.com/he6eLNHL (base64 encoded)
I just ran testReplaceSignature()
from MSCabinetSignerTest.java
and the signature failed to validate. Do you get a valid signature with this test?
@ebourg I just tested it again. Works fine.
Please delete the jsign-core/target/test-classes
directory and try again.
Maybe the directory is dirty.
How do you check the signatures?
I just ran the test code and only checked in the file properties tab of explorer.
I confirmed that verification fails with the signtool verify
command. (SignTool Error: WinVerifyTrust returned error: 0x80096010
)
I will fix it. Thank you.
https://gist.github.com/jc-lab/05a12fc2f5deae65c78f77da3d4298d3 All of the verification through signtool was successful.
I confirm the signature replacement and the multiple signatures work fine now.
I didn't notice it before but the signature of cabinet-sample-3-signed.cab fails to validate too.
sample-3 is not used. It is the same as sample-2. sample-2 (Multi-volume) was also fixed in the c25756f commit.
I think this looks great and seems to work. Anything open before it can be merged?
I have to find some time to check the tests again.
In the multi disk case (sample 2), is it normal that only the first disk is signed?
Um... I can't remember well because it happened a long time ago.. I will compare it with Microsoft's tools and let you know.
The digest process was incorrect due to insufficient References on Cabinet AuthentiCode. I found the correct way and fixed it.
The headerDigestUpdate
part has been fixed.
Below is the test result with automatic verification using the signtool tool.
CAB File
Name: sample.cab
Size: 17515
Last Modified: Sun Mar 21 15:57:51 KST 2021
Verifying: D:\jcworkspace\jsign\jsign-core\target\test-classes\cabinet-sample-2-signed\disk1\sample.cab
Signature Index: 0 (Primary Signature)
Hash of file (sha256): E1A96C65E376EE3B4D0EC46EA2ABC144E390E5C97D0376D5EFF886D68884E387
Signing Certificate Chain:
Issued to: Jsign Root Certificate Authority
Issued by: Jsign Root Certificate Authority
Expires: Thu Jun 11 04:55:56 2037
SHA1 hash: D23C30ECFB196B2F349B614CFB43AA8B4B35C091
Issued to: Jsign Code Signing CA
Issued by: Jsign Root Certificate Authority
Expires: Thu Jun 11 04:55:56 2037
SHA1 hash: E8410255F9D237BFB5F476EC38B8A117FE6061B2
Issued to: Jsign Code Signing Test Certificate
Issued by: Jsign Code Signing CA
Expires: Thu Jun 11 04:55:56 2037
SHA1 hash: 9E2FD81E5A61B81FF41C4268AB2B1FC90506FE05
File is not timestamped.
Successfully verified: D:\jcworkspace\jsign\jsign-core\target\test-classes\cabinet-sample-2-signed\disk1\sample.cab
Number of files successfully Verified: 1
Number of warnings: 0
Number of errors: 0
CAB File
Name: sample.cab
Size: 14099
Last Modified: Sun Mar 21 15:57:51 KST 2021
Verifying: D:\jcworkspace\jsign\jsign-core\target\test-classes\cabinet-sample-2-signed\disk2\sample.cab
Signature Index: 0 (Primary Signature)
Hash of file (sha256): 9AD30179C67D2AD43AE78DDC8C2C35C28417EA3324F04C0288F93219FE5A600F
Signing Certificate Chain:
Issued to: Jsign Root Certificate Authority
Issued by: Jsign Root Certificate Authority
Expires: Thu Jun 11 04:55:56 2037
SHA1 hash: D23C30ECFB196B2F349B614CFB43AA8B4B35C091
Issued to: Jsign Code Signing CA
Issued by: Jsign Root Certificate Authority
Expires: Thu Jun 11 04:55:56 2037
SHA1 hash: E8410255F9D237BFB5F476EC38B8A117FE6061B2
Issued to: Jsign Code Signing Test Certificate
Issued by: Jsign Code Signing CA
Expires: Thu Jun 11 04:55:56 2037
SHA1 hash: 9E2FD81E5A61B81FF41C4268AB2B1FC90506FE05
File is not timestamped.
Successfully verified: D:\jcworkspace\jsign\jsign-core\target\test-classes\cabinet-sample-2-signed\disk2\sample.cab
Number of files successfully Verified: 1
Number of warnings: 0
Number of errors: 0
It looks great, thank you! I'll merge that soon with a few cosmetic changes.
I've stumbled on an infinite loop when signing an old cab file from Windows 95:
[WIN95_03.CAB.gz]()
I haven't figured out the issue yet.
I also got sigpos wrong and found that channel.read
fails to read the file and causes an infinite loop.
I will fix it. Thank you for finding the case.
Can you tell me the origin of the file? I think it could be helpful in analyzing the cause.
I got it from an old Windows NT 4.0 ISO.
Can you share the entire file (ISO or full CAB)?
My email is development@jc-lab.net
.
Among the files I found on the Internet, I could not find a cab similar to the format.
Also, if I verify with signtool, I get the following error.
SignTool Error: CryptCATAdminCalcHashFromFileHandle returned error: 0x0000000B (ERROR_BAD_FORMAT)
Even unsigned files do not normally cause CryptCATAdminCalcHashFromFileHandle
errors.
Actually, I first got a buffer overflow with the file WIN95_03.CAB:
java.nio.BufferOverflowException
at java.nio.Buffer.nextPutIndex(Buffer.java:527)
at java.nio.HeapByteBuffer.putInt(HeapByteBuffer.java:372)
at net.jsign.mscab.MSCabFile.setSignature(MSCabFile.java:424)
at net.jsign.AuthenticodeSigner.sign(AuthenticodeSigner.java:349)
The file got corrupted and then triggered an infinite loop when I ran the test again.
There was a mistake in not clearing the buffer. Fixed it.
This is now merged, many thanks! Let me know how it works for you. If it goes well I'll try to publish the 3.2 release next week.
I tested an exe and a cab used in our production. It works fine! The code is also beautiful! Thank you.
Support MS-CAB
All tests OK