Maison  >  Article  >  développement back-end  >  Comment ajouter le DirName et le numéro de série à l'identifiant de clé d'autorisation X509v3

Comment ajouter le DirName et le numéro de série à l'identifiant de clé d'autorisation X509v3

王林
王林avant
2024-02-10 10:54:081011parcourir

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

l'éditeur php Strawberry vous présentera comment ajouter DirName et le numéro de série à l'identifiant de la clé d'autorisation X509v3. Dans les communications réseau, un identifiant de clé d'autorisation (X509v3) est un certificat numérique utilisé pour vérifier l'identité de la partie communicante. DirName fait référence au nom du titulaire du certificat, tandis que le numéro de série est le numéro utilisé pour identifier de manière unique le certificat. En ajoutant DirName et numéro de série, la lisibilité et le caractère unique du certificat peuvent être augmentés, et la sécurité et la fiabilité de la communication peuvent être améliorées. Ensuite, nous expliquerons en détail comment procéder.

Contenu de la question

J'essaie de générer un certificat client en utilisant openssl et go code. J'ai un script openssl qui génère un certificat avec l'extension requise et je souhaite obtenir le même résultat en utilisant le code go.

Utilisez openssl

options.ext

Le fichier options.ext utilisé par openssl contient les extensions suivantes :

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

Générer-client-cert.sh

Le script openssl que j'ai actuellement est le suivant :

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

Après avoir généré le certificat, je peux visualiser ses détails à l'aide de la commande suivante :

openssl x509 -in cert.crt -text -noout

Le certificat généré a la structure suivante :

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

Cela devrait ressembler à ceci :

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

Exécuter le code

Dans mon code go, j'utilise le package x509 pour générer le certificat. Cependant, je ne sais pas comment configurer l'extension d'identifiant de clé d'autorisation x509v3. Voici la partie pertinente de mon code go :

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

Comment ajouter le nom de répertoire et le numéro de série à l'identifiant de la clé d'autorisation x509v3 ?

Connexe

  • http://oid-info.com/get/2.5.29.35
  • https://github.com/golang/go/issues/47096 (numéro original)

Quand j'essaye ceci :

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)...)
...

Le résultat est :

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

Workaround

authoritykeyidentifiervalue 可以使用 asn1.marshal 生成。下面的演示根据 rfc 5280定义了 struct authkeyid > et utilisez cette structure pour générer la valeur :

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))
}

La valeur de codage hexadécimal est :

30548014e58e3c0c9f7a2d05958774bf68d27fe921b2fe3ea12aa4283026310f300d060355040a13064d79204f7267311330110603550403130a4d7920526f6f7420434182101a80a30c937563aac65846d75bc57c30

Les chaînes hexadécimales peuvent être créées à l'aide d'un décodeur javascript tel que asn.1  :

La démo c# suivante donne le même résultat :

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();
    }
}

Mise à jour :

Il s'agit d'une version mise à jour de gen qui inclut l'adresse e-mail :

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,
    })
}

Veuillez noter qu'oid est obsolète (voir http://oid-info.com/get/1.2.840.113549.1.9.1). .net ne l'inclut pas non plus.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer