Функция x509.CreateCertificate
Функция x509.CreateCertificate создает новый сертификат X.509.
Первый параметр - rand.Reader, предоставляющий криптостойкий генератор случайных чисел.
Второй параметр - шаблон сертификата, описывающий поля создаваемого сертификата.
Третий параметр - родительский сертификат (может быть самим собой для самоподписанного).
Четвертый параметр - открытый ключ создаваемого сертификата.
Пятый параметр - приватный ключ для подписи сертификата.
Синтаксис
x509.CreateCertificate(rand io.Reader, template, parent *x509.Certificate, pub any, priv any) ([]byte, error)
Пример
Создадим самоподписанный сертификат X.509 для тестовых целей:
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"math/big"
"time"
)
func main() {
// Генерация приватного ключа RSA
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
fmt.Println("Error generating key:", err)
return
}
// Шаблон сертификата
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "example.com",
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 365),
}
// Создание самоподписанного сертификата
certBytes, err := x509.CreateCertificate(
rand.Reader,
template,
template,
&privateKey.PublicKey,
privateKey,
)
if err != nil {
fmt.Println("Error creating certificate:", err)
return
}
fmt.Printf("Certificate created, length: %d bytes\n", len(certBytes))
}
Результат выполнения кода:
"Certificate created, length: 1137 bytes"
Пример
Создадим сертификат с использованием родительского сертификата и приватного ключа:
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"math/big"
"time"
)
func main() {
// Создание корневого (родительского) ключа и сертификата
caKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
fmt.Println("Error generating CA key:", err)
return
}
caTemplate := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "CA",
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 365),
}
caCertBytes, err := x509.CreateCertificate(
rand.Reader,
caTemplate,
caTemplate,
&caKey.PublicKey,
caKey,
)
if err != nil {
fmt.Println("Error creating CA certificate:", err)
return
}
caCert, err := x509.ParseCertificate(caCertBytes)
if err != nil {
fmt.Println("Error parsing CA certificate:", err)
return
}
// Создание клиентского ключа
clientKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
fmt.Println("Error generating client key:", err)
return
}
// Шаблон клиентского сертификата
clientTemplate := &x509.Certificate{
SerialNumber: big.NewInt(2),
Subject: pkix.Name{
CommonName: "client.example.com",
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 30),
}
// Создание сертификата, подписанного корневым
clientCertBytes, err := x509.CreateCertificate(
rand.Reader,
clientTemplate,
caCert,
&clientKey.PublicKey,
caKey,
)
if err != nil {
fmt.Println("Error creating client certificate:", err)
return
}
fmt.Printf("Client certificate created, length: %d bytes\n", len(clientCertBytes))
}
Результат выполнения кода:
"Client certificate created, length: 1135 bytes"
Пример
Создание сертификата с различными расширениями (SAN, ключевые использования):
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"math/big"
"net"
"time"
)
func main() {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
fmt.Println("Error generating key:", err)
return
}
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "example.com",
},
DNSNames: []string{"example.com", "www.example.com"},
IPAddresses: []net.IP{
net.ParseIP("192.168.1.1"),
},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 365),
}
certBytes, err := x509.CreateCertificate(
rand.Reader,
template,
template,
&privateKey.PublicKey,
privateKey,
)
if err != nil {
fmt.Println("Error creating certificate:", err)
return
}
fmt.Printf("Certificate with SAN created, length: %d bytes\n", len(certBytes))
}
Результат выполнения кода:
"Certificate with SAN created, length: 1188 bytes"
Смотрите также
-
функцию
x509.ParseCertificate,
которая парсит DER-кодированный сертификат в структуру -
функцию
x509.ParsePKCS1PrivateKey,
которая парсит приватный ключ RSA в формате PKCS#1 -
функцию
pem.Encode,
которая кодирует сертификат в формат PEM -
функцию
rsa.GenerateKey,
которая генерирует пару ключей RSA