关于在pyasn1中为nameRelativeToCRLIssuer添加<host>和<attrdesc>属性的技术咨询
嘿,我最近研究RFC5280里关于CRL的LDAP URI规范时,刚好碰到了类似问题,先给你贴一段RFC里的核心要求:
When the LDAP URI scheme [RFC4516] is used, the URI MUST include a field containing the distinguished name of the entry holding the CRL, MUST include a single
that contains an appropriate attribute description for the attribute that holds the CRL [RFC4523], and SHOULD include a (e.g., ldap://ldap.example.com/cn=example CA,dc=example,dc=com?certificateRevocationList;binary). Omitting the (e.g., ldap:///cn=CA,dc=example,dc=com?authorityRevocation...)
先给你理清楚关键概念:nameRelativeToCRLIssuer在标准RFC5280的ASN.1结构里,本质就是相对DN序列,本身并不包含nameRelativeToCRLIssuer的内置属性。下面给你两种处理方案:
方案一:标准兼容的正确姿势(推荐)
按照RFC要求,你需要把nameRelativeToCRLIssuer对应的相对DN、uniformResourceIdentifier字段传递,这样所有遵循标准的解析器都能识别。
具体用pyasn1实现的代码示例:
from pyasn1_modules import rfc5280 from pyasn1.type import univ, char # 1. 构造nameRelativeToCRLIssuer对应的相对DN rdn = rfc5280.RelativeDistinguishedName() # 添加属性类型和值(这里以CN=example CA为例) ava = rfc5280.AttributeTypeAndValue() ava['type'] = univ.ObjectIdentifier('2.5.4.3') # OID对应CN属性 ava['value'] = char.UTF8String('example CA') rdn.setComponentByPosition(0, ava) rdn_seq = rfc5280.RDNSequence() rdn_seq.setComponentByPosition(0, rdn) # 2. 准备<host>和<attrdesc>内容 host = "ldap.example.com" attrdesc = "certificateRevocationList;binary" # 把相对DN转成URI编码的字符串(这里直接用编码后的形式示例) relative_dn_uri = "cn=example%20CA,dc=example,dc=com" # 3. 拼接成完整的LDAP URI ldap_uri = f"ldap://{host}/{relative_dn_uri}?{attrdesc}" # 4. 构造CRL分布点并设置URI dist_point = rfc5280.DistributionPoint() dist_point['distributionPoint']['uniformResourceIdentifier'] = char.IA5String(ldap_uri)
这种方式完全符合RFC5280的要求,不用担心兼容性问题。
方案二:自定义扩展结构(不推荐,仅特殊场景用)
如果你确实需要把nameRelativeToCRLIssuer相关的结构里,那只能自定义扩展ASN.1类型——但要注意,这种自定义结构不兼容标准RFC,其他系统大概率解析不了。
代码示例如下:
from pyasn1_modules import rfc5280 from pyasn1.type import univ, char, namedtype # 自定义扩展的相对DN结构,额外包含host和attrdesc字段 class ExtendedRelativeDN(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType("standardRdn", rfc5280.RelativeDistinguishedName()), namedtype.NamedType("host", char.IA5String()), namedtype.NamedType("attrdesc", char.IA5String()) ) # 使用自定义结构 extended_rdn = ExtendedRelativeDN() # 给标准Rdn字段赋值(和方案一的构造方式一致) std_rdn = rfc5280.RelativeDistinguishedName() ava = rfc5280.AttributeTypeAndValue() ava['type'] = univ.ObjectIdentifier('2.5.4.3') ava['value'] = char.UTF8String('example CA') std_rdn.setComponentByPosition(0, ava) extended_rdn['standardRdn'] = std_rdn # 设置自定义的host和attrdesc extended_rdn['host'] = char.IA5String("ldap.example.com") extended_rdn['attrdesc'] = char.IA5String("certificateRevocationList;binary")
总结一下,优先用方案一,这是符合标准的正确做法;方案二只适合你有特殊定制需求,且能控制两端解析逻辑的场景。
备注:内容来源于stack exchange,提问作者happy one

