package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"math/big"
	"os"
	"time"
)

func writeDataToFile(fn string, data []byte) {
	// 创建一个新文件来写入数据
	file, err := os.Create(fn)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	// 将 data 写入到文件中
	_, err = file.Write(data)
	if err != nil {
		panic(err)
	}
}

func main() {
	// 生成CA根证书密钥对
	caKey, err := rsa.GenerateKey(rand.Reader, 4096)
	if err != nil {
		fmt.Println(err)
	}

	// 生成CA证书模板
	caTemplate := x509.Certificate{
		SerialNumber: big.NewInt(1),
		Subject: pkix.Name{
			Organization: []string{"Go CA"},
		},
		NotBefore:             time.Now(),
		NotAfter:              time.Now().Add(time.Hour * 24 * 3650),
		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
		BasicConstraintsValid: true,
		IsCA:                  true,
	}

	// 使用模板自签名生成CA证书
	caCert, err := x509.CreateCertificate(rand.Reader, &caTemplate, &caTemplate, &caKey.PublicKey, caKey)
	if err != nil {
		fmt.Println(err)
	}

	// 生成中间CA密钥对
	interKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		fmt.Println(err)
	}

	// 生成中间CA证书模板
	interTemplate := x509.Certificate{
		SerialNumber: big.NewInt(2),
		Subject: pkix.Name{
			Organization: []string{"Go OMC CA"},
		},
		NotBefore:             time.Now(),
		NotAfter:              time.Now().Add(time.Hour * 24 * 3650),
		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
		BasicConstraintsValid: true,
		IsCA:                  true,
	}

	// 用CA证书签名生成中间CA证书
	interCert, err := x509.CreateCertificate(rand.Reader, &interTemplate, &caTemplate, &interKey.PublicKey, caKey)
	if err != nil {
		fmt.Println(err)
	}

	// 生成叶子证书密钥对
	leafKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		fmt.Println(err)
	}

	// 生成叶子证书模板,CN为server.com
	leafTemplate := x509.Certificate{
		SerialNumber: big.NewInt(3),
		Subject: pkix.Name{
			Organization: []string{"OMC Server"},
			CommonName:   "",
		},
		NotBefore:   time.Now(),
		NotAfter:    time.Now().Add(time.Hour * 24 * 3650),
		KeyUsage:    x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		//IPAddresses:  []net.IP{net.ParseIP("192.168.2.219")},
		//DNSNames:     []string{""},
		SubjectKeyId: []byte{1, 2, 3, 4},
	}

	// 用中间CA证书签名生成叶子证书
	leafCert, err := x509.CreateCertificate(rand.Reader, &leafTemplate, &interTemplate, &leafKey.PublicKey, interKey)
	if err != nil {
		fmt.Println(err)
	}

	// 生成server1.com叶子证书
	leafKey1, _ := rsa.GenerateKey(rand.Reader, 2048)

	leafTemplate1 := x509.Certificate{
		SerialNumber: big.NewInt(4),
		Subject: pkix.Name{
			CommonName: "server1.com",
		},
		NotBefore: time.Now(),
		NotAfter:  time.Now().Add(time.Hour * 24 * 3650),

		KeyUsage:    x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		DNSNames:    []string{"server1.com"},
	}

	leafCert1, _ := x509.CreateCertificate(rand.Reader, &leafTemplate1, &interTemplate, &leafKey1.PublicKey, interKey)

	// 生成server2.com叶子证书
	leafKey2, _ := rsa.GenerateKey(rand.Reader, 2048)

	leafTemplate2 := x509.Certificate{
		SerialNumber: big.NewInt(5),
		Subject: pkix.Name{
			CommonName: "server2.com",
		},
		NotBefore: time.Now(),
		NotAfter:  time.Now().Add(time.Hour * 24 * 3650),

		KeyUsage:    x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		DNSNames:    []string{"server2.com"},
	}

	leafCert2, _ := x509.CreateCertificate(rand.Reader, &leafTemplate2, &interTemplate, &leafKey2.PublicKey, interKey)

	// 将证书和密钥编码为PEM格式
	caCertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: caCert})
	caKeyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(caKey)})

	interCertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: interCert})
	interKeyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(interKey)})

	leafCertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert})
	leafKeyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(leafKey)})

	leafCertPEM1 := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert1})
	leafKeyPEM1 := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(leafKey1)})

	leafCertPEM2 := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert2})
	leafKeyPEM2 := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(leafKey2)})

	// 将PEM写入文件
	writeDataToFile("ca.crt", caCertPEM)
	writeDataToFile("ca.key", caKeyPEM)

	writeDataToFile("omc-ca.crt", interCertPEM)
	writeDataToFile("omc-ca.key", interKeyPEM)

	writeDataToFile("omc-server.crt", leafCertPEM)
	writeDataToFile("omc-server.key", leafKeyPEM)

	writeDataToFile("omc-web.crt", leafCertPEM1)
	writeDataToFile("omc-web.key", leafKeyPEM1)

	writeDataToFile("omc-server2-cert.pem", leafCertPEM2)
	writeDataToFile("omc-server2-key.pem", leafKeyPEM2)
}
