设计目标
- 支持RSA2加签验签(解析密钥方式:PKCS1 数字签名算法:SHA256)
- 支持grpc拦截器加签验签,对业务代码无侵入
- 支持gin框架中间件验签,支持客户端发送http请求设置加签信息到Header中
- 支持服务端对接多语言客户端(签名原文为:有序JSON(ASCII码序排序Key,忽略结构体/Map中的0值和空值),RSA2加签(PKCS1+SHA256))
不足
- HTTP请求时,application/json类型POST请求签名原文区分类型,其他类型框架无法获取值的类型,只能转化为map[string]string后进行签名
- 为了通用性,没有在通用参数中加入timestamp, nonce等参数,不能防重放攻击
签名
签名接口
加签接口
func Sign(content, privateKey string)(sign string, err error)
验签接口
func Verify(content, sign, pubKey string) (err error)
结构体、Map等转换为JSON字符串接口
func InterfaceToSortedJSONStr(i interface{
}) (str string, err error)
代码
package signature
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"reflect"
"strings"
)
type Sign func(content, privateKey string) (sign string, err error)
type Verify func(content, sign, pubKey string) (err error)
func NewSigner(s Sign) *Signer {
if s == nil {
s = rsa2Sign
}
return &Signer{
S: s,
}
}
var ErrPemDecode = errors.New("pem.Decode failed")
func rsa2Sign(content, privateKey string) (sign string, err error) {
block, _ := pem.Decode([]byte(privateKey))
if block == nil {
err = ErrPemDecode
return
}
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return
}
hash := sha256.New()
_, err = hash.Write([]byte(content))
if err != nil {
return
}
signature, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, hash.Sum(nil))
if err != nil {
return
}
sign = base64.StdEncoding.EncodeToString(signature)
return
}
type Signer struct {
S Sign
}
func (s *Signer) Sign(content, privateKey string) (sign string, err error) {
return s.S(content, privateKey)
}
func NewVerifier(v Verify) *Verifier {
if v == nil {
v = rsa2Verify
}
return &Verifier{
V: v,
}
}
func rsa2Verify(content, sign, pubKey string) (err error) {
signature, err := base64.StdEncoding.DecodeString(sign)
if err != nil {
return
}
block, _ := pem.Decode([]byte(pubKey))
if block == nil {
err = ErrPemDecode
return
}
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return
}
hash := sha256.New()
_, err = hash.Write([]byte(content))
if err != nil {
return
}
pub := key.(*rsa.PublicKey)
err = rsa.VerifyPKCS1v15(pub, crypto.SHA256, hash.Sum(nil), signature)
return
}
type Verifier struct {
V Verify
}
func (s *Verifier) Verify(content, sign, pubKey string) (err error) {
return s.V(content, sign, pubKey)
}
const InvalidType = "invalid type=%v"
func InterfaceToSortedJSONStr(i interface{
}) (str string, err error) {
if i == nil {
err = fmt.Errorf(InvalidType, i)
return
}
v, err := interfaceValExtract(i)
if err != nil {
return
}
if vStr, ok := v.(string); ok {
str = vStr
return
}
if vMap, ok := v.(ToSignMap); ok && len(vMap) == 0 {
str = ""
return
}
return MarshalToStr(v)
}
func MarshalToStr(i interface{
}) (str string, err error) {
buffer := &bytes.Buffer{
}
encoder := json.NewEncoder