当前位置:网站首页>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
DNS
andIP
( 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
边栏推荐
- Li Kou 98: verify binary search tree
- Concurrent network modular reading notes transfer
- Unity修仙手游 | lua动态滑动功能(3种源码具体实现)
- LOGO特訓營 第一節 鑒別Logo與Logo設計思路
- Detailed explanation of flask context
- Force buckle 2_ 1480. Dynamic sum of one-dimensional array
- 攻防世界 MISC 高手进阶区 001 normal_png
- In Linux, I call odspcmd to query the database information. How to output silently is to only output values. Don't do this
- How to transfer to software testing, one of the high paying jobs in the Internet? (software testing learning roadmap attached)
- Mongodb aggregation operation summary
猜你喜欢
Li Kou 98: verify binary search tree
国产数据库乱象
How to transfer to software testing, one of the high paying jobs in the Internet? (software testing learning roadmap attached)
Attack and defense world misc advanced grace-50
Wake up day, how do I step by step towards the road of software testing
【OpenGL】笔记二十九、抗锯齿(MSAA)
More than 30 institutions jointly launched the digital collection industry initiative. How will it move forward in the future?
[Yugong series] go teaching course 003-ide installation and basic use in July 2022
Introduction and application of bigfilter global transaction anti duplication component
攻防世界 MISC 进阶区 3-11
随机推荐
LOGO特训营 第四节 字体设计的重要性
MySQL storage data encryption
Mongodb aggregation operation summary
国产数据库乱象
SPSS installation and activation tutorial (including network disk link)
SQL中MAX与GREATEST的区别
达梦数据凭什么被称为国产数据库“第一股”?
odps 中 对表进行了一次备份,为什么在元数据库查m_table 时,两张表的逻辑大小不一致,但数
[the 2023 autumn recruitment of MIHA tour] open [the only exclusive internal push code of school recruitment eytuc]
Business is too busy. Is there really no reason to have time for automation?
Now MySQL cdc2.1 is parsing the datetime class with a value of 0000-00-00 00:00:00
LOGO特训营 第一节 鉴别Logo与Logo设计思路
Logo special training camp section II collocation relationship between words and graphics
Apachecn translation, proofreading, note sorting activity progress announcement 2022.7
业务太忙,真的是没时间搞自动化理由吗?
Practice and principle of PostgreSQL join
Embedded development: skills and tricks -- seven skills to improve the quality of embedded software code
攻防世界 MISC 进阶 glance-50
Redis sentinel simply looks at the trade-offs between distributed high availability and consistency
将QA引入软件开发生命周期是工程师要遵循的最佳实践