ASN1 结构代理语法

ASN1 结构代理语法

我想将 Procuration 扩展添加到我的证书中。因此我使用工具 XCA,它使用 OpenSSL conf 来创建证书。

这是 ASN1 结构:

ProcurationSyntax ::= SEQUENCE
{
    country [1] EXPLICIT PrintableString OPTIONAL
    typeOfSubstitution[2] EXPLICIT DirectoryString OPTIONAL
    signingFor [3] EXPLICIT SigningFor
}

SigningFor ::= CHOICE
{
    thirdPerson GeneralName
    certRef IssuerSerial
}

IssuerSerial ::= SEQUENCE
{
    issuer GeneralNames
    serial CertificateSerialNumber
    issuerUID UniqueIdentifier OPTIONAL
}

现在我想通过 openssl conf 将此扩展添加为任意扩展(https://www.openssl.org/docs/man1.1.0/apps/x509v3_config.html#ARBITRARY-EXTENSIONS

我的代码看起来是这样的,但我坚持其余部分 - 第三人称的东西:

1.3.36.8.3.2=ASN1:SEQUENCE:proc_sect

[proc_sect]
country=EXPLICIT:1,IA5STRING:EN
typeOfSubtitution=EXPLICIT:2,IA5STRING:My Type of Substitution
thirdPerson OR certRef=EXPLICIT:3,TODO

因此,如果有人可以提供缺失的其余部分(即 thirdPerson 和 certRef)的有效示例代码,那将会非常有帮助。

答案1

整个事情的最小例子

1.3.36.8.3.2 = ASN1:SEQUENCE:procuration

[procuration]
country            = EXP:1, PRINTABLE:EN
typeOfSubstitution = EXP:2, UTF8:My Type of Substitution
thirdPerson        = EXP:3, EXP:0, EXP:1, IA5:[email protected]

为了获得测试用例,我使用以下 ASN.1 值符号编译了asn1-游乐场

procuration ProcurationSyntax ::= {
  country "EN",
  typeOfSubstitution utf8String : "My Type of Substitution",
  signingFor thirdPerson rfc822Name : "[email protected]"
}

我使用了这个模式:

-- RFC 5280 Appendix A.1
PKIX1Explicit88 DEFINITIONS EXPLICIT TAGS ::=
BEGIN
    Name ::= CHOICE { -- only one possibility for now --
          rdnSequence  RDNSequence }

    RDNSequence ::= SEQUENCE OF RelativeDistinguishedName

    DistinguishedName ::= RDNSequence

    RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue

    AttributeTypeAndValue ::= SEQUENCE {
            type    AttributeType,
            value   AttributeValue }

    AttributeType ::= OBJECT IDENTIFIER

    AttributeValue ::= ANY -- DEFINED BY AttributeType

    DirectoryString ::= CHOICE {
          teletexString       TeletexString   (SIZE (1..MAX)),
          printableString     PrintableString (SIZE (1..MAX)),
          universalString     UniversalString (SIZE (1..MAX)),
          utf8String          UTF8String      (SIZE (1..MAX)),
          bmpString           BMPString       (SIZE (1..MAX)) }

    CertificateSerialNumber  ::=  INTEGER

    UniqueIdentifier  ::=  BIT STRING
END

-- RFC 5280 Appendix A.2
PKIX1Implicit88 DEFINITIONS IMPLICIT TAGS ::=
BEGIN
    IMPORTS
        DirectoryString,
        Name
        FROM PKIX1Explicit88;

    GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName

    GeneralName ::= CHOICE {
         otherName                 [0]  AnotherName,
         rfc822Name                [1]  IA5String,
         dNSName                   [2]  IA5String,
         --x400Address               [3]  ORAddress,
         directoryName             [4]  Name,
         --ediPartyName              [5]  EDIPartyName,
         uniformResourceIdentifier [6]  IA5String,
         iPAddress                 [7]  OCTET STRING,
         registeredID              [8]  OBJECT IDENTIFIER }

    AnotherName ::= SEQUENCE {
         type-id    OBJECT IDENTIFIER,
         value      [0] EXPLICIT ANY DEFINED BY type-id }
END

-- Foo
Procuration-Schema DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
    IMPORTS
        CertificateSerialNumber, DirectoryString, UniqueIdentifier FROM PKIX1Explicit88
        GeneralName, GeneralNames FROM PKIX1Implicit88;

    ProcurationSyntax ::= SEQUENCE
    {
        country [1] EXPLICIT PrintableString OPTIONAL,
        typeOfSubstitution[2] EXPLICIT DirectoryString OPTIONAL,
        signingFor [3] EXPLICIT SigningFor
    }

    SigningFor ::= CHOICE
    {
        thirdPerson GeneralName,
        certRef IssuerSerial
    }

    IssuerSerial ::= SEQUENCE
    {
        issuer GeneralNames,
        serial CertificateSerialNumber,
        issuerUID UniqueIdentifier OPTIONAL
    }
END

这个 OpenSSL.cfg 也可能有效:

[v3]
subjectAltName = @alt_names
1.3.36.8.3.2 = ASN1:SEQUENCE:procuration

[alt_names]
DNS.1 = ldap.example.com
DNS.2 = ldap1.example.com

[procuration]
country = EXPLICIT:1, PRINTABLE:EN
typeOfSubstitution = EXPLICIT:2, UTF8:My Type of Substitution
thirdPerson = EXPLICIT:3, EXPLICIT:0, IMP:1, IA5:[email protected]
#certRef = EXPLICIT:3, IMP:1, SEQUENCE:cert_ref

#[cert_ref]
#issuer = IMP:0, SEQUENCE:proc_certref_issuer
#serial = IMP:1, INTEGER:12345

#[proc_certref_issuer]
#1 = IMP:1, IA5:bar
#2 = EXP:4, IMP:1, IMP:16U, FORMAT:HEX, #OCTETSTRING:3035310b30090603550406130245553110300e060355040a0c074578616d706c653114301206035504030c0b4672656420466f6f626172

[过程]

注意各种不同的字符串类型。

country定义为 PrintableString (它只是一个子集IA5String 的):

country = EXPLICIT:1, PRINTABLE:EN

typeOfSubstitution定义为目录字符串,它是 TeletexString、PrintableString、UniversalString、UTF8String 或 BMPString 之间的选择 - 其中一些是 IA5String 的子集,其他是超集,但实际的IA5String 实际上并不允许。因此,让我们使用 UTF-8 Unicode:

;                            ┌── tag for ProcurationSyntax sequence
;                            ¦
typeOfSubstitution = EXPLICIT:2, UTF8:My Type of Substitution

(在线 asn1step 说 DirectoryString 选择没有单独的标签;我猜这是因为所有可能的选择都已经有独特的“通用”标签。)

因为signingForthirdPerson是vs之间的选择certRef,你可以包括一个或者另一个,由您来选择合适的类型。

thirdPerson定义为 [0]通用名称,这是各种其他类型之间的选择——与 subjectAltName 扩展中的选择完全相同。例如,您可以包含电子邮件地址(格式为 rfc822Name [1] IA5String):

;                ┌── tag for ProcurationSyntax sequence
;                │      ┌── tag for SigningFor choice
;                │      │      ┌── tag for GeneralName choice
;                ¦      ¦      ¦
thirdPerson = EXP:3, EXP:0, EXP:1, IA5:[email protected]

或者 dNSName (定义为 [2] IA5String):

thirdPerson = EXP:3, EXP:0, EXP:2, IA5:example.com

(或者包含小猫的 MPEG 视频的 otherName。)

如果你想选择一个certRef,这是一个完整的嵌套序列。

;            ┌── tag for ProcurationSyntax sequence
;            │      ┌── tag for SigningFor choice
;            ¦      ¦
certRef = EXP:3, IMP:1, SEQUENCE:proc_certref

[proc_certref]

在该[proc_certref]部分内,您必须至少定义issuerserial

issuer通用名称,它是 GeneralName 值的序列。

issuer = IMP:0, SEQUENCE:proc_certref_issuer
;           └── tag for IssuerSerial sequence

serial证书序列号只是一个整数。

serial = IMP:1, INTEGER:0x123456

笔记:我非常不确定这些是否应该有隐式标签。

[proc_certref_issuer]

太棒了。又一个部分,还有通用名称仅此而已。幸运的是,只有一个。不幸的是,有超过零个。

最简单的有效值是单个 GeneralName,它只是一个 rfc822Name 或一个 dNSName(都是 IA5String):

issuer.0 = IMP:1, IA5:[email protected]
;             └── tag for GeneralName choice

…实际上,我们已经做过一次 directoryName 了,不是吗?因为这issuer.0是一个 GeneralName,所以它使用与admissionAuthority你的以前的扩展(具有相同的标记和所有内容)——所以我不会再次尝试在这里实现它。

相关内容