From 11c3c7f89d56a27bc1b438e46b3fb6b630f99af3 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Thu, 24 Aug 2023 15:04:23 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=81=E4=B9=A6=E7=99=BB=E5=BD=95=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/utils/cakey.go | 45 +++++++++++++++++------------- handle/api/req_cmca_login_alarm.go | 2 ++ handle/service/login.go | 30 +++++++++++++------- 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/core/utils/cakey.go b/core/utils/cakey.go index 25d94e4..c383e49 100644 --- a/core/utils/cakey.go +++ b/core/utils/cakey.go @@ -7,28 +7,35 @@ import ( "crypto/x509" "encoding/pem" "fmt" + "strings" ) -// 解析PKCS1公钥 -// https://uutool.cn/rsa-generate/ -func ParsePKCS1PublicKey(publicKeyPEM string) (*rsa.PublicKey, error) { - block, _ := pem.Decode([]byte(publicKeyPEM)) - if block == nil { - return nil, fmt.Errorf("无效的公钥 -----BEGIN RSA PUBLIC KEY----- 编码") - } - - pubKey, err := x509.ParsePKCS1PublicKey(block.Bytes) - if err != nil { - return nil, err - } - - return pubKey, nil -} - -// 验证签名 -func VerifySignature(publicKey *rsa.PublicKey, data, signature []byte) bool { +// 验证私钥的签名, publicKey从证书里获取公钥 certificate.PublicKey +func VerifySignature(publicKey any, data, signature []byte) bool { + rsaPublicKey := publicKey.(*rsa.PublicKey) hashed := sha256.Sum256(data) - err := rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], signature) + err := rsa.VerifyPKCS1v15(rsaPublicKey, crypto.SHA256, hashed[:], signature) return err == nil } + +// 解析证书信息 +func ParseCert(carCertificate string) (*x509.Certificate, error) { + // 解析头尾需要换行符 + result := strings.Split(carCertificate, "-----") + result[2] = "\n" + result[2] + "\n" + carCertificate = strings.Join(result, "-----") + + // 解码证书 + block, _ := pem.Decode([]byte(carCertificate)) + if block == nil { + return nil, fmt.Errorf("无法解码证书") + } + + // 解析证书 + certificate, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, err + } + return certificate, nil +} diff --git a/handle/api/req_cmca_login_alarm.go b/handle/api/req_cmca_login_alarm.go index bfbd782..7fc462b 100644 --- a/handle/api/req_cmca_login_alarm.go +++ b/handle/api/req_cmca_login_alarm.go @@ -46,9 +46,11 @@ func (*ReqCMCALoginAlarm) Handle(request ziface.IRequest) { request.GetConnection().Stop() return } + // 得到连接实例的随机码 seqNo := m.GetUserByPID(uid.(string)).SeqNo content := username + ":" + seqNo + // 检查判断是否对应随机码 if err := service.CMCALogin(username, cert, content, key); err != nil { zlog.Ins().ErrorF("LoginFail %s", err) diff --git a/handle/service/login.go b/handle/service/login.go index 53c0d17..ddeabe6 100644 --- a/handle/service/login.go +++ b/handle/service/login.go @@ -7,6 +7,7 @@ import ( "omc/core/db" "omc/core/utils" "omc/handle/model" + "time" "github.com/aceld/zinx/zlog" ) @@ -31,27 +32,36 @@ func UserLogin(name, passwd string) error { // CMCALogin 验证随机码 // content "user:seqNo" 组合的字符 // signatureBase64 签名数据(base64编码) -func CMCALogin(name, publicKeyStr, content, signatureBase64 string) error { +func CMCALogin(name, carCertificate, content, signatureBase64 string) error { // 用户名密码校验 var user model.User err := db.Client.Model(&model.User{}).Where("account_id=?", name).First(&user).Error if err != nil { zlog.Ins().ErrorF("Password Login[%s]:%s", name, err) - return errors.New("无效用户名") + return errors.New("无效OMC用户") } if user.AccountId != name { return fmt.Errorf("用户名错误 %s", name) } - // 公钥 - publicKeyPEM := fmt.Sprintf("-----BEGIN RSA PUBLIC KEY-----\n %s \n-----END RSA PUBLIC KEY-----", publicKeyStr) - - // 解析公钥 - publicKey, err := utils.ParsePKCS1PublicKey(publicKeyPEM) + // 解析证书信息 + certificate, err := utils.ParseCert(carCertificate) if err != nil { - zlog.Ins().ErrorF("publicKeyPEM Login[%s]:%s", name, err) - return fmt.Errorf("解析公钥失败") + zlog.Ins().ErrorF("ParseCert Login[%s]:%s", name, err) + return fmt.Errorf("解析证书失败") + } + + // 判断证书到期时间 + if time.Now().After(certificate.NotAfter) { + zlog.Ins().ErrorF("certificate Not After Now time Login[%s]:%s", name, err) + return errors.New("证书已过期") + } + + // 判断证书持有人 + if certificate.Subject.CommonName != name { + zlog.Ins().ErrorF("certificate Subject CommonName Login[%s]:%s", name, err) + return errors.New("用户与证书持有人不匹配") } // 解码base64得到签名字节串 @@ -62,7 +72,7 @@ func CMCALogin(name, publicKeyStr, content, signatureBase64 string) error { } // 验证签名 - valid := utils.VerifySignature(publicKey, []byte(content), signature) + valid := utils.VerifySignature(certificate.PublicKey, []byte(content), signature) if valid { return nil }