如何使用任意或已弃用的扩展名签署证书

How to sign cert with an arbitrary or deprecated extension

例如,假设我想签署一个具有任意或已弃用扩展名的证书(例如 nsCertType):https://www.openssl.org/docs/manmaster/man5/x509v3_config.html

我相信我应该按照下面的方式将任意扩展添加为证书的一部分,但是您如何/在哪里发现 asn1 对象标识符?我已经阅读了更多我今天愿意承认的文档,但仍然感到困惑。

tmpl := &x509.Certificate{
    SerialNumber:          big.NewInt(time.Now().Unix()*1000),
    Subject:               pkix.Name{CommonName: "edgeproxy", Organization: []string{"edgeproxy"}},
    NotBefore:             now,
    NotAfter:              now.Add(caMaxAge),
    ExtraExtensions:       []pkix.Extension{
        {
            Id: asn1.ObjectIdentifier{}, //what goes here
            Critical: false,
            []byte("sslCA"),
        },
    },
    ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth,x509.ExtKeyUsageClientAuth,x509.ExtKeyUsageEmailProtection, x509.ExtKeyUsageTimeStamping, x509.ExtKeyUsageMicrosoftCommercialCodeSigning, x509.ExtKeyUsageMicrosoftServerGatedCrypto, x509.ExtKeyUsageNetscapeServerGatedCrypto} ,
    KeyUsage:              x509.KeyUsageCRLSign | x509.KeyUsageCertSign,
    IsCA:                  true,
    BasicConstraintsValid: true,
}

在 python 中,我会这样做,但不知道如何将其移植到 go 中(这就是我在一天结束时所做的):

    OpenSSL.crypto.X509Extension(
        b"nsCertType",
        False,
        b"sslCA"
    ), 

前往 https://golang.org/src/encoding/asn1/asn1.go 定义的资源:

// An ObjectIdentifier represents an ASN.1 OBJECT IDENTIFIER.

type ObjectIdentifier []int

所以对象标识符(简称OID)是一个整数数组。 asn1 模块有解析它们的方法,比如 parseObjectIdentifier.

这是您需要放在 Id: 属性之后的结构。

但是现在你需要找到你想要的OID。

虽然难以阅读,但 OpenSSL 源代码可以向您显示 X.400/X.500/X.509 世界中许多事物的 OID,或者至少是 OpenSSL 已知的那些。

如果你去https://github.com/openssl/openssl/blob/1aec7716c1c5fccf605a46252a46ea468e684454/crypto/objects/obj_dat.h

并在 nsCertType 上搜索,您会得到:

{"nsCertType", "Netscape Cert Type", NID_netscape_cert_type, 9, &so[407]},

so 是之前定义的,如果你跳到它的第 407th 项,你会看到:

    0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01,  /* [  407] OBJ_netscape_cert_type */

并在同一文件中对 OBJ_netscape_cert_type 进行最终搜索得到:

  71,    /* OBJ_netscape_cert_type           2 16 840 1 113730 1 1 */

表示对应的OID为2.16.840.1.113730.1.1

或者您可以解码上面描述此 OID 的整数列表(有关详细信息,请参阅 How does ASN.1 encode an object identifier?)。

  • 第一个0x609610所以2*40 + 16,也就是说OID以2.16.[=98=开头]
  • 然后彼此为"base128"形式:如果最高有效位为1,则将所有后续数字的7个最低有效位组合在一起,直到最高有效位为0
  • 0x86100001102 所以必须与 0x48 又名 010010002 所以实际上是 000011010010002 或者 84010
  • 0x01 小于 128 所以它本身,1
  • 0x86 仍然是 100001102 但必须与两者配对 0xF8 (111110002) 和 0x42 (010000102 因为第一位是 0 我们就停在这里) 所以 0000110111100010000102 一共或 11373010
  • 最后两个0x01是他们自己,1

所以我们又得到了2.16.840.1.113730.1.1

您可以在一些在线 OID 浏览器上仔细检查它,如下所示: http://oid-info.com/cgi-bin/display?oid=2.16.840.1.113730.1.1&action=display 给出了以下描述:

Netscape certificate type (a Rec. ITU-T X.509 v3 certificate extension used to identify whether the certificate subject is a Secure Sockets Layer (SSL) client, an SSL server or a Certificate Authority (CA))

然后您甚至可以浏览各种弧线,例如 netscape 或其他弧线,以找出其他 OID。

您还可以获得完整的 ASN.1 表示法:

{joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730) cert-ext(1) cert-type(1)}