当前位置:网站首页>Create Ca and issue certificate through go language
Create Ca and issue certificate through go language
2022-07-04 22:40:00 【Hermokrates】
In this article , Will describe how to use go establish CA, And use CA Signed certificate . In the use of openssl When creating a certificate , The steps to follow are Create secret key > establish CA > Generate the secret key to issue the certificate > Use CA grant a certificate . Such steps , So let's try it now .
The authority that created the certificate
First , Will be created from CA Start .CA Will be used to sign other certificates
// Sign the certificate
ca := &x509.Certificate{
SerialNumber: big.NewInt(2019),
Subject: pkix.Name{
CommonName: "domain name",
Organization: []string{
"Company, INC."},
Country: []string{
"US"},
Province: []string{
""},
Locality: []string{
"San Francisco"},
StreetAddress: []string{
"Golden Gate Bridge"},
PostalCode: []string{
"94016"},
},
NotBefore: time.Now(), // entry-into-force time
NotAfter: time.Now().AddDate(10, 0, 0), // Expiration time Specific date
IsCA: true, // For CA
// openssl Medium extendedKeyUsage = clientAuth, serverAuth Field
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
// openssl Medium keyUsage Field
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}
Next, you need to generate public and private keys for the certificate
caPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return err
}
And then generate the certificate :
caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey)
if err != nil {
return err
}
The certificate we see is PEM Encoding , Now? caBytes We have the generated certificate , We'll do it PEM Code for later use :
caPEM := new(bytes.Buffer)
pem.Encode(caPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: caBytes,
})
caPrivKeyPEM := new(bytes.Buffer)
pem.Encode(caPrivKeyPEM, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(caPrivKey),
})
Create certificate
Certificate x509.Certificate And CA Of x509.Certificate Properties are slightly different , Some changes are needed
cert := &x509.Certificate{
SerialNumber: big.NewInt(1658),
Subject: pkix.Name{
CommonName: "domain name",
Organization: []string{
"Company, INC."},
Country: []string{
"US"},
Province: []string{
""},
Locality: []string{
"San Francisco"},
StreetAddress: []string{
"Golden Gate Bridge"},
PostalCode: []string{
"94016"},
},
IPAddresses: []net.IP{
}, // Here is the openssl In profile subjectAltName Inside IP:/IP=
DNSNames: []string{
}, // Here is the openssl In profile subjectAltName Inside DNS:/DNS=
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(10, 0, 0),
SubjectKeyId: []byte{
1, 2, 3, 4, 6},
// Here is the openssl Medium extendedKeyUsage
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
}
notes : Here, the certificate will be specially added
DNSandIP( This is not necessary ), The addition of this option means that our certificate can support multiple domain names
Create a private and public key for the certificate :
certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return err
}
Use CA Signed certificate
With the above content , You can create certificates and use CA To sign
certBytes, err := x509.CreateCertificate(rand.Reader, cert, ca, &certPrivKey.PublicKey, caPrivKey)
if err != nil {
return err
}
To save in certificate format, you need to do PEM code
certPEM := new(bytes.Buffer)
pem.Encode(certPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
})
certPrivKeyPEM := new(bytes.Buffer)
pem.Encode(certPrivKeyPEM, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey),
})
Integrate the above contents
Create a ca.go Inside is create ca And the logic of issuing certificates
package main
import (
"bytes"
cr "crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"math/rand"
"net"
"os"
"time"
)
type CERT struct {
CERT []byte
CERTKEY *rsa.PrivateKey
CERTPEM *bytes.Buffer
CERTKEYPEM *bytes.Buffer
CSR *x509.Certificate
}
func CreateCA(sub *pkix.Name, expire int) (*CERT, error) {
var (
ca = new(CERT)
err error
)
if expire < 1 {
expire = 1
}
// by ca Generate private key
ca.CERTKEY, err = rsa.GenerateKey(cr.Reader, 4096)
if err != nil {
return nil, err
}
// Sign the certificate
ca.CSR = &x509.Certificate{
SerialNumber: big.NewInt(rand.Int63n(2000)),
Subject: *sub,
NotBefore: time.Now(), // entry-into-force time
NotAfter: time.Now().AddDate(expire, 0, 0), // Expiration time
IsCA: true, // For CA
// openssl Medium extendedKeyUsage = clientAuth, serverAuth Field
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
// openssl Medium keyUsage Field
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}
// Create certificate
// caBytes Is the generated certificate
ca.CERT, err = x509.CreateCertificate(cr.Reader, ca.CSR, ca.CSR, &ca.CERTKEY.PublicKey, ca.CERTKEY)
if err != nil {
return nil, err
}
ca.CERTPEM = new(bytes.Buffer)
pem.Encode(ca.CERTPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: ca.CERT,
})
ca.CERTKEYPEM = new(bytes.Buffer)
pem.Encode(ca.CERTKEYPEM, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(ca.CERTKEY),
})
// Conduct PEM code , Coding is direct cat What is shown in the certificate
return ca, nil
}
func Req(ca *x509.Certificate, sub *pkix.Name, expire int, dns []string, ip []net.IP) (*CERT, error) {
var (
cert = &CERT{
}
err error
)
cert.CERTKEY, err = rsa.GenerateKey(cr.Reader, 4096)
if err != nil {
return nil, err
}
if expire < 1 {
expire = 1
}
cert.CSR = &x509.Certificate{
SerialNumber: big.NewInt(rand.Int63n(2000)),
Subject: *sub,
IPAddresses: ip,
DNSNames: dns,
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(expire, 0, 0),
SubjectKeyId: []byte{
1, 2, 3, 4, 6},
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
}
cert.CERT, err = x509.CreateCertificate(cr.Reader, cert.CSR, ca, &cert.CERTKEY.PublicKey, cert.CERTKEY)
if err != nil {
return nil, err
}
cert.CERTPEM = new(bytes.Buffer)
pem.Encode(cert.CERTPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: cert.CERT,
})
cert.CERTKEYPEM = new(bytes.Buffer)
pem.Encode(cert.CERTKEYPEM, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(cert.CERTKEY),
})
return cert, nil
}
func Write(cert *CERT, file string) error {
keyFileName := file + ".key"
certFIleName := file + ".crt"
kf, err := os.Create(keyFileName)
if err != nil {
return err
}
defer kf.Close()
if _, err := kf.Write(cert.CERTKEYPEM.Bytes()); err != nil {
return err
}
cf, err := os.Create(certFIleName)
if err != nil {
return err
}
if _, err := cf.Write(cert.CERTPEM.Bytes()); err != nil {
return err
}
return nil
}
If needed , You can reference these functions
package main
import (
"crypto/x509/pkix"
"log"
"net"
)
func main() {
subj := &pkix.Name{
CommonName: "chinamobile.com",
Organization: []string{
"Company, INC."},
Country: []string{
"US"},
Province: []string{
""},
Locality: []string{
"San Francisco"},
StreetAddress: []string{
"Golden Gate Bridge"},
PostalCode: []string{
"94016"},
}
ca, err := CreateCA(subj, 10)
if err != nil {
log.Panic(err)
}
Write(ca, "./ca")
crt, err := Req(ca.CSR, subj, 10, []string{
"test.default.svc", "test"}, []net.IP{
})
if err != nil {
log.Panic(err)
}
Write(crt, "./tls")
}
Problems encountered
panic: x509: unsupported public key type: rsa.PublicKey
This is because x509.CreateCertificate Parameters of privatekey You need to pass in reference variables , What is passed in is a common variable
notes :x509: only RSA and ECDSA public keys supported
The meaning of some parameters
extendedKeyUsage : Enhanced key usage ( See "new_oids" Field ): Server authentication 、 Client authentication 、 Time stamp .
extendedKeyUsage = critical,serverAuth, clientAuth, timeStamping
keyUsage : Key usage , Anti denial (nonRepudiation)、 digital signature (digitalSignature)、 Key encryption (keyEncipherment).
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
Reference
边栏推荐
- LOGO特训营 第三节 首字母创意手法
- Short video system source code, click the blank space of the screen, the keyboard does not automatically stow
- 9 - 类
- Postgresqlql advanced skills pivot table
- UML图记忆技巧
- 共创软硬件协同生态:Graphcore IPU与百度飞桨的“联合提交”亮相MLPerf
- Challenges faced by virtual human industry
- 短视频系统源码,点击屏幕空白处键盘不自动收起
- 攻防世界 MISC 进阶区 hong
- How diff are the contents of the same configuration item in different environments?
猜你喜欢

