使用证书颁发机构签署证书请求
Signing certificate request with certificate authority
我想使用 TLS 相互身份验证在 API 上对客户端进行身份验证。我已经创建了一个证书颁发机构,假设 Bob 有一个他想与客户端一起使用的密钥对。 Bob 创建了一个证书请求并希望我验证他的证书以便获得授权和
在 API.
上通过身份验证
我用它来创建我的证书颁发机构:
openssl genrsa -aes256 -out ca.key 4096
openssl req -new -x509 -sha256 -days 730 -key ca.key -out ca.crt
Bob 使用它来创建他的证书和证书请求:
openssl genrsa -out bob.key 4096
openssl req -new -key bob.key -out bob.csr
我想实现这个,但在进行中:
openssl x509 -req -days 365 -sha256 -in bob.csr -CA ca.crt -CAkey ca.key -set_serial 3 -out bob.crt
现在,通过这些命令,Bob 可以创建到我的 API 的 TLS 连接,它使用 tls.Config :
func createTLSConfig(certFile string, keyFile string, clientCAFilepath string) (config *tls.Config, err error) {
cer, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, err
}
clientCAFile, err := ioutil.ReadFile(clientCAFilepath)
if err != nil {
return nil, err
}
clientCAPool := x509.NewCertPool()
clientCAPool.AppendCertsFromPEM(clientCAFile)
config = &tls.Config{
Certificates: []tls.Certificate{cer},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: clientCAPool,
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
},
PreferServerCipherSuites: true,
SessionTicketsDisabled: false,
MinVersion: tls.VersionTLS12,
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384},
}
return config, nil
}
但是如果 Julia 现在想登录怎么办?她将必须创建一个 CSR,将其发送给我,我也必须手动将她的 CSR 验证到 CRT。为了避免这种手动操作,我们的想法是拥有一个注册端点,Julia 可以在其中提交她的 CSR 并取回有效的 CRT。端点基本上是这样的:
func Register(c echo.Context) (err error) {
// get Julia's csr from POST body
csr := certificateFromBody(c.Body)
// valid csr with ca to generate the crt
crt := signCSR(csr, config.ClientCAPath)
// return the crt to julia
return c.JSON(http.StatusCreated, base64.StdEncoding.EncodeToString(crt))
}
我花了一些时间了解 openssl 如何使用 CA 从 CRS 创建 CRT,但没有成功。
Golang 有一个 CertificateRequest object from the crypto/x509 package that I can create with the ParseCertificateRequest 但我找不到获取此对象和我的 CA 以及 return 证书的函数。
感谢您的帮助!
您也许可以使用 x509.CreateCertificate。
CreateCertificate 的参数之一是 'template' 证书。
您可以使用 Julia 的 CertificateRequest.
中的字段设置模板证书的字段
Go 的 generate cert 脚本显示了一个示例用法 CreateCertificate。
这假设来自 Julia 的 API 请求确实来自 Julia,并且足够可信以签署请求和 return 证书。
另外,Using your own PKI for TLS in Go 可能会有帮助。
它现在可以工作了,这里是使用 CA 从 CRT 验证 CSR 的基本解决方案:
- 加载 CA 证书
- 加载ca私钥(带密码)
- 加载鲍勃 CSR
- 使用 CSR 和 CA 信息创建证书模板
- 从模板和 CA 私钥生成证书
- 保存 bob 的证书
一个工作示例:
package main
import (
"crypto/rand"
"crypto/x509"
"encoding/pem"
"io/ioutil"
"math/big"
"os"
"time"
)
func crsToCrtExample() {
// load CA key pair
// public key
caPublicKeyFile, err := ioutil.ReadFile("certs/ca-root.crt")
if err != nil {
panic(err)
}
pemBlock, _ := pem.Decode(caPublicKeyFile)
if pemBlock == nil {
panic("pem.Decode failed")
}
caCRT, err := x509.ParseCertificate(pemBlock.Bytes)
if err != nil {
panic(err)
}
// private key
caPrivateKeyFile, err := ioutil.ReadFile("certs/ca-mutu.key")
if err != nil {
panic(err)
}
pemBlock, _ = pem.Decode(caPrivateKeyFile)
if pemBlock == nil {
panic("pem.Decode failed")
}
der, err := x509.DecryptPEMBlock(pemBlock, []byte("ca private key password"))
if err != nil {
panic(err)
}
caPrivateKey, err := x509.ParsePKCS1PrivateKey(der)
if err != nil {
panic(err)
}
// load client certificate request
clientCSRFile, err := ioutil.ReadFile("certs/bob.csr")
if err != nil {
panic(err)
}
pemBlock, _ = pem.Decode(clientCSRFile)
if pemBlock == nil {
panic("pem.Decode failed")
}
clientCSR, err := x509.ParseCertificateRequest(pemBlock.Bytes)
if err != nil {
panic(err)
}
if err = clientCSR.CheckSignature(); err != nil {
panic(err)
}
// create client certificate template
clientCRTTemplate := x509.Certificate{
Signature: clientCSR.Signature,
SignatureAlgorithm: clientCSR.SignatureAlgorithm,
PublicKeyAlgorithm: clientCSR.PublicKeyAlgorithm,
PublicKey: clientCSR.PublicKey,
SerialNumber: big.NewInt(2),
Issuer: caCRT.Subject,
Subject: clientCSR.Subject,
NotBefore: time.Now(),
NotAfter: time.Now().Add(24 * time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
// create client certificate from template and CA public key
clientCRTRaw, err := x509.CreateCertificate(rand.Reader, &clientCRTTemplate, caCRT, clientCSR.PublicKey, caPrivateKey)
if err != nil {
panic(err)
}
// save the certificate
clientCRTFile, err := os.Create("certs/bob.crt")
if err != nil {
panic(err)
}
pem.Encode(clientCRTFile, &pem.Block{Type: "CERTIFICATE", Bytes: clientCRTRaw})
clientCRTFile.Close()
}
谢谢马克!
这是我为有关 PKI 的博客 post 编写的演示程序的一段代码。完整 post: https://anchorloop.com/2017/09/25/security-iq-ii-public-key-infrastructure/
// Now read that number of bytes and parse the certificate request
asn1Data := make([]byte, asn1DataSize)
_, err = reader.Read(asn1Data)
if err != nil {
return err
}
fmt.Println("Received Certificate Signing Request.")
certReq, err := x509.ParseCertificateRequest(asn1Data)
if err != nil {
return err
}
// Create template for certificate creation, uses properties from the request and root certificate.
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return err
}
template := x509.Certificate {
Signature: certReq.Signature,
SignatureAlgorithm: certReq.SignatureAlgorithm,
PublicKeyAlgorithm: certReq.PublicKeyAlgorithm,
PublicKey: certReq.PublicKey,
SerialNumber: serialNumber,
Issuer: rootCert.Subject,
Subject: certReq.Subject,
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 365),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
// Create certificate from template and root certificate, signed by the RootCA's private key.
certData, err := x509.CreateCertificate(rand.Reader, &template, rootCert, template.PublicKey, privateKey)
if err != nil {
return err
}
fmt.Println("Created Certificate from CSR, signed by RootCA's Private Key.")
基本上:
- CSR 由客户端创建并发送。
- 签名证书的所有者解析它并从 CSR 和签名证书的混合属性中构建一个新的 x509.Certificate。
- 签名者的私钥被传递给x509.CreateCertificate进行签名。
- 之后,您可以将其发送回客户端。
希望对您有所帮助。
我想使用 TLS 相互身份验证在 API 上对客户端进行身份验证。我已经创建了一个证书颁发机构,假设 Bob 有一个他想与客户端一起使用的密钥对。 Bob 创建了一个证书请求并希望我验证他的证书以便获得授权和 在 API.
上通过身份验证我用它来创建我的证书颁发机构:
openssl genrsa -aes256 -out ca.key 4096
openssl req -new -x509 -sha256 -days 730 -key ca.key -out ca.crt
Bob 使用它来创建他的证书和证书请求:
openssl genrsa -out bob.key 4096
openssl req -new -key bob.key -out bob.csr
我想实现这个,但在进行中:
openssl x509 -req -days 365 -sha256 -in bob.csr -CA ca.crt -CAkey ca.key -set_serial 3 -out bob.crt
现在,通过这些命令,Bob 可以创建到我的 API 的 TLS 连接,它使用 tls.Config :
func createTLSConfig(certFile string, keyFile string, clientCAFilepath string) (config *tls.Config, err error) {
cer, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, err
}
clientCAFile, err := ioutil.ReadFile(clientCAFilepath)
if err != nil {
return nil, err
}
clientCAPool := x509.NewCertPool()
clientCAPool.AppendCertsFromPEM(clientCAFile)
config = &tls.Config{
Certificates: []tls.Certificate{cer},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: clientCAPool,
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
},
PreferServerCipherSuites: true,
SessionTicketsDisabled: false,
MinVersion: tls.VersionTLS12,
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384},
}
return config, nil
}
但是如果 Julia 现在想登录怎么办?她将必须创建一个 CSR,将其发送给我,我也必须手动将她的 CSR 验证到 CRT。为了避免这种手动操作,我们的想法是拥有一个注册端点,Julia 可以在其中提交她的 CSR 并取回有效的 CRT。端点基本上是这样的:
func Register(c echo.Context) (err error) {
// get Julia's csr from POST body
csr := certificateFromBody(c.Body)
// valid csr with ca to generate the crt
crt := signCSR(csr, config.ClientCAPath)
// return the crt to julia
return c.JSON(http.StatusCreated, base64.StdEncoding.EncodeToString(crt))
}
我花了一些时间了解 openssl 如何使用 CA 从 CRS 创建 CRT,但没有成功。
Golang 有一个 CertificateRequest object from the crypto/x509 package that I can create with the ParseCertificateRequest 但我找不到获取此对象和我的 CA 以及 return 证书的函数。
感谢您的帮助!
您也许可以使用 x509.CreateCertificate。
CreateCertificate 的参数之一是 'template' 证书。
您可以使用 Julia 的 CertificateRequest.
中的字段设置模板证书的字段Go 的 generate cert 脚本显示了一个示例用法 CreateCertificate。
这假设来自 Julia 的 API 请求确实来自 Julia,并且足够可信以签署请求和 return 证书。
另外,Using your own PKI for TLS in Go 可能会有帮助。
它现在可以工作了,这里是使用 CA 从 CRT 验证 CSR 的基本解决方案:
- 加载 CA 证书
- 加载ca私钥(带密码)
- 加载鲍勃 CSR
- 使用 CSR 和 CA 信息创建证书模板
- 从模板和 CA 私钥生成证书
- 保存 bob 的证书
一个工作示例:
package main
import (
"crypto/rand"
"crypto/x509"
"encoding/pem"
"io/ioutil"
"math/big"
"os"
"time"
)
func crsToCrtExample() {
// load CA key pair
// public key
caPublicKeyFile, err := ioutil.ReadFile("certs/ca-root.crt")
if err != nil {
panic(err)
}
pemBlock, _ := pem.Decode(caPublicKeyFile)
if pemBlock == nil {
panic("pem.Decode failed")
}
caCRT, err := x509.ParseCertificate(pemBlock.Bytes)
if err != nil {
panic(err)
}
// private key
caPrivateKeyFile, err := ioutil.ReadFile("certs/ca-mutu.key")
if err != nil {
panic(err)
}
pemBlock, _ = pem.Decode(caPrivateKeyFile)
if pemBlock == nil {
panic("pem.Decode failed")
}
der, err := x509.DecryptPEMBlock(pemBlock, []byte("ca private key password"))
if err != nil {
panic(err)
}
caPrivateKey, err := x509.ParsePKCS1PrivateKey(der)
if err != nil {
panic(err)
}
// load client certificate request
clientCSRFile, err := ioutil.ReadFile("certs/bob.csr")
if err != nil {
panic(err)
}
pemBlock, _ = pem.Decode(clientCSRFile)
if pemBlock == nil {
panic("pem.Decode failed")
}
clientCSR, err := x509.ParseCertificateRequest(pemBlock.Bytes)
if err != nil {
panic(err)
}
if err = clientCSR.CheckSignature(); err != nil {
panic(err)
}
// create client certificate template
clientCRTTemplate := x509.Certificate{
Signature: clientCSR.Signature,
SignatureAlgorithm: clientCSR.SignatureAlgorithm,
PublicKeyAlgorithm: clientCSR.PublicKeyAlgorithm,
PublicKey: clientCSR.PublicKey,
SerialNumber: big.NewInt(2),
Issuer: caCRT.Subject,
Subject: clientCSR.Subject,
NotBefore: time.Now(),
NotAfter: time.Now().Add(24 * time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
// create client certificate from template and CA public key
clientCRTRaw, err := x509.CreateCertificate(rand.Reader, &clientCRTTemplate, caCRT, clientCSR.PublicKey, caPrivateKey)
if err != nil {
panic(err)
}
// save the certificate
clientCRTFile, err := os.Create("certs/bob.crt")
if err != nil {
panic(err)
}
pem.Encode(clientCRTFile, &pem.Block{Type: "CERTIFICATE", Bytes: clientCRTRaw})
clientCRTFile.Close()
}
谢谢马克!
这是我为有关 PKI 的博客 post 编写的演示程序的一段代码。完整 post: https://anchorloop.com/2017/09/25/security-iq-ii-public-key-infrastructure/
// Now read that number of bytes and parse the certificate request
asn1Data := make([]byte, asn1DataSize)
_, err = reader.Read(asn1Data)
if err != nil {
return err
}
fmt.Println("Received Certificate Signing Request.")
certReq, err := x509.ParseCertificateRequest(asn1Data)
if err != nil {
return err
}
// Create template for certificate creation, uses properties from the request and root certificate.
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return err
}
template := x509.Certificate {
Signature: certReq.Signature,
SignatureAlgorithm: certReq.SignatureAlgorithm,
PublicKeyAlgorithm: certReq.PublicKeyAlgorithm,
PublicKey: certReq.PublicKey,
SerialNumber: serialNumber,
Issuer: rootCert.Subject,
Subject: certReq.Subject,
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 365),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
// Create certificate from template and root certificate, signed by the RootCA's private key.
certData, err := x509.CreateCertificate(rand.Reader, &template, rootCert, template.PublicKey, privateKey)
if err != nil {
return err
}
fmt.Println("Created Certificate from CSR, signed by RootCA's Private Key.")
基本上:
- CSR 由客户端创建并发送。
- 签名证书的所有者解析它并从 CSR 和签名证书的混合属性中构建一个新的 x509.Certificate。
- 签名者的私钥被传递给x509.CreateCertificate进行签名。
- 之后,您可以将其发送回客户端。
希望对您有所帮助。