如何在Go中生成任意长度的x509证书链

问题描述 投票:0回答:1

我正在尝试生成

x509
任意长度的证书链,但在尝试验证它时惨败。

验证失败并显示

x509: certificate signed by unknown authority

这是尝试执行此操作的代码。它首先生成一些根证书,然后将其添加到用于验证的证书池中

func main() {
    log.SetFlags(log.LstdFlags | log.Lshortfile)
    count := 3

    rootKeys, err := makeRootKeys(count)
    if err != nil {
        log.Fatal(err)
    }

    rootCerts, err := makeRootCerts(rootKeys)
    if err != nil {
        log.Fatal(err)
    }

    rootPool := x509.NewCertPool()
    for _, rootCert := range rootCerts {
        rootPool.AddCert(rootCert)
    }

    for i := 1; i < count; i++ {
        chain, err := makeChain(rootKeys[i], i)
        if err != nil {
            log.Fatal(err)
        }

        opts := x509.VerifyOptions{
            Roots:     rootPool,
            KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
        }

        leaf := chain[0]
        if opts.Intermediates == nil {
            opts.Intermediates = x509.NewCertPool()
            for _, intermediate := range chain[1:] {
                opts.Intermediates.AddCert(intermediate)
            }
        }

        if _, err := leaf.Verify(opts); err != nil {
            log.Fatal(err)
        }
    }
}

该链是使用以下代码构建的,我怀疑这是问题所在,但我似乎无法找出问题所在。该代码尝试使用给定的根密钥创建给定深度的证书链。

type Key struct {
    priv crypto.PrivateKey
    pub  crypto.PublicKey
}

func makeChain(rootKey Key, depth int) ([]*x509.Certificate, error) {
    var (
        certs     = make([]*x509.Certificate, depth)
        parentKey = rootKey

        key  *ecdsa.PrivateKey
        cert *x509.Certificate
        err  error
    )

    for depth > 0 {
        if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil {
            return nil, err
        }

        if cert, err = GenerateCACert(parentKey.priv, key.Public()); err != nil {
            return nil, err
        }

        depth--
        certs[depth] = cert
        parentKey = Key{priv: key, pub: key.Public()}
    }

    return certs, nil
}

完整代码可在 Go Playground 中找到。有谁知道我在这里做错了什么导致认证验证失败?

go x509certificate tls1.3
1个回答
0
投票

经过一番调试,我意识到在

CommonName
中指定发行人的
GenerateCACert
时犯了一个愚蠢的错误,而实际上并没有在 OG 帖子中显示。

func GenerateCACert(signer crypto.PrivateKey, trustedKey crypto.PublicKey) (*x509.Certificate, error) {
    subjectInfo := &certTemplateInfo{
        commonName: keyIDFromCryptoKey(trustedKey),
        isCA:       true,
    }

    issuerInfo := &certTemplateInfo{
        commonName: keyIDFromCryptoKey(signer),
    }


    return generateCert(signer.priv, trustedKey, subjectInfo, issuerInfo)
}

keyIDFromCryptoKey
函数创建_public_key的指纹:

func keyIDFromCryptoKey(pubKey crypto.PublicKey) string {
    // Generate and return a fingerprint of the public key.
    // For an RSA key this should be:
    //   SHA256(DER encoded ASN1)
    // Then truncated to 240 bits and encoded into 12 base32 groups like so:
    //   ABCD:EFGH:IJKL:MNOP:QRST:UVWX:YZ23:4567:ABCD:EFGH:IJKL:MNOP
    derBytes, err := x509.MarshalPKIXPublicKey(pubKey)
    if err != nil {
        return ""
    }
    hasher := crypto.SHA256.New()
    hasher.Write(derBytes)
    return keyIDEncode(hasher.Sum(nil)[:30])
}

但我意识到我正在向它传递一个PRIVATE密钥。确保使用

signer
的私钥解决了问题。

完整代码可在 Go Playground

获取

注意:部分代码源自 https://github.com/docker/libtrust

© www.soinside.com 2019 - 2024. All rights reserved.