我正在尝试生成
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 中找到。有谁知道我在这里做错了什么导致认证验证失败?
经过一番调试,我意识到在
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