通过Go语言创建CA与签发证书

Python025

通过Go语言创建CA与签发证书,第1张

本篇文章中,将描述如何使用go创建CA,并使用CA签署证书。在使用openssl创建证书时,遵循的步骤是 创建秘钥 >创建CA >生成要颁发证书的秘钥 >使用CA签发证书。这种步骤,那么我们现在就来尝试下。

首先,会从将从创建CA开始。 CA会被用来签署其他证书

接下来需要对证书生成公钥和私钥

然后生成证书:

我们看到的证书内容是PEM编码后的,现在 caBytes 我们有了生成的证书,我们将其进行 PEM 编码以供以后使用:

证书的 x509.Certificate 与CA的 x509.Certificate 属性有稍微不同,需要进行一些修改

为该证书创建私钥和公钥:

有了上述的内容后,可以创建证书并用CA进行签名

要保存成证书格式需要做PEM编码

创建一个 ca.go 里面是创建ca和颁发证书的逻辑

如果需要使用的话,可以引用这些函数

panic: x509: unsupported public key type: rsa.PublicKey

这里是因为 x509.CreateCertificate 的参数 privatekey 需要传入引用变量,而传入的是一个普通变量

extendedKeyUsage :增强型密钥用法(参见"new_oids"字段):服务器身份验证、客户端身份验证、时间戳。

keyUsage : 密钥用法,防否认(nonRepudiation)、数字签名(digitalSignature)、密钥加密(keyEncipherment)。

文章来自https://www.cnblogs.com/Cylon/p/16436126.html

周末在家无趣,研究了一个golang里面的Certificate.Verify函数。

golang的官方定义在这里: https://golang.org/pkg/crypto/x509/#Certificate.Verify

函数原型声明如下:

func (c Certificate) Verify(opts VerifyOptions) (chains [][] Certificate, err error)

其中:

这个函数的功能是:

Verify attempts to verify c by building one or more chains from c to a certificate in opts.Roots, using certificates in opts.Intermediates if needed. If successful, it returns one or more chains where the first element of the chain is c and the last element is from opts.Roots.

If opts.Roots is nil and system roots are unavailable the returned error will be of type SystemRootsError.

解释一下就是:

举一个例子:

假设存在证书链签出关系:C1 ->C2 ->C3 ->C4,即C1签出C2,C2签出C3,C3签出C4;现在使用函数:

我们根据Intermediates和Roots的值不同,比较输出结果:

如何验证证书链的签出关系

在证书链中,通常由根CA证书,签出中间CA证书,再签出服务证书。这是一个签出链关系:

Root CA ->Intermediate CA1 ->Intermediate CA2 ->... Intermediate CAn ->Server Certificate

那么如何验证谁是谁的签出关系呢,意思就是验证一个证书是由谁签发的。

通常我们拿到一个完整服务端证书的时候会包含:

ca-chain.pem里面可能包含多个CA证书,如何找到直接签出那个CA证书呢。

我们查看证书的一般内容:

有几个信息:

这里Issuer就明确表明了当前证书是由谁签发的,那我们去找ca-chain里面的所有证书,挨个遍历找出其Subject和这个一样,那么就说明是签发证书。

理论上是这样的,但是Subject只是包含文本信息,用户可以篡改伪造,只要是同名Subject就可以啦。所以这个字段只是便于肉眼辨识使用,真正使用验证的是signature信息。

在前面证书内容中,最后我们看到有Signature Algorithm域,它的值就是签出证书的signature,这个签名是根据签出证书的内容生成的,只有签出证书本身才能得出这个signature。所以我们需要对照CA证书,生成他的signature值,然后和服务端证书里的这个域值进行比较,如果相当就说明是签出证书。

这个算法比较复杂,不细究了,golang里面提供了函数可以直接调用:

func (c *Certificate) CheckSignatureFrom(parent *Certificate) error

举例:

输入:go build test.go &&./test cert.pem ca.pem

验证ca.pem是不是cert.pem的直接签出证书。

还有一个办法是使用: func ( Certificate) Verify() 函数。

如果verify成功,在返回的chains [][] Certificate中每一列的: