You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法解析OID友好名时,如何读取X.500相对辨别名?

处理X.500 RDN中的非通用标识符(俄文/英文INN、OGRN等)的跨平台解析问题

问题描述

我在处理数字签名时需要读取X.500相对辨别名(RDN),但主体名称包含俄罗斯特有的非通用标识符——比如俄文的ИНН、ОГРН、СНИЛС,或对应的英文INN、OGRN、SNILS等,遇到了以下解析问题:

  • 从CAdES容器通过SignedCms读取X500DistinguishedName对象时,直接对比自定义OID常量就能正常处理,没有问题
  • 但如果是单独提供的友好名字符串,用X500DistinguishedName(string)构造函数解析时,会出现跨环境兼容性问题:
    1. 俄文名称在Windows本地能解析,但Linux容器等生产环境会抛出System.Security.Cryptography.CryptographicException: No OID value matches this name.异常
    2. 英文名称因系统区域设置差异,本地机器也无法解析
    3. 部分环境中部分OID没有对应的友好名,无论俄文还是英文名称都无法匹配OID,导致解析失败

我想知道:

  1. 是否存在可以跳过自动OID查找、以非严格方式读取X.500 RDN的API?要求能正确解析格式(分号、引号、换行等),同时不受OID匹配限制
  2. 有没有其他解决方案,比如添加多语言OID查找源?

我考虑过手动解析字符串,但担心自己写的解析逻辑有格式错误;也试过在传入构造函数前把友好名替换成OID.<identifier>,但怕误替换RDN的值。


示例

CAdES容器PEM格式

