Rumah >pembangunan bahagian belakang >Golang >Cara menambah DirName dan Nombor Siri pada Pengecam Kunci Kebenaran X509v3

Cara menambah DirName dan Nombor Siri pada Pengecam Kunci Kebenaran X509v3

王林
王林ke hadapan
2024-02-10 10:54:081045semak imbas

如何将 DirName 和序列号添加到 X509v3 授权密钥标识符

editor php Strawberry akan memperkenalkan anda cara menambah DirName dan nombor siri pada pengecam kunci kebenaran X509v3. Dalam komunikasi rangkaian, pengecam kunci kebenaran (X509v3) ialah sijil digital yang digunakan untuk mengesahkan identiti pihak yang berkomunikasi. DirName merujuk kepada nama pemegang sijil, manakala nombor siri ialah nombor yang digunakan untuk mengenal pasti sijil secara unik. Dengan menambahkan DirName dan nombor siri, kebolehbacaan dan keunikan sijil boleh ditingkatkan, dan keselamatan serta kebolehpercayaan komunikasi boleh dipertingkatkan. Seterusnya, kami akan menerangkan secara terperinci bagaimana untuk melakukan ini.

Kandungan soalan

Saya cuba menjana sijil pelanggan menggunakan kod openssl dan go. Saya mempunyai skrip openssl yang menjana sijil dengan sambungan yang diperlukan dan saya mahu mencapai hasil yang sama menggunakan kod go.

Guna openssl

options.ext

Fail options.ext yang digunakan oleh openssl mengandungi sambungan berikut:

basicconstraints=ca:false
authoritykeyidentifier=keyid,issuer
subjectkeyidentifier=hash
keyusage=digitalsignature
extendedkeyusage=clientauth

Jana-sijil-klien.sh

Skrip openssl yang saya miliki sekarang adalah seperti berikut:

openssl req \
  -newkey rsa:2048 \
  -keyout cert.crt \
  -out cert.csr \
  -nodes \
  -sha256

openssl x509 \
  -req \
  -ca ca.crt \
  -cakey ca.key \
  -in cert.csr \
  -out cert.crt \
  -days 365 \
  -cacreateserial \
  -extfile options.ext \
  -sha256

Selepas menjana sijil, saya boleh melihat butirannya menggunakan arahan berikut:

openssl x509 -in cert.crt -text -noout

Sijil yang dihasilkan mempunyai struktur berikut:

certificate:
    data:
        version: 3 (0x2)
        serial number:
            xx:xx:xx:xx:xx:xx:xx:xx
    signature algorithm: sha256withrsaencryption
        issuer: cn=xxx
        validity
            not before: jan 1 00:00:00 2023 gmt
            not after : jan 1 00:00:00 2024 gmt
        subject: cn=xxx
        subject public key info:
            public key algorithm: rsaencryption
                rsa public-key: (2048 bit)
                modulus:
                    ...
                exponent: 65537 (0x10001)
        x509v3 extensions:
            x509v3 basic constraints: 
                ca:false
            x509v3 authority key identifier: 
                dirname:cn=xxx
                serial:xx:xx:xx:xx:xx:xx:xx:xx

            x509v3 subject key identifier: 
                ...
            x509v3 key usage: 
                digital signature
            x509v3 extended key usage: 
                tls web client authentication
    signature algorithm: sha256withrsaencryption

Ia sepatutnya kelihatan seperti ini:

x509v3 authority key identifier: 
    dirname:cn=xxx
    serial:xx:xx:xx:xx:xx:xx:xx:xx

Laksanakan kod

Dalam kod go saya, saya menggunakan pakej x509 untuk menjana sijil. Walau bagaimanapun, saya tidak pasti cara menyediakan sambungan pengecam kunci kebenaran x509v3. Berikut ialah bahagian kod go saya yang berkaitan:

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/sha1"
    "crypto/x509"
    "crypto/x509/pkix"
    "encoding/asn1"
    "os"
    "time"
)

...

var cacertificate *x509.certificate
var caprivatekey *rsa.privatekey

var authoritykeyidentifiervalue []byte // how to write this?

