生成CSR和自簽名證書

2023-10-23 12:01:37

CSR,全稱Certificate Signing Request(證書籤發請求),是一種包含了公鑰和與主題(通常是實體的資訊,如個人或組織)相關的其他資訊的資料結構。CSR通常用於向證書頒發機構(Certificate Authority,CA)申請數位憑證。下面是CSR的詳細介紹:

CSR 的結構

一個典型的CSR包含以下關鍵資訊:

  1. 主題資訊(Subject):這部分資訊包括了證書的使用者(通常是個人或實體)的詳細資訊。主題資訊可以包括以下欄位:

    • Common Name (CN):通常是個體的名稱或主機名。
    • Organization (O):個體所屬的組織。
    • Organizational Unit (OU):組織內的部門或單位。
    • Locality (L):個體所在地的城市或地理位置。
    • State (ST):個體所在地的州或省份。
    • Country (C):個體所在地的國家程式碼。
  2. 公鑰(Public Key):CSR包含了與證書請求者相關的公鑰。這個公鑰用於加密和數位簽章。

  3. 擴充套件資訊:除了主題資訊和公鑰,CSR還可以包含各種擴充套件資訊,以指定證書的用途、有效期、金鑰用途等。常見的擴充套件包括金鑰用途擴充套件(Key Usage)、擴充套件金鑰用途(Extended Key Usage)、基本約束(Basic Constraints)等。

  4. 簽名演演算法:CSR也包含用於簽署CSR的簽名演演算法(通常是RSA或ECDSA)。

CSR 的生成

生成CSR通常包括以下步驟:

  1. 生成金鑰對:首先,生成一個金鑰對,其中包括公鑰和私鑰。通常使用RSA或ECDSA演演算法生成金鑰。
  2. 建立主題資訊:確定要包含在CSR中的主題資訊。這些資訊將在頒發證書時顯示在證書上。
  3. 建立 CSR:使用上述的主題資訊和生成的公鑰建立CSR。CSR是一個包含上述資訊的資料結構,可以在程式設計中生成,也可以使用CSR生成工具。
  4. 簽署 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/x509crypto/x509/pkix包,以及私鑰和公鑰管理的包,比如crypto/rsa。以下是一個簡單的範例,演示如何生成CSR並通過CSR生成自簽名證書。

生成CSR:

首先,我們將生成CSR(Certificate Signing Request)。CSR包含了公鑰、主題資訊以及其他證書請求的相關資訊。以下是一個範例程式碼:

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和私鑰。以下是一個範例程式碼:

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: 戀水無意