Domestic database chaos

Concurrent optimization summary

LOGO特训营 第二节 文字与图形的搭配关系

攻防世界 misc 进阶区 2017_Dating_in_Singapore

UML图记忆技巧

Mongodb aggregation operation summary

串口数据帧

2022-07-04: what is the output of the following go language code? A:true; B:false; C: Compilation error. package main import “fmt“ func main() { fmt.Pri

SPSS installation and activation tutorial (including network disk link)
Redis sentinel simply looks at the trade-offs between distributed high availability and consistency
随机推荐
Redis的持久化机制
Short video system source code, click the blank space of the screen, the keyboard does not automatically stow
虚拟人产业面临的挑战
【OpenGL】笔记二十九、抗锯齿(MSAA)
Google Earth Engine(GEE)——Tasks升级,实现RUN ALL可以一键下载任务类型中的所有影像
Attack and defense world misc advanced grace-50
sobel过滤器
业务太忙,真的是没时间搞自动化理由吗?
Google Earth Engine(GEE)——以MODIS/006/MCD19A2为例批量下载逐天AOD数据逐天的均值、最大值、最小值、标准差、方差统计分析和CSV下载(北京市各区为例)
leetcode 72. Edit distance edit distance (medium)
In Linux, I call odspcmd to query the database information. How to output silently is to only output values. Don't do this
嵌入式开发:技巧和窍门——提高嵌入式软件代码质量的7个技巧
MySQL storage data encryption
LOGO特訓營 第三節 首字母創意手法
攻防世界 MISC 进阶区 hit-the-core
Domestic database chaos
质量体系建设之路的分分合合
攻防世界 MISC 进阶区 3-11
SQL中MAX与GREATEST的区别
Logo special training camp Section IV importance of font design