template := &x509.certificate{
    subject: pkix.name{
        commonname: "xxx",
    },
    extraextensions: []pkix.extension{
        {
            id:    asn1.objectidentifier{2, 5, 29, 35},
            value: authoritykeyidentifiervalue,
        },
    },
    keyusage:              x509.keyusagedigitalsignature,
    extkeyusage:           []x509.extkeyusage{x509.extkeyusageclientauth},
    notbefore:             time.now(),
    notafter:              time.now().adddate(0, 0, 365),
    isca:                  false,
    basicconstraintsvalid: true,
}

privatekey, err := rsa.generatekey(rand.reader, 2048)
if err != nil {
    // err
}

certificatebytes, err := x509.createcertificate(rand.reader, template, cacertificate, &privatekey.publickey, caprivatekey)
if err != nil {
    // err
}

// out

Bagaimana untuk menambah nama dan nombor siri pada pengecam kunci kebenaran x509v3?

Berkaitan

  • http://oid-info.com/get/2.5.29.35
  • https://github.com/golang/go/issues/47096 (isu asal)

Apabila saya mencuba ini:

var capublickeybytes []byte
publickeyhash := (sha1.sum(capublickeybytes))[:]

var dirname string

authoritykeyidentifiervalue := []byte{0x30, len(publickeyhash)}
authoritykeyidentifiervalue = append(authoritykeyidentifiervalue, publickeyhash...)
authoritykeyidentifiervalue = append(authoritykeyidentifiervalue, 0x80, len(dirname))
authoritykeyidentifiervalue = append(authoritykeyidentifiervalue, []byte(dirname)...)
...

Hasilnya ialah:

