CSR,全称Certificate Signing Request(证书签发请求),是一种包含了公钥和与主题(通常是实体的信息,如个人或组织)相关的其他信息的数据结构。CSR通常用于向证书颁发机构(Certificate Authority,CA)申请数字证书。下面是CSR的详细介绍:
CSR 的结构
一个典型的CSR包含以下关键信息:
-
主题信息(Subject):这部分信息包括了证书的使用者(通常是个人或实体)的详细信息。主题信息可以包括以下字段:
- Common Name (CN):通常是个体的名称或主机名。
- Organization (O):个体所属的组织。
- Organizational Unit (OU):组织内的部门或单位。
- Locality (L):个体所在地的城市或地理位置。
- State (ST):个体所在地的州或省份。
- Country (C):个体所在地的国家代码。
-
公钥(Public Key):CSR包含了与证书请求者相关的公钥。这个公钥用于加密和数字签名。
-
扩展信息:除了主题信息和公钥,CSR还可以包含各种扩展信息,以指定证书的用途、有效期、密钥用途等。常见的扩展包括密钥用途扩展(Key Usage)、扩展密钥用途(Extended Key Usage)、基本约束(Basic Constraints)等。
-
签名算法:CSR也包含用于签署CSR的签名算法(通常是RSA或ECDSA)。
CSR 的生成
生成CSR通常包括以下步骤:
- 生成密钥对:首先,生成一个密钥对,其中包括公钥和私钥。通常使用RSA或ECDSA算法生成密钥。
- 创建主题信息:确定要包含在CSR中的主题信息。这些信息将在颁发证书时显示在证书上。
- 创建 CSR:使用上述的主题信息和生成的公钥创建CSR。CSR是一个包含上述信息的数据结构,可以在编程中生成,也可以使用CSR生成工具。
- 签署 CSR:通常,CSR需要使用私钥进行签名,以确保CSR的完整性。签名的结果包括CSR的签名部分。
提交 CSR
一旦CSR生成完成,它通常会被提交给证书颁发机构(CA)来获取数字证书。CA将对CSR进行验证,并根据验证结果签发相应的数字证书。验证通常涉及对主题信息的验证,确保申请者的身份合法性。
CSR 的应用
CSR通常用于以下场景:
- HTTPS 证书申请:网站管理员通常会生成CSR并将其提交给CA,以获取HTTPS证书,以便在安全的HTTPS连接中使用。
- 代码签名:开发者可以生成CSR,用于获取代码签名证书,以确保其代码在分发和执行时的完整性和真实性。
- 身份验证:CSR也可用于生成客户端证书,用于SSL/TLS客户端身份验证,例如在虚拟专用网络(VPN)或企业网络中。
CSR是建立公共密钥基础设施(PKI)中的信任和安全通信的关键组成部分。通过创建并提交CSR,申请者可以获得数字证书,从而实现安全通信和身份验证。
示例代码
在Go中生成证书签发请求(Certificate Signing Request,CSR)以及通过CSR生成证书通常需要使用Go语言的crypto/x509
和crypto/x509/pkix
包,以及私钥和公钥管理的包,比如crypto/rsa
。以下是一个简单的示例,演示如何生成CSR并通过CSR生成自签名证书。
生成CSR:
首先,我们将生成CSR(Certificate Signing Request)。CSR包含了公钥、主题信息以及其他证书请求的相关信息。以下是一个示例代码:
go
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"os"
"time"
)
func generateCSR() ([]byte, *rsa.PrivateKey, error) {
privKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, nil, err
}
subject := pkix.Name{
CommonName: "example.com",
Organization: []string{"My Organization"},
OrganizationalUnit: []string{"IT"},
Locality: []string{"City"},
Province: []string{"State"},
Country: []string{"US"},
}
template := x509.CertificateRequest{
Subject: subject,
SignatureAlgorithm: x509.SHA256WithRSA,
}
csrDER, err := x509.CreateCertificateRequest(rand.Reader, &template, privKey)
if err != nil {
return nil, nil, err
}
csrPEM := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE REQUEST",
Bytes: csrDER,
})
return csrPEM, privKey, nil
}
func main() {
csrPEM, privKey, err := generateCSR()
if err != nil {
fmt.Println("Error generating CSR:", err)
return
}
csrFile, err := os.Create("example.csr")
if err != nil {
fmt.Println("Error creating CSR file:", err)
return
}
defer csrFile.Close()
csrFile.Write(csrPEM)
// Optionally, you can save the private key
keyFile, err := os.Create("private.key")
if err != nil {
fmt.Println("Error creating private key file:", err)
return
}
defer keyFile.Close()
keyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(privKey),
})
keyFile.Write(keyPEM)
fmt.Println("CSR and private key generated successfully.")
}
上述代码生成了一个自签名证书请求(CSR),其中包括了公钥、主题信息和签名算法等。私钥也被生成并保存到文件中。
生成自签名证书:
生成自签名证书的过程需要使用之前生成的CSR和私钥。以下是一个示例代码:
go
package main
import (
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"os"
"time"
)
func generateCertificate(csrFile, keyFile string) error {
// Read CSR
csrPEM, err := ioutil.ReadFile(csrFile)
if err != nil {
return err
}
block, _ := pem.Decode(csrPEM)
if block == nil {
return fmt.Errorf("failed to parse PEM block containing the CSR")
}
csr, err := x509.ParseCertificateRequest(block.Bytes)
if err != nil {
return err
}
// Read private key
keyPEM, err := ioutil.ReadFile(keyFile)
if err != nil {
return err
}
block, _ = pem.Decode(keyPEM)
if block == nil {
return fmt.Errorf("failed to parse PEM block containing the private key")
}
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return err
}
// Create a self-signed certificate
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: csr.Subject,
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(1, 0, 0),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
if err != nil {
return err
}
// Save the self-signed certificate to a file
certFile, err := os.Create("selfsigned.crt")
if err != nil {
return err
}
defer certFile.Close()
certPEM := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: derBytes,
})
certFile.Write(certPEM)
return nil
}
func main() {
err := generateCertificate("example.csr", "private.key")
if err != nil {
fmt.Println("Error generating certificate:", err)
return
}
fmt.Println("Self-signed certificate generated successfully.")
}
上述代码读取之前生成的CSR和私钥,然后使用这些信息创建了一个自签名证书。证书的有效期、密钥用途等信息可以根据需要进行调整。最后,它将生成的自签名证书保存到文件中。
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意