当前位置:网站首页>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
边栏推荐
- 模拟摇杆控制舵机
- 好用app推荐:扫描二维码、扫描条形码并查看历史
- 攻防世界 MISC 进阶区 hong
- Solana chain application crema was shut down due to hacker attacks
- 质量体系建设之路的分分合合
- How to send a reliable request before closing the page
- Redis sentinel simply looks at the trade-offs between distributed high availability and consistency
- Scala download and configuration
- 将QA引入软件开发生命周期是工程师要遵循的最佳实践
- 制作条形码的手机App推荐
猜你喜欢
MYSQL架构——逻辑架构
Google Earth Engine(GEE)——基于 MCD64A1 的 GlobFire 日常火灾数据集
Redis的持久化机制
串口数据帧
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
[acwing] solution of the 58th weekly match
共创软硬件协同生态:Graphcore IPU与百度飞桨的“联合提交”亮相MLPerf
Attack and defense world misc advanced grace-50
Unity修仙手游 | lua动态滑动功能(3种源码具体实现)
Convolutional neural network model -- lenet network structure and code implementation
随机推荐
SQL中MAX与GREATEST的区别
Concurrent network modular reading notes transfer
阿里推出新品牌“瓴羊”,致力成为“数字化领头羊”
Erik baleog and Olaf, advanced area of misc in the attack and defense world
LOGO特训营 第二节 文字与图形的搭配关系
攻防世界 MISC 进阶 glance-50
LOGO特训营 第五节 字体结构与设计常用技法
Attack and defense world misc advanced area ditf
Naacl-22 | introduce the setting of migration learning on the prompt based text generation task
It is said that software testing is very simple, but why are there so many dissuasions?
Wake up day, how do I step by step towards the road of software testing
华泰证券是国家认可的券商吗?开户安不安全?
Scala download and configuration
MYSQL架构——用户权限与管理
微服务--开篇
POM in idea XML dependency cannot be imported
Embedded development: skills and tricks -- seven skills to improve the quality of embedded software code
Éducation à la transmission du savoir | Comment passer à un test logiciel pour l'un des postes les mieux rémunérés sur Internet? (joindre la Feuille de route pour l'apprentissage des tests logiciels)
Jvm-Sandbox-Repeater的部署
Redis的持久化机制