X509v3 Authority Key Identifier:
    0....0...<....).!.r[..F.....".hCN=xxx.....$...D

Penyelesaian

authoritykeyidentifiervalue 可以使用 asn1.marshal 生成。下面的演示根据 rfc 5280定义了 struct authkeyid > dan gunakan struktur ini untuk menjana nilai:

package main

import (
    "crypto/x509"
    "crypto/x509/pkix"
    "encoding/asn1"
    "encoding/hex"
    "encoding/pem"
    "fmt"
    "math/big"
)

// rfc 5280, a.2. implicitly tagged module, 1988 syntax
//
//  authoritykeyidentifier ::= sequence {
//      keyidentifier             [0] keyidentifier            optional,
//      authoritycertissuer       [1] generalnames             optional,
//      authoritycertserialnumber [2] certificateserialnumber  optional }
//      -- authoritycertissuer and authoritycertserialnumber must both
//      -- be present or both be absent
type authkeyid struct {
    keyidentifier             []byte       `asn1:"optional,tag:0"`
    authoritycertissuer       generalnames `asn1:"optional,tag:1"`
    authoritycertserialnumber *big.int     `asn1:"optional,tag:2"`
}

// rfc 5280, a.2. implicitly tagged module, 1988 syntax
//
//  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 }
type generalnames struct {
    name []pkix.rdnsequence `asn1:"tag:4"`
}

func gen(issuer *x509.certificate) ([]byte, error) {
    return asn1.marshal(authkeyid{
        keyidentifier:             issuer.subjectkeyid,
        authoritycertissuer:       generalnames{name: []pkix.rdnsequence{issuer.issuer.tordnsequence()}},
        authoritycertserialnumber: issuer.serialnumber,
    })
}

func main() {
    cacert := `-----begin certificate-----
miibotccauegawibagiqgocjdjn1y6rgwebxw8v8mdakbggqhkjopqqdajammq8w
dqydvqqkewznesbpcmcxezarbgnvbamtck15ifjvb3qgq0ewhhcnmjmwnte2mtqy
ntuwwhcnmjmwnte3mtuyntuwwjammq8wdqydvqqkewznesbpcmcxezarbgnvbamt
ck15ifjvb3qgq0ewwtatbgcqhkjopqibbggqhkjopqmbbwncaarzqz2ka7fi6w9/
32sjhtajrke+vqyx7hfnmtx1inpbajnfvonf2silh5nqms50jpnvgivehtbfl0a0
dcurufhno1cwvtaobgnvhq8baf8ebamcaqqwewydvr0lbawwcgyikwybbquhawew
dwydvr0taqh/bauwaweb/zadbgnvhq4efgqu5y48dj96lqwvh3s/anj/6sgy/j4w
cgyikozizj0eawidsaawrqihanqdh6sgz014wvfdh0zhbeghdb2tqxzujxa7ymo3
80unaiapzp4wlzqlb+j4fipnep+txru01jgfaksml2yhv3mewg==
-----end certificate-----`
    b, _ := pem.decode([]byte(cacert))
    if b == nil {
        panic("couldn't decode test certificate")
    }
    issuer, err := x509.parsecertificate(b.bytes)
    if err != nil {
        panic(err)
    }

    authoritykeyidentifiervalue, err := gen(issuer)
    if err != nil {
        panic(err)
    }
    fmt.println(hex.encodetostring(authoritykeyidentifiervalue))
}

Nilai pengekodan heksadesimal ialah:

30548014e58e3c0c9f7a2d05958774bf68d27fe921b2fe3ea12aa4283026310f300d060355040a13064d79204f7267311330110603550403130a4d7920526f6f7420434182101a80a30c937563aac65846d75bc57c30

Rentetan hex boleh dibuat menggunakan penyahkod javascript seperti asn.1 :

Demo c# berikut memberikan hasil yang sama:

using system.security.cryptography.x509certificates;
using system.text;

internal class program
{
    private static void main(string[] args)
    {
        var certbytes = encoding.ascii.getbytes(@"-----begin certificate-----
miibotccauegawibagiqgocjdjn1y6rgwebxw8v8mdakbggqhkjopqqdajammq8w
dqydvqqkewznesbpcmcxezarbgnvbamtck15ifjvb3qgq0ewhhcnmjmwnte2mtqy
ntuwwhcnmjmwnte3mtuyntuwwjammq8wdqydvqqkewznesbpcmcxezarbgnvbamt
ck15ifjvb3qgq0ewwtatbgcqhkjopqibbggqhkjopqmbbwncaarzqz2ka7fi6w9/
32sjhtajrke+vqyx7hfnmtx1inpbajnfvonf2silh5nqms50jpnvgivehtbfl0a0
dcurufhno1cwvtaobgnvhq8baf8ebamcaqqwewydvr0lbawwcgyikwybbquhawew
dwydvr0taqh/bauwaweb/zadbgnvhq4efgqu5y48dj96lqwvh3s/anj/6sgy/j4w
cgyikozizj0eawidsaawrqihanqdh6sgz014wvfdh0zhbeghdb2tqxzujxa7ymo3
80unaiapzp4wlzqlb+j4fipnep+txru01jgfaksml2yhv3mewg==
-----end certificate-----");

        using var issuer = new x509certificate2(certbytes);
        var e = x509authoritykeyidentifierextension.createfromcertificate(issuer, true, true);
        console.writeline(bytearraytohex(e.rawdata));
    }

    private static string bytearraytohex(byte[] bytes)
    {
        var builder = new stringbuilder(bytes.length * 2);

        for (int i = 0; i < bytes.length; i++)
        {
            builder.append($"{bytes[i]:x2}");
        }

        return builder.tostring();
    }
}

Kemas kini:

Ini ialah versi terkini gen yang termasuk alamat e-mel:

func gen(issuer *x509.Certificate) ([]byte, error) {
    rdnSequence := issuer.Issuer.ToRDNSequence()
    if len(issuer.EmailAddresses) > 0 {
        oidEmail := asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}
        emails := make([]pkix.AttributeTypeAndValue, len(issuer.EmailAddresses))
        for i, value := range issuer.EmailAddresses {
            emails[i].Type = oidEmail
            emails[i].Value = value
        }
        rdnSequence = append(rdnSequence, emails)
    }

    return asn1.Marshal(authKeyId{
        KeyIdentifier:             issuer.SubjectKeyId,
        AuthorityCertIssuer:       generalNames{Name: []pkix.RDNSequence{rdnSequence}},
        AuthorityCertSerialNumber: issuer.SerialNumber,
    })
}

Sila ambil perhatian bahawa oid telah ditamatkan (lihat http://oid-info.com/get/1.2.840.113549.1.9.1). .net juga tidak memasukkannya.

Atas ialah kandungan terperinci Cara menambah DirName dan Nombor Siri pada Pengecam Kunci Kebenaran X509v3. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam