sign 方法类
package common import ( "Ganzhou/config" "Ganzhou/pkg/log" "crypto" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/base64" "encoding/pem" "errors" ) var AppPriKey = config.GZQAppPriKey var AppPubKey = config.GZQCloudPubKey // Rsa2Sign RSA2私钥签名 func Rsa2Sign(str string, hash crypto.Hash) string { rs := FormateKey(AppPriKey, 1, false) shaNew := hash.New() shaNew.Write([]byte(str)) hashed := shaNew.Sum(nil) priKey, err := ParsePrivateKey(rs) if err != nil { return "" } signature, err := rsa.SignPKCS1v15(rand.Reader, priKey, hash, hashed) if err != nil { return "" } return base64.StdEncoding.EncodeToString(signature) } // 解析私钥 func ParsePrivateKey(privateKey string) (*rsa.PrivateKey, error) { block, _ := pem.Decode([]byte(privateKey)) if block == nil { return nil, errors.New("私钥信息错误!") } privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err == nil { return privKey, nil } privKeyInterface, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err == nil { if priKey, ok := privKeyInterface.(*rsa.PrivateKey); ok { return priKey, nil } } return nil, errors.New("parse private key error") } // RSAVerifySign RSA验证签名 func RSAVerifySign(text []byte, publicKey string, hashType crypto.Hash, sig []byte) error { block, _ := pem.Decode([]byte(publicKey)) if block == nil { log.Errorf("pem.Decode error") return errors.New("public key error") } pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { log.Errorf("x509.ParsePKIXPublicKey error: %s", err) return err } pub := pubInterface.(*rsa.PublicKey) hashInstance := hashType.New() hashInstance.Write(text) hashed := hashInstance.Sum(nil) return rsa.VerifyPKCS1v15(pub, hashType, hashed, sig) } // RSAVerifySignBase64 RSA验证Base64签名 func RSAVerifySignBase64(b64Cipher string, hashType crypto.Hash, text []byte) error { publicKey := FormateKey(AppPubKey, 1, true) cipherText, err := base64.StdEncoding.DecodeString(b64Cipher) if err != nil { cipherText, err = base64.RawURLEncoding.DecodeString(b64Cipher) if err != nil { log.Errorf("base64.StdEncoding.DecodeString error! b64Cipher:%s, err:%s", b64Cipher, err) return err } } return RSAVerifySign(text, publicKey, hashType, cipherText) } func RSAVerify(data []byte, base64Sig string) error { // 1、对base64编码的签名内容进行解码,返回签名字节 bytes, err := base64.StdEncoding.DecodeString(base64Sig) if err != nil { return err } // 2、选择hash算法,对需要签名的数据进行hash运算 myhash := crypto.SHA256 hashInstance := myhash.New() hashInstance.Write(data) hashed := hashInstance.Sum(nil) // 3、读取公钥文件,解析出公钥对象 publicKey, err := ReadParsePublicKey() if err != nil { return err } // 4、RSA验证数字签名(参数是公钥对象、哈希类型、签名文件的哈希串、签名后的字节) return rsa.VerifyPKCS1v15(publicKey, myhash, hashed, bytes) } // 读取公钥文件,解析出公钥对象 func ReadParsePublicKey() (*rsa.PublicKey, error) { publicKeyStr := FormateKey(AppPubKey, 1, true) // 2、解码公钥字节,生成加密块对象 block, _ := pem.Decode([]byte(publicKeyStr)) if block == nil { return nil, errors.New("公钥信息错误!") } // 3、解析DER编码的公钥,生成公钥接口 publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return nil, err } // 4、公钥接口转型成公钥对象 publicKey := publicKeyInterface.(*rsa.PublicKey) return publicKey, nil } //key是否具有头尾换行不交由程序判断 //keyType=1,为key增加头尾,并每间隔64位换行 //ifPublic true 为公钥, false为私钥 //keyType=0,不变 func FormateKey(key string, keyType int, ifPublic bool) string { if keyType == 0 { return key } if ifPublic { var publicHeader = "\n-----BEGIN PUBLIC KEY-----\n" var publicTail = "-----END PUBLIC KEY-----\n" var temp string Split(key, &temp) return publicHeader + temp + publicTail } else { var publicHeader = "\n-----BEGIN RSA PRIVATE KEY-----\n" var publicTail = "-----END RSA PRIVATE KEY-----\n" var temp string Split(key, &temp) return publicHeader + temp + publicTail } } func Split(key string, temp *string) { if len(key) <= 64 { *temp = *temp + key + "\n" } for i := 0; i < len(key); i++ { if (i+1)%64 == 0 { *temp = *temp + key[:i+1] + "\n" key = key[i+1:] Split(key, temp) break } } }
sm4方法类
package common import ( "Ganzhou/config" "bytes" "encoding/hex" "fmt" "github.com/tjfoc/gmsm/sm4" ) var SM4Key = config.GZQCloudDataKey var SM4Ivstr = config.GZQUserSecKey // SM4加密 func SM4Encrypt(data string) (result string, err error) { test, err := sm4.Sm4Ecb([]byte(SM4Key), []byte(data), true) return hex.EncodeToString(test), err ////字符串转byte切片 //plainText := []byte(data) ////建议从配置文件中读取秘钥,进行统一管理 ////todo 注意:iv需要是随机的,进一步保证加密的安全性,将iv的值和加密后的数据一起返回给外部 //SM4Iv := SM4Ivstr //iv := []byte(SM4Iv) //key := []byte(SM4Key) ////实例化sm4加密对象 //block, err := sm4.NewCipher(key) //if err != nil { // panic(err) //} ////明文数据填充 //paddingData := paddingLastGroup(plainText, block.BlockSize()) ////声明SM4的加密工作模式 //blockMode := cipher.NewCBCEncrypter(block, iv) ////为填充后的数据进行加密处理 //cipherText := make([]byte, len(paddingData)) ////使用CryptBlocks这个核心方法,将paddingData进行加密处理,将加密处理后的值赋值到cipherText中 //blockMode.CryptBlocks(cipherText, paddingData) ////加密结果使用hex转成字符串,方便外部调用 //cipherString := hex.EncodeToString(cipherText) //return cipherString, nil } // SM4解密 传入string 输出string func SM4Decrypt(data string) (res string, err error) { decodeString, err := hex.DecodeString(data) if err != nil { return "", err } test, err := sm4.Sm4Ecb([]byte(SM4Key), decodeString, false) return string(test), err ////iv是Initialization Vector,初始向量, //SM4Iv := SM4Ivstr //iv := []byte(SM4Iv) //key := []byte(SM4Key) //block, err := sm4.NewCipher(key) //if err != nil { // panic(err) //} ////使用hex解码 //decodeString, err := hex.DecodeString(data) //if err != nil { // return "", err //} ////CBC模式 优点:具有较好的安全性,能够隐藏明文的模式和重复性。 缺点:加密过程是串行的,不适合并行处理。 //blockMode := cipher.NewCBCDecrypter(block, iv) ////下文有详解这段代码的含义 //blockMode.CryptBlocks(decodeString, decodeString) ////去掉明文后面的填充数据 //plainText := unPaddingLastGroup(decodeString) ////直接返回字符串类型,方便外部调用 //return string(plainText), nil } // 明文数据填充 func paddingLastGroup(plainText []byte, blockSize int) []byte { //1.计算最后一个分组中明文后需要填充的字节数 padNum := blockSize - len(plainText)%blockSize //2.将字节数转换为byte类型 char := []byte{byte(padNum)} //3.创建切片并初始化 newPlain := bytes.Repeat(char, padNum) //4.将填充数据追加到原始数据后 newText := append(plainText, newPlain...) return newText } // 去掉明文后面的填充数据 func unPaddingLastGroup(plainText []byte) []byte { //1.拿到切片中的最后一个字节 length := len(plainText) lastChar := plainText[length-1] //2.将最后一个数据转换为整数 number := int(lastChar) return plainText[:length-number] } func main() { key := []byte("1234567890abcdef") fmt.Printf("key = %v\n", key) data := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10} fmt.Printf("key = %v\n", key) fmt.Printf("data = %x\n", data) //iv := []byte("0000000000000000") //err = SetIV(iv)//设置SM4算法实现的IV值,不设置则使用默认值 ecbMsg, err := sm4.Sm4Ecb(key, data, true) //sm4Ecb模式pksc7填充加密 if err != nil { //t.Errorf("sm4 enc error:%s", err) return } fmt.Printf("ecbMsg = %x\n", ecbMsg) ecbDec, err := sm4.Sm4Ecb(key, ecbMsg, false) //sm4Ecb模式pksc7填充解密 if err != nil { //t.Errorf("sm4 dec error:%s", err) return } fmt.Printf("ecbDec = %x\n", ecbDec) }
sign 签名加密方法调用
func PutPostRdoteFun(p model2.PutRequest) (Pdate model2.PutRequestJson) { str, err := json.Marshal(p) if err != nil { fmt.Println(err) } sign, decrypt := cm.GetSignAndRequest(string(str)) //sign := cm.Rsa2Sign(string(str), crypto.SHA256) //fmt.Println(sign) //fmt.Println(url.QueryEscape(sign)) //decrypt, err := cm.SM4Encrypt(string(str)) //if err != nil { // return //} //fmt.Printf("sm4加密结果:%s\n", decrypt) Pdate.Sign = sign Pdate.Request = decrypt Pdate.UserCode = config.GZQUserCode return Pdate }
// 请求数据签名和sm4加密 func GetSignAndRequest(str string) (sign, Request string) { fmt.Println(str) sig := Rsa2Sign(str, crypto.SHA256) fmt.Println(sign) fmt.Println(url.QueryEscape(sign)) decrypt, err := SM4Encrypt(str) if err != nil { return } fmt.Printf("sm4加密结果:%s\n", decrypt) return sig, decrypt }
sign 签名验签
// 检查验签 func GetExamResultVerification(sign, date string) (pt model2.PutResult, err error) { tt, err := cm.SM4Decrypt(date) if err == nil { fmt.Println(tt) //验签 err = cm.RSAVerifySignBase64(sign, crypto.SHA256, []byte(tt)) if err == nil { err = json.Unmarshal([]byte(tt), &pt) if err != nil { fmt.Printf("Json转译错误: %+v\n", err) } } } return pt, err }