MIIHmAYJKoZIhvcNAQcCoIIHiTCCB4UCAQExDjAMBggqhQMHAQECAgUAMB8GCSqG
SIb3DQEHAaASJIAEDEhlbGxvIGd1eXMNCgAAoIIE9zCCBPMwggSgoAMCAQICExIA
ZO+nLuft0G9PuJwAAgBk76cwCgYIKoUDBwEBAwIwfzEjMCEGCSqGSIb3DQEJARYU
c3VwcG9ydEBjcnlwdG9wcm8ucnUxCzAJBgNVBAYTAlJVMQ8wDQYDVQQHEwZNb3Nj
b3cxFzAVBgNVBAoTDkNSWVBUTy1QUk8gTExDMSEwHwYDVQQDExhDUllQVE8tUFJP
IFRlc3QgQ2VudGVyIDIwHhcNMjQwODI3MDczODM1WhcNMjQxMDI3MDc0ODM1WjCC
AekxFTATBgUqhQNkBBIKMDkwNjIwOTQ5OTEWMBQGBSqFA2QDEgs2OTQ2Mzg3NDU2
OTEYMBYGBSqFA2QBEg01MDQ1MjIyNjUzMDg2MRowGAYIKoUDA4EDAQESDDg5NTAx
NzQ4NDc1MDEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTELMAkGA1UE
BhMCUlUxHDAaBgNVBAgMEzc3INCzLiDQnNC+0YHQutCy0LAxHDAaBgNVBAcME9Ch
0LDQvdC60YIt0KLQtdGB0YIxMzAxBgNVBAoMKtCe0J7QniAi0KLQtdGB0YLQvtCy
0LDRjyDQutC+0LzQv9Cw0L3QuNGPIjEtMCsGA1UECQwk0J3QsNCxLiDQotC10YHR
gtC+0LLRgdC60LDRjywg0LQuIDI5MTIwMAYDVQQMDCnQotC10YHRgtC+0LLRi9C5
INGA0YPQutC+0LLQvtC00LjRgtC10LvRjDE0MDIGA1UEKgwr0JDQstGA0LXQu9C4
0Lkg0JrQvtC90YHRgtCw0L3RgtC40L3QvtCy0LjRhzEVMBMGA1UEBAwM0KLQtdGB
0YLQvtCyMTMwMQYDVQQDDCrQntCe0J4gItCi0LXRgdGC0L7QstCw0Y8g0LrQvtC8
0L/QsNC90LjRjyIwZjAfBggqhQMHAQEBATATBgcqhQMCAiMBBggqhQMHAQECAgND
AARAJ5Tnn5/Y9VIaUPVExWxKWwLQiUg+EmRs1qzeCyAgNu1QiM1LZ9xDWnTNX7x7
dL0pihdqn7lRwQD6qQ7jnRYSoaOCAYAwggF8MA4GA1UdDwEB/wQEAwIE8DAdBgNV
HSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwHQYDVR0OBBYEFOCaVoLHoz3yK5JH
vJ9Q/dChqvJ5MB8GA1UdIwQYMBaAFBPuDprx4ItKrhkW78vExS2pGTcdMFwGA1Ud
HwRVMFMwUaBPoE2GS2h0dHA6Ly90ZXN0Y2EuY3J5cHRvcHJvLnJ1L0NlcnRFbnJv
bGwvQ1JZUFRPLVBSTyUyMFRlc3QlMjBDZW50ZXIlMjAyKDIpLmNybDCBrAYIKwYB
BQUHAQEEgZ8wgZwwZAYIKwYBBQUHMAKGWGh0dHA6Ly90ZXN0Y2EuY3J5cHRvcHJv
LnJ1L0NlcnRFbnJvbGwvdGVzdC1jYS0yMDE0X0NSWVBUTy1QUk8lMjBUZXN0JTIw
Q2VudGVyJTIwMigyKS5jcnQwNAYIKwYBBQUHMAGGKGh0dHA6Ly90ZXN0Y2EuY3J5
cHRvcHJvLnJ1L29jc3Avb2NzcC5zcmYwCgYIKoUDBwEBAwIDQQBDe8OvSTVPAO5d
t05bBTb/8496udYLS60cuC3Teq5Vr+zj77fx8+TRjpvxO7K2n5cJEvw5owSXYq2+
vH4qP5VIMYICUjCCAk4CAQEwgZYwfzEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBj
cnlwdG9wcm8ucnUxCzAJBgNVBAYTAlJVMQ8wDQYDVQQHEwZNb3Njb3cxFzAVBgNV
BAoTDkNSWVBUTy1QUk8gTExDMSEwHwYDVQQDExhDUllQVE8tUFJPIFRlc3QgQ2Vu
dGVyIDICExIAZO+nLuft0G9PuJwAAgBk76cwDAYIKoUDBwEBAgIFAKCCAVIwGAYJ
KoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjQwODI3MDc1
MTMxWjAvBgkqhkiG9w0BCQQxIgQgv3iAK5O+y+rh2rJDoPstHwMYFPL/HfQ2LqxR
rm49WNYwgeYGCyqGSIb3DQEJEAIvMYHWMIHTMIHQMIHNMAoGCCqFAwcBAQICBCCN
uZ99TEIPpysfzEgjaW0/vTrWmR5lHCn/gv42o6BOQjCBnDCBhKSBgTB/MSMwIQYJ
KoZIhvcNAQkBFhRzdXBwb3J0QGNyeXB0b3Byby5ydTELMAkGA1UEBhMCUlUxDzAN
BgNVBAcTBk1vc2NvdzEXMBUGA1UEChMOQ1JZUFRPLVBSTyBMTEMxITAfBgNVBAMT
GENSWVBUTy1QUk8gVGVzdCBDZW50ZXIgMgITEgBk76cu5+3Qb0+4nAACAGTvpzAK
BggqhQMHAQEBAQRAueXJ91COJM0XPnR5ZUmyj0Qsf+ltTswNGf2ZGXYL5Lw/AEVR
kc1R7TnjhVBxKCGfw16WVZ6v2r+08AE4N3fybw==

俄文主体名称字符串

CN="ООО ""Тестовая компания""", SN=Тестов, G=Аврелий Константинович, Т=Тестовый руководитель, STREET="Наб. Тестовская, д. 29", O="ООО ""Тестовая компания""", L=Санкт-Тест, S=77 г. Москва, C=RU, E=test@example.com, ИНН=895017484750, ОГРН=5045222653086, СНИЛС=69463874569, ИНН ЮЛ=0906209499

英文主体名称字符串

