mirror of https://github.com/allinssl/allinssl
141 lines
3.6 KiB
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
|
|
}
|