X509Certificate2 在 Linux 上无法解析,但在 Windows 上可以运行

sec*_*ana 5 c# linux x509certificate2 .net-core .net-standard

从字节数组创建 X509Certificate2 实例在 Windows 上可以工作,但在 Linux 上会失败并出现“CryptographicException”。

static void Main(string[] args)
{
    var cert = new X509Certificate2(Cert.CertBytes);
}
Run Code Online (Sandbox Code Playgroud)

在 Windows 上:创建有效的 X509Certificate2 实例 在 Linux 上:引发异常:

{System.Security.Cryptography.CryptographicException: Cannot find the original signer. at Internal.Cryptography.Pal.PkcsFormatReader.TryReadPkcs7(SafePkcs7Handle pkcs7, Boolean single, ICertificatePal& certPal, List`1& certPals) at Internal.Cryptography.Pal.PkcsFormatReader.TryReadPkcs7Der(Byte[] rawData, Boolean single, ICertificatePal& certPal, List`1& certPals) at Internal.Cryptography.Pal.CertificatePal.FromBlob(Byte[] rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] data) at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData) at CertTest.Program.Main(String[] args) in /home/CertTest/Program.cs:line 14}

难道我做错了什么?我认为证书就是证书,无论解析它的操作系统是什么。

您可以在此处找到可以在 Windows 上解析但不能在 Linux 上解析的有效 X509 证书:https://gist.github.com/secana/9c13f8fa495681f8a30adb5d8754450e

我尝试了多个证书,但没有一个在 Linux 上有效。我没有 Mac,所以无法测试它是否可以在 Mac 上运行。

在 Ubuntu 16.04、Ubuntu 17.10、OpenSuse Tumbleweed、Windows 10 上使用 .Net Core 2.0.2 进行了测试

sec*_*ana 4

由于new X509Certficate2()在 Linux 下不会像在 Windows 下那样返回签名证书,因此您必须解析 PKCS7 的 ASN.1 结构才能找到签名证书。

例子:

 // Import all certificates in the structure into a collection
 var collection = new X509Certificate2Collection();
 collection.Import(Cert.CertBytes);

 // Find the signing cert
 var signingCert = collection.Cast<X509Certificate2>().FirstOrDefault(cert => 
 string.Equals(cert.SerialNumber, SignerSerialNumber, 
 StringComparison.CurrentCultureIgnoreCase));
Run Code Online (Sandbox Code Playgroud)

唯一的困难是获取签名证书的序列号。为此,我解析了 ASN.1 结构。序列号位于 ASN.1 路径中1/0/4/0/1/1

例子:

// Get signing cert serial number from ASN.1
var serialNumber = asn1[1][0][4][0][1][1];
Run Code Online (Sandbox Code Playgroud)

作为 ASN.1 解析器,我使用了 Mono 项目中的代码,但 Nuget 上有多个可用的解析器。