CN="ООО ""Тестовая компания""", SN=Тестов, G=Аврелий Константинович, Т=Тестовый руководитель, STREET="Наб. Тестовская, д. 29", O="ООО ""Тестовая компания""", L=Санкт-Тест, S=77 г. Москва, C=RU, E=test@example.com, INN=895017484750, OGRN=5045222653086, SNILS=69463874569, INNLE=0906209499

解决方案

方案1:自定义OID映射,扩展系统OID解析表

.NET允许通过Oid.RegisterCustomOid方法注册自定义OID与友好名的映射,让系统直接识别俄文/英文的非通用标识符,无需修改原始字符串。

俄罗斯常用标识符的标准OID如下:

  • ИНН/INN/ИНН ЮЛ/INNLE: 1.2.643.100.1(法人INN靠值的长度区分)
  • ОГРН/OGRN: 1.2.643.100.2
  • СНИЛС/SNILS: 1.2.643.100.3

在应用启动时注册映射:

// 注册俄文友好名
Oid.RegisterCustomOid(new Oid("1.2.643.100.1", "ИНН"));
Oid.RegisterCustomOid(new Oid("1.2.643.100.2", "ОГРН"));
Oid.RegisterCustomOid(new Oid("1.2.643.100.3", "СНИЛС"));
Oid.RegisterCustomOid(new Oid("1.2.643.100.1", "ИНН ЮЛ"));

// 注册英文友好名
Oid.RegisterCustomOid(new Oid("1.2.643.100.1", "INN"));
Oid.RegisterCustomOid(new Oid("1.2.643.100.2", "OGRN"));
Oid.RegisterCustomOid(new Oid("1.2.643.100.3", "SNILS"));
Oid.RegisterCustomOid(new Oid("1.2.643.100.1", "INNLE"));

注册后,X500DistinguishedName(string)构造函数就能在跨环境下正确解析这些标识符。

方案2:使用非严格解析的第三方库

如果不想依赖系统OID映射,可以用专注于ASN.1解析的第三方库SysadminsLV.Asn1Parser,它支持非严格模式读取DN,不强制OID匹配,直接解析结构。

使用示例:

using SysadminsLV.Asn1Parser;
using SysadminsLV.PKI.Cryptography.X509Certificates;

var dnString = "CN=\"ООО \"\"Тестовая компания\"\"\", ИНН=895017484750, ОГРН=5045222653086";
var dn = new X500DistinguishedName(dnString);
// 遍历所有RDN条目
foreach (var rdn in dn.RawData.DecodeX500Rdn()) {
    foreach (var attr in rdn.Attributes) {
        Console.WriteLine($"{attr.Oid.FriendlyName ?? attr.Oid.Value}: {attr.Value}");
    }
}

即使OID没有友好名,库也会保留OID值和属性值,不会抛出异常。

方案3:安全替换友好名为OID字符串(避免误替换)

如果必须使用系统的X500DistinguishedName构造函数,可以用正则表达式仅替换RDN的属性名部分,避免误修改属性值:

using System.Text.RegularExpressions;

string ReplaceFriendlyNamesWithOids(string dnString) {
    var replacements = new Dictionary<string, string> {
        {"ИНН", "1.2.643.100.1"},
        {"ОГРН", "1.2.643.100.2"},
        {"СНИЛС", "1.2.643.100.3"},
        {"ИНН ЮЛ", "1.2.643.100.1"},
        {"INN", "1.2.643.100.1"},
        {"OGRN", "1.2.643.100.2"},
        {"SNILS", "1.2.643.100.3"},
        {"INNLE", "1.2.643.100.1"}
    };

    foreach (var kvp in replacements) {
        // 仅匹配开头或逗号后的属性名,确保只替换属性名部分
        dnString = Regex.Replace(dnString, $@"(^|, ){Regex.Escape(kvp.Key)}=", $"$1{kvp.Value}=");
    }
    return dnString;
}

// 使用示例
var originalDn = "CN=\"ООО \"\"Тестовая компания\"\"\", ИНН=895017484750";
var modifiedDn = ReplaceFriendlyNamesWithOids(originalDn);
var x500Dn = new X500DistinguishedName(modifiedDn);

内容的提问来源于stack exchange,提问作者Dmitry Frolov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 01:02:03