证书登录校验
This commit is contained in:
@@ -7,28 +7,35 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 解析PKCS1公钥
|
// 验证私钥的签名, publicKey从证书里获取公钥 certificate.PublicKey
|
||||||
// https://uutool.cn/rsa-generate/
|
func VerifySignature(publicKey any, data, signature []byte) bool {
|
||||||
func ParsePKCS1PublicKey(publicKeyPEM string) (*rsa.PublicKey, error) {
|
rsaPublicKey := publicKey.(*rsa.PublicKey)
|
||||||
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 {
|
|
||||||
hashed := sha256.Sum256(data)
|
hashed := sha256.Sum256(data)
|
||||||
err := rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], signature)
|
err := rsa.VerifyPKCS1v15(rsaPublicKey, crypto.SHA256, hashed[:], signature)
|
||||||
|
|
||||||
return err == nil
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -46,9 +46,11 @@ func (*ReqCMCALoginAlarm) Handle(request ziface.IRequest) {
|
|||||||
request.GetConnection().Stop()
|
request.GetConnection().Stop()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 得到连接实例的随机码
|
// 得到连接实例的随机码
|
||||||
seqNo := m.GetUserByPID(uid.(string)).SeqNo
|
seqNo := m.GetUserByPID(uid.(string)).SeqNo
|
||||||
content := username + ":" + seqNo
|
content := username + ":" + seqNo
|
||||||
|
|
||||||
// 检查判断是否对应随机码
|
// 检查判断是否对应随机码
|
||||||
if err := service.CMCALogin(username, cert, content, key); err != nil {
|
if err := service.CMCALogin(username, cert, content, key); err != nil {
|
||||||
zlog.Ins().ErrorF("LoginFail %s", err)
|
zlog.Ins().ErrorF("LoginFail %s", err)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"omc/core/db"
|
"omc/core/db"
|
||||||
"omc/core/utils"
|
"omc/core/utils"
|
||||||
"omc/handle/model"
|
"omc/handle/model"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/aceld/zinx/zlog"
|
"github.com/aceld/zinx/zlog"
|
||||||
)
|
)
|
||||||
@@ -31,27 +32,36 @@ func UserLogin(name, passwd string) error {
|
|||||||
// CMCALogin 验证随机码
|
// CMCALogin 验证随机码
|
||||||
// content "user:seqNo" 组合的字符
|
// content "user:seqNo" 组合的字符
|
||||||
// signatureBase64 签名数据(base64编码)
|
// signatureBase64 签名数据(base64编码)
|
||||||
func CMCALogin(name, publicKeyStr, content, signatureBase64 string) error {
|
func CMCALogin(name, carCertificate, content, signatureBase64 string) error {
|
||||||
// 用户名密码校验
|
// 用户名密码校验
|
||||||
var user model.User
|
var user model.User
|
||||||
err := db.Client.Model(&model.User{}).Where("account_id=?", name).First(&user).Error
|
err := db.Client.Model(&model.User{}).Where("account_id=?", name).First(&user).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zlog.Ins().ErrorF("Password Login[%s]:%s", name, err)
|
zlog.Ins().ErrorF("Password Login[%s]:%s", name, err)
|
||||||
return errors.New("无效用户名")
|
return errors.New("无效OMC用户")
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.AccountId != name {
|
if user.AccountId != name {
|
||||||
return fmt.Errorf("用户名错误 %s", name)
|
return fmt.Errorf("用户名错误 %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 公钥
|
// 解析证书信息
|
||||||
publicKeyPEM := fmt.Sprintf("-----BEGIN RSA PUBLIC KEY-----\n %s \n-----END RSA PUBLIC KEY-----", publicKeyStr)
|
certificate, err := utils.ParseCert(carCertificate)
|
||||||
|
|
||||||
// 解析公钥
|
|
||||||
publicKey, err := utils.ParsePKCS1PublicKey(publicKeyPEM)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zlog.Ins().ErrorF("publicKeyPEM Login[%s]:%s", name, err)
|
zlog.Ins().ErrorF("ParseCert Login[%s]:%s", name, err)
|
||||||
return fmt.Errorf("解析公钥失败")
|
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得到签名字节串
|
// 解码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 {
|
if valid {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user