-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
new X509Certificate2(byte[]) should return the signing cert for PKCS#7 on Unix #15073
Comments
Marking Future explicitly because we have decided thisi s not necessary for 2.0. |
Moving to Future, it's just getting a bit late to plumb this down (and a lot of tests need to be defined to ensure that we're behaving the same way as in our Windows black-box implementation... zero signers, multiple signers, igner-cert-not-included, hybridized values, etc) The workaround for caller code which knows it's getting a PKCS7 is to just load it into the SignedCms class. This is the naive approach (only works for one signer, when the signer cert is present) SignedCms cms = new SignedCms();
cms.Decode(bytes);
SignerInfoCollection signers = cms.SignerInfos;
if (signers.Count != 1)
{
throw new CryptographicException("Wrong number of signers.");
}
return signers[0].Certificate ?? throw new CryptograpicException("Signer cert was not present"); |
I was playing with decoding Authenticode, which is also supposed to be supported. Turns out most of the plumbing code is already present in CoreFX (no error handling, just PoC):
and it boils down to reading PKCS#7 certificates. The last constructor fails with an exception. |
We need to be able to verify Authenticode signatures on managed DLLs in Linux for licensing enforcement. |
Hello, my project based on linux relying on reading cert from PKCS#7 signed file, which is not working atm. Is this going to be fixed in upcoming .NET Core versions (3.0) or what is the situation around this? I would greatly appreciate any info about this issue and its future. |
@Kalyxt Maybe https://github.com/secana/PeNet can do what you want (I'm the author). The PeNet library is able to extract the cert from signed files on Windows, Linux and Mac. |
Thanks! This is exactly what I was looking for. I've tested it on win and linux-arm. |
No, there's not a lot of time left in the 3.0 release and I'm already over committed. (Though PRs are welcome if someone wants to contribute a fix...) |
Any updates on the issue regarding the version it will most likely be fixed in? It's not fixed in 3.1 and was already an issue in 2.0. |
I'll go ahead and mark it as 5 (aka "next version"). If you want to give it a try, Lines 226 to 236 in 4f9ae42
If you just want the functionality but aren't too keen on playing with pointers, that's fine... it'll still get taken care of this release. |
TODO(2910): Figure out how to extract the signing certificate, when it's present. Get the serial number of the signing certificate: private string? GetSigningSerialNumber()
{
var asn1 = _contentInfo?.Content;
if (asn1 is null) return null;
var x = (Asn1Integer)asn1.Nodes[0].Nodes[4].Nodes[0].Nodes[1].Nodes[1]; // ASN.1 Path to signer serial number: /1/0/4/0/1/1
return x.Value.ToHexString().Substring(2).ToUpper();
} Get the signing certificate from the PE file with the private X509Certificate2 GetSigningCertificateNonWindows(PeFile peFile)
{
var collection = new X509Certificate2Collection();
collection.Import(peFile.WinCertificate?.BCertificate.ToArray());
return collection.Cast<X509Certificate2>().FirstOrDefault(cert =>
string.Equals(cert.SerialNumber, SignerSerialNumber, StringComparison.CurrentCultureIgnoreCase));
} But I'm not sure on how to get access to the Asn1 of the PE file in the |
@secana There are two different issues.
|
On macOS, X509Certificate2Collection.Import() throws the following exception when importing PKCS#7 data: > HResult = -25257 Message = Unknown format in import. Source = System.Security.Cryptography.X509Certificates StackTrace = at Internal.Cryptography.Pal.X509Pal.AppleX509Pal.GetCertContentType(Byte[] rawData) at System.Security.Cryptography.X509Certificates.X509Certificate2.GetCertContentType(Byte[] rawData) at Internal.Cryptography.Pal.StorePal.FromBlob(Byte[] rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(Byte[] rawData) at PeNet.Header.Authenticode.AuthenticodeInfo.GetSigningCertificateNonWindows(Byte[] pkcs7) Using `SignedCms.Decode` instead of `X509Certificate2Collection.Import` as [suggested by Jeremy Barton][1] works on macOS thus making all the unit tests pass. [1]: dotnet/runtime#15073 (comment)
On macOS, X509Certificate2Collection.Import() throws the following exception when importing PKCS#7 data: > HResult = -25257 Message = Unknown format in import. Source = System.Security.Cryptography.X509Certificates StackTrace = at Internal.Cryptography.Pal.X509Pal.AppleX509Pal.GetCertContentType(Byte[] rawData) at System.Security.Cryptography.X509Certificates.X509Certificate2.GetCertContentType(Byte[] rawData) at Internal.Cryptography.Pal.StorePal.FromBlob(Byte[] rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(Byte[] rawData) at PeNet.Header.Authenticode.AuthenticodeInfo.GetSigningCertificateNonWindows(Byte[] pkcs7) Using `SignedCms.Decode` instead of `X509Certificate2Collection.Import` as [suggested by Jeremy Barton][1] works on macOS thus making all the unit tests pass. [1]: dotnet/runtime#15073 (comment)
I think I can pick this one up to get
@bartonjs Do you know off the top of your head if it is actually validating anything? Maybe it isn't going so far as to validate a certificate chain or anything, but I wonder what happens if the If we actually need to validate something, we can't add a reference to S.S.C.Pkcs due to circular references. |
I'm like 98% sure that it's just a structural decode and checking if it's a signed CMS for Windows to report that it's |
@jeffhandley |
@jeffhandley This issue was in the 7.0.0 bucket that's now marked as completed. Is the fix in .NET 7? |
No. This is currently marked "Future" and still open. This did not get complete for 7.0. |
I've been hitting this issue (I think), reading up on it, and am wondering if someone can confirm that I'm understanding the implications correctly. |
If you mean a file signed with Windows Authenticode, then correct - .NET does not provide an API to verify Authenticode signatures. But |
Thanks. Part of what I was struggling to determine was if all code signing in Windows was Authenticode or not as a lot of info just refers to 'digital signature'. In any case, I think it's safe to say that Window's signtool.exe is Authenticode. Quite right, getting the cert from the file isn't validating the cert, that was a subsequent step I was taking. I just wanted to be sure that my actual goal of validating the file wasn't possible some other way that didn't necessitate actually having the cert object itself. |
what is the status of this? as we think we experience invalid exports of PKCS#7 in .net 7 and seeing this makes me believe things are not fully implemented yet? |
This issue is specifically about importing a PKCS#7 blob from @wstaelens do you have a code snippet of what is not working for you? |
@vcsjones We tried several things. Maybe missing something, not sure how to get it working.
If we do If we put it in a collection and export it the file is about 30% smaller and when importing it it isn't valid (can't debug it is being loaded into an external device). |
The Windows code supports reading a PKCS#7 signed or PKCS#7 signed-and-enveloped structure; but in single certificate mode it doesn't return certs[0], it returns the certificate which signed the structure.
My test files (produced by Windows (certmgr.msc and X509Certificate2Collection::Export)) aren't signed, so Windows emits an exception (
new CryptographicException(ErrorCode.CRYPT_E_SIGNER_NOT_FOUND)
).Without a sample to see what's going on here, it's hard to make compatible behavior. So, for now, the Unix implementation will just throw, even if it could have worked.
The text was updated successfully, but these errors were encountered: