allinssl/backend/public/cert.go

141 lines
3.6 KiB
Go

package public
import (
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"time"
)
// **解析 PEM 格式的证书**
func ParseCertificate(certPEM []byte) (*x509.Certificate, error) {
block, _ := pem.Decode(certPEM)
if block == nil {
return nil, fmt.Errorf("无法解析证书 PEM")
}
return x509.ParseCertificate(block.Bytes)
}
// **解析 PEM 格式的私钥**
func ParsePrivateKey(keyPEM []byte) (crypto.PrivateKey, error) {
block, _ := pem.Decode(keyPEM)
if block == nil {
return nil, fmt.Errorf("无法解析私钥 PEM")
}
// **尝试解析不同类型的私钥**
if key, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {
return key, nil
}
if key, err := x509.ParseECPrivateKey(block.Bytes); err == nil {
return key, nil
}
if key, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {
return key, nil
}
return nil, fmt.Errorf("无法识别的私钥格式")
}
// **检查证书是否过期**
func CheckCertificateExpiration(cert *x509.Certificate) error {
now := time.Now()
if now.Before(cert.NotBefore) {
return fmt.Errorf("证书尚未生效,有效期开始于: %v", cert.NotBefore)
}
if now.After(cert.NotAfter) {
return fmt.Errorf("证书已过期,有效期截止到: %v", cert.NotAfter)
}
return nil
}
// **检查证书是否与私钥匹配**
func VerifyCertificateAndKey(cert *x509.Certificate, privateKey crypto.PrivateKey) error {
messageARR := sha256.Sum256([]byte("test message"))
message := messageARR[:]
var signature []byte
var err error
// **用私钥签名数据**
switch key := privateKey.(type) {
case *rsa.PrivateKey:
signature, err = rsa.SignPKCS1v15(nil, key, crypto.SHA256, message)
case *ecdsa.PrivateKey:
signature, err = key.Sign(rand.Reader, message, crypto.SHA256)
case ed25519.PrivateKey:
signature = ed25519.Sign(key, message)
default:
err = errors.New("不支持的私钥类型")
}
if err != nil {
return fmt.Errorf("签名失败: %v", err)
}
// **使用公钥验证签名**
switch pub := cert.PublicKey.(type) {
case *rsa.PublicKey:
err = rsa.VerifyPKCS1v15(pub, crypto.SHA256, message, signature)
case *ecdsa.PublicKey:
ok := ecdsa.VerifyASN1(pub, message, signature)
if !ok {
err = fmt.Errorf("ECDSA 签名验证失败")
}
case ed25519.PublicKey:
if !ed25519.Verify(pub, message, signature) {
err = fmt.Errorf("Ed25519 签名验证失败")
}
default:
err = fmt.Errorf("不支持的公钥类型: %T", pub)
}
return err
}
// **主验证函数**
func ValidateSSLCertificate(certStr, keyStr string) error {
certPEM, keyPEM := []byte(certStr), []byte(keyStr)
// **解析证书和私钥**
cert, err := ParseCertificate(certPEM)
if err != nil {
return fmt.Errorf("解析证书失败: %v", err)
}
privateKey, err := ParsePrivateKey(keyPEM)
if err != nil {
return fmt.Errorf("解析私钥失败: %v", err)
}
// **检查证书有效期**
if err := CheckCertificateExpiration(cert); err != nil {
return err
}
// **检查证书和私钥是否匹配**
if err := VerifyCertificateAndKey(cert, privateKey); err != nil {
return fmt.Errorf("证书与私钥不匹配: %v", err)
}
return nil
}
// 获取sha256
func GetSHA256(certStr string) (string, error) {
certPEM := []byte(certStr)
block, _ := pem.Decode(certPEM)
if block == nil {
return "", fmt.Errorf("无法解析证书 PEM")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return "", fmt.Errorf("解析证书失败: %v", err)
}
sha256Hash := sha256.Sum256(cert.Raw)
return hex.EncodeToString(sha256Hash[:]), nil
}