security: switch from RSA-2048 to ECDSA-P256 for agent certs and update certificate config and handling

This commit is contained in:
yusing 2025-05-17 08:29:01 +08:00
parent f45f3fba79
commit 36ceba3ae7

View file

@ -2,7 +2,6 @@ package agent
import ( import (
"crypto/rand" "crypto/rand"
"crypto/rsa"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"crypto/x509/pkix" "crypto/x509/pkix"
@ -12,20 +11,37 @@ import (
"math/big" "math/big"
"strings" "strings"
"time" "time"
"crypto/ecdsa"
"crypto/elliptic"
"fmt"
) )
const ( const (
CertsDNSName = "godoxy.agent" CertsDNSName = "godoxy.agent"
KeySize = 2048
) )
func toPEMPair(certDER []byte, key *rsa.PrivateKey) *PEMPair { func toPEMPair(certDER []byte, key *ecdsa.PrivateKey) *PEMPair {
marshaledKey, err := marshalECPrivateKey(key)
if err != nil {
// This is a critical internal error during PEM encoding of a newly generated key.
// Panicking is acceptable here as it indicates a fundamental issue.
panic(fmt.Sprintf("failed to marshal EC private key for PEM encoding: %v", err))
}
return &PEMPair{ return &PEMPair{
Cert: pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}), Cert: pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}),
Key: pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}), Key: pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: marshaledKey}),
} }
} }
func marshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
derBytes, err := x509.MarshalECPrivateKey(key)
if err != nil {
return nil, fmt.Errorf("failed to marshal EC private key: %w", err)
}
return derBytes, nil
}
func b64Encode(data []byte) string { func b64Encode(data []byte) string {
return base64.StdEncoding.EncodeToString(data) return base64.StdEncoding.EncodeToString(data)
} }
@ -63,10 +79,23 @@ func (p *PEMPair) ToTLSCert() (*tls.Certificate, error) {
return &cert, err return &cert, err
} }
func newSerialNumber() (*big.Int, error) {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) // 128-bit random number
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, fmt.Errorf("failed to generate serial number: %w", err)
}
return serialNumber, nil
}
func NewAgent() (ca, srv, client *PEMPair, err error) { func NewAgent() (ca, srv, client *PEMPair, err error) {
caSerialNumber, err := newSerialNumber()
if err != nil {
return nil, nil, nil, err
}
// Create the CA's certificate // Create the CA's certificate
caTemplate := &x509.Certificate{ caTemplate := &x509.Certificate{
SerialNumber: big.NewInt(1), SerialNumber: caSerialNumber,
Subject: pkix.Name{ Subject: pkix.Name{
Organization: []string{"GoDoxy"}, Organization: []string{"GoDoxy"},
CommonName: CertsDNSName, CommonName: CertsDNSName,
@ -76,9 +105,12 @@ func NewAgent() (ca, srv, client *PEMPair, err error) {
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true, BasicConstraintsValid: true,
IsCA: true, IsCA: true,
MaxPathLen: 0,
MaxPathLenZero: true,
SignatureAlgorithm: x509.ECDSAWithSHA256,
} }
caKey, err := rsa.GenerateKey(rand.Reader, KeySize) caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
@ -91,20 +123,29 @@ func NewAgent() (ca, srv, client *PEMPair, err error) {
ca = toPEMPair(caDER, caKey) ca = toPEMPair(caDER, caKey)
// Generate a new private key for the server certificate // Generate a new private key for the server certificate
serverKey, err := rsa.GenerateKey(rand.Reader, KeySize) serverKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
serverSerialNumber, err := newSerialNumber()
if err != nil {
return nil, nil, nil, err
}
srvTemplate := &x509.Certificate{ srvTemplate := &x509.Certificate{
SerialNumber: big.NewInt(2), SerialNumber: serverSerialNumber,
Issuer: caTemplate.Subject, Issuer: caTemplate.Subject,
Subject: caTemplate.Subject, Subject: pkix.Name{
DNSNames: []string{CertsDNSName}, Organization: caTemplate.Subject.Organization,
NotBefore: time.Now(), OrganizationalUnit: []string{"Server"},
NotAfter: time.Now().AddDate(1000, 0, 0), // Add validity period CommonName: CertsDNSName,
KeyUsage: x509.KeyUsageDigitalSignature, },
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, DNSNames: []string{CertsDNSName},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(1000, 0, 0), // Add validity period
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
SignatureAlgorithm: x509.ECDSAWithSHA256,
} }
srvCertDER, err := x509.CreateCertificate(rand.Reader, srvTemplate, caTemplate, &serverKey.PublicKey, caKey) srvCertDER, err := x509.CreateCertificate(rand.Reader, srvTemplate, caTemplate, &serverKey.PublicKey, caKey)
@ -114,20 +155,29 @@ func NewAgent() (ca, srv, client *PEMPair, err error) {
srv = toPEMPair(srvCertDER, serverKey) srv = toPEMPair(srvCertDER, serverKey)
clientKey, err := rsa.GenerateKey(rand.Reader, KeySize) clientKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
clientSerialNumber, err := newSerialNumber()
if err != nil {
return nil, nil, nil, err
}
clientTemplate := &x509.Certificate{ clientTemplate := &x509.Certificate{
SerialNumber: big.NewInt(3), SerialNumber: clientSerialNumber,
Issuer: caTemplate.Subject, Issuer: caTemplate.Subject,
Subject: caTemplate.Subject, Subject: pkix.Name{
DNSNames: []string{CertsDNSName}, Organization: caTemplate.Subject.Organization,
NotBefore: time.Now(), OrganizationalUnit: []string{"Client"},
NotAfter: time.Now().AddDate(1000, 0, 0), CommonName: CertsDNSName,
KeyUsage: x509.KeyUsageDigitalSignature, },
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, DNSNames: []string{CertsDNSName},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(1000, 0, 0),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
SignatureAlgorithm: x509.ECDSAWithSHA256,
} }
clientCertDER, err := x509.CreateCertificate(rand.Reader, clientTemplate, caTemplate, &clientKey.PublicKey, caKey) clientCertDER, err := x509.CreateCertificate(rand.Reader, clientTemplate, caTemplate, &clientKey.PublicKey, caKey)
if err != nil { if err != nil {