gpt4 book ai didi

c# - 从 CAC/x509 证书扩展中解码 ASN.1 数据(主题目录属性 > 国籍)

转载 作者:行者123 更新时间:2023-11-30 16:55:07 30 4
gpt4 key购买 nike

我需要读取未通过 X509Certificate2 类发布的 x509 属性。因此我需要自己读取它的 OID 并解码 ASN.1 数据。

具体来说,我需要分别阅读“主题目录属性”>“国籍”OID 2.5.29.9 和 1.3.6.1.5.5.7.9.4。请记住,主题目录属性是一个集合,我只是真正追求公民身份。

现在我可以获得 ASN.1 数据并可以运行它 this javascript decoder并查看 OID (1.3.6.1.5.5.7.9.4) 和我追求的值(美国),但我无法弄清楚如何在 C# 中解码数据,并进一步针对 Citizenship OID。这是我到目前为止的以下代码:

var citizenship = (
from X509Extension ext in x509.Extensions
where ext.Oid.Value == "2.5.29.9"
select new AsnEncodedData(ext.Oid, ext.RawData).Format(true)
);

十六进制的原始数据是“30 12 30 10 06 08 2b 06 01 05 05 07 09 04 31 04 13 02 55 53”

[编辑] 我希望在网页中读取此值,但序列化到磁盘并不能真正满足我的需求。

最佳答案

您可以使用 Asn1Net.Reader .当您在 ASN.1 editor 中打开“RawData”(但以二进制形式保存到文件中)时或 Asn1Viewer您可以看到 ASN.1 数据的结构。下面是从 ASN.1 编辑器中截取的图片。

Structure of you citizenship ASN.1 object

然后使用 Asn1Net.Reader (nuget here),您可以使用此代码解析该值(没有进行非空检查;我在这里使用 nunit 测试)

[Test]
[TestCase("30 12 30 10 06 08 2B 06 01 05 05 07 09 04 31 04 13 02 55 53")]
public void ReadCitizenship(string example)
{
// translates hex to byte[]
var encoded = Helpers.GetExampleBytes(example);

// initialize reader
var reader = Helpers.ReaderFromData(encoded);

// parse ASN.1 object to the end and read value as byte[]
var subjDirAttributes = reader.ReadToEnd(true);

// NO Checking for null has been done
// sequence sequence set printable string
var citizenship = subjDirAttributes.ChildNodes[0].ChildNodes[0].ChildNodes[1].ChildNodes[0];

var value = citizenship.ReadContentAsPrintableString();
Assert.IsTrue(value == "US");
}

您可以使用此读取器解析任何 ASN.1 对象,如果您知道结构,则可以从中读取任何值。

更新:根据RFC 3739主题目录属性在 section 3.2.2 中定义. appendix C.3 中有一个示例.给定证书的主题目录属性如下所示。

Subject directory attributes example from RFC 3739

根据 RFC 3739 中定义的结构,此代码应解析出所有公民身份值。

[Test]
public void ReadCitizenship()
{
var exampleCert = @"MIIDEDCCAnmgAwIBAgIESZYC0jANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJE
RTE5MDcGA1UECgwwR01EIC0gRm9yc2NodW5nc3plbnRydW0gSW5mb3JtYXRpb25z
dGVjaG5payBHbWJIMB4XDTA0MDIwMTEwMDAwMFoXDTA4MDIwMTEwMDAwMFowZTEL
MAkGA1UEBhMCREUxNzA1BgNVBAoMLkdNRCBGb3JzY2h1bmdzemVudHJ1bSBJbmZv
cm1hdGlvbnN0ZWNobmlrIEdtYkgxHTAMBgNVBCoMBVBldHJhMA0GA1UEBAwGQmFy
emluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDc50zVodVa6wHPXswg88P8
p4fPy1caIaqKIK1d/wFRMN5yTl7T+VOS57sWxKcdDzGzqZJqjwjqAP3DqPK7AW3s
o7lBG6JZmiqMtlXG3+olv+3cc7WU+qDv5ZXGEqauW4x/DKGc7E/nq2BUZ2hLsjh9
Xy9+vbw+8KYE9rQEARdpJQIDAQABo4HpMIHmMGQGA1UdCQRdMFswEAYIKwYBBQUH
CQQxBBMCREUwDwYIKwYBBQUHCQMxAxMBRjAdBggrBgEFBQcJATERGA8xOTcxMTAx
NDEyMDAwMFowFwYIKwYBBQUHCQIxCwwJRGFybXN0YWR0MA4GA1UdDwEB/wQEAwIG
QDASBgNVHSAECzAJMAcGBSskCAEBMB8GA1UdIwQYMBaAFAABAgMEBQYHCAkKCwwN
Dg/+3LqYMDkGCCsGAQUFBwEDBC0wKzApBggrBgEFBQcLAjAdMBuBGW11bmljaXBh
bGl0eUBkYXJtc3RhZHQuZGUwDQYJKoZIhvcNAQEFBQADgYEAj4yAu7LYa3X04h+C
7+DyD2xViJCm5zEYg1m5x4znHJIMZsYAU/vJJIJQkPKVsIgm6vP/H1kXyAu0g2Ep
z+VWPnhZK1uw+ay1KRXw8rw2mR8hQ2Ug6QZHYdky2HH3H/69rWSPp888G8CW8RLU
uIKzn+GhapCuGoC4qWdlGLWqfpc=";

var cer = new X509Certificate2(Convert.FromBase64String(exampleCert));
var ext = cer.Extensions.OfType<X509Extension>().FirstOrDefault(p => p.Oid.Value == "2.5.29.9");

var citizenshipValues = new List<string>();

// initialize reader
var reader = Helpers.ReaderFromData(ext.RawData);

// parse ASN.1 object to the end and read value as byte[]
var subjDirAttributes = reader.ReadToEnd(true);


var citizenshipAsn1Object = subjDirAttributes.ChildNodes[0];

foreach (var node in citizenshipAsn1Object.ChildNodes)
{
var shouldBeOidNode = node.ChildNodes[0];

if (shouldBeOidNode.Identifier.Tag != Asn1Type.ObjectIdentifier) // should be oid
throw new FormatException("Invalid structure of Subject Directory Attributes");

var oidValue = shouldBeOidNode.ReadContentAsObjectIdentifier();

if (oidValue != "1.3.6.1.5.5.7.9.4")
continue;

// found it

var setNode = node.ChildNodes[1];
if (setNode.Identifier.Tag != Asn1Type.Set)
throw new FormatException("Invalid structure of Subject Directory Attributes");

foreach (var internalNode in setNode.ChildNodes)
{
var valueOfCitizenship = internalNode.ReadContentAsPrintableString();
if (valueOfCitizenship.Length != 2)
throw new FormatException("Invalid value in countryOfCitizenship. Length should be exactly 2 characters.");

citizenshipValues.Add(valueOfCitizenship);
}

// found all values, lets break
break;
}

Assert.IsTrue(citizenshipValues.Count == 1);
}

关于c# - 从 CAC/x509 证书扩展中解码 ASN.1 数据(主题目录属性 > 国籍),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29974414/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com