Apply .gitignore rules
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
package securityUtil
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// RsaSha256验证签名
|
||||
// publicKey:公钥
|
||||
// source:原字符串
|
||||
// targetSign:用以验证的目标签名(会进行Base64解码)
|
||||
// 返回值:返回nil为成功
|
||||
func VerifyRsaWithSha256(publicKey, source, targetSign string) error {
|
||||
//未加标记的PEM密钥加上公钥标记
|
||||
if !strings.HasPrefix(publicKey, "-") {
|
||||
publicKey = fmt.Sprintf(`-----BEGIN PUBLIC KEY-----
|
||||
%s
|
||||
-----END PUBLIC KEY-----`, publicKey)
|
||||
}
|
||||
|
||||
//base64解码目标签名
|
||||
signBuf, err := base64.StdEncoding.DecodeString(targetSign)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//解码公钥
|
||||
block, _ := pem.Decode([]byte(publicKey))
|
||||
if block == nil {
|
||||
return fmt.Errorf("RSA.VerifyRsaWithSha256,Block is nil,public key error!")
|
||||
}
|
||||
|
||||
//转化为公钥对象
|
||||
pubObj, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pub := pubObj.(*rsa.PublicKey)
|
||||
|
||||
//验证签名
|
||||
err = rsa.VerifyPKCS1v15(pub, crypto.SHA256, Sha256Bytes([]byte(source)), signBuf)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// RsaSha1验证签名
|
||||
// publicKey:公钥
|
||||
// source:原字符串
|
||||
// targetSign:用以验证的目标签名(会进行Base64解码)
|
||||
// 返回值:返回nil为成功
|
||||
func VerifyRsaWithSha1(publicKey, source, targetSign string) error {
|
||||
//未加标记的PEM密钥加上公钥标记
|
||||
if !strings.HasPrefix(publicKey, "-") {
|
||||
publicKey = fmt.Sprintf(`-----BEGIN PUBLIC KEY-----
|
||||
%s
|
||||
-----END PUBLIC KEY-----`, publicKey)
|
||||
}
|
||||
|
||||
//base64解码目标签名
|
||||
signBuf, err := base64.StdEncoding.DecodeString(targetSign)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//解码公钥
|
||||
block, _ := pem.Decode([]byte(publicKey))
|
||||
if block == nil {
|
||||
return fmt.Errorf("RSA.VerifyRsaWithSha1,Block is nil,public key error!")
|
||||
}
|
||||
|
||||
//转化为公钥对象
|
||||
pubObj, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pub := pubObj.(*rsa.PublicKey)
|
||||
|
||||
//验证签名
|
||||
err = rsa.VerifyPKCS1v15(pub, crypto.SHA1, Sha1StringToBytes(source), signBuf)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 对字符数组进行SHA1加密
|
||||
// b:输入字符数组
|
||||
// 返回值:sha1加密后的原数据
|
||||
func Sha1StringToBytes(b string) []byte {
|
||||
if len(b) == 0 {
|
||||
panic(errors.New("input []byte can't be empty"))
|
||||
}
|
||||
|
||||
sha1Instance := sha1.New()
|
||||
sha1Instance.Write([]byte(b))
|
||||
result := sha1Instance.Sum(nil)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func packageData(originalData []byte, packageSize int) (r [][]byte) {
|
||||
var src = make([]byte, len(originalData))
|
||||
copy(src, originalData)
|
||||
|
||||
r = make([][]byte, 0)
|
||||
if len(src) <= packageSize {
|
||||
return append(r, src)
|
||||
}
|
||||
for len(src) > 0 {
|
||||
var p = src[:packageSize]
|
||||
r = append(r, p)
|
||||
src = src[packageSize:]
|
||||
if len(src) <= packageSize {
|
||||
r = append(r, src)
|
||||
break
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// RSAEncrypt 数据加密
|
||||
// plaintext:待加密的数据
|
||||
// key:公钥
|
||||
// 返回值:
|
||||
// []byte:加密后的数据
|
||||
// error:错误信息
|
||||
func RSAEncrypt(plaintext, key []byte) ([]byte, error) {
|
||||
var err error
|
||||
var block *pem.Block
|
||||
block, _ = pem.Decode(key)
|
||||
if block == nil {
|
||||
return nil, errors.New("public key error")
|
||||
}
|
||||
|
||||
var pubInterface interface{}
|
||||
pubInterface, err = x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pub = pubInterface.(*rsa.PublicKey)
|
||||
|
||||
var data = packageData(plaintext, pub.N.BitLen()/8-11)
|
||||
var cipherData []byte = make([]byte, 0, 0)
|
||||
|
||||
for _, d := range data {
|
||||
var c, e = rsa.EncryptPKCS1v15(rand.Reader, pub, d)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
cipherData = append(cipherData, c...)
|
||||
}
|
||||
|
||||
return cipherData, nil
|
||||
}
|
||||
|
||||
// RSADecrypt 数据解密
|
||||
// plaintext:待解密的数据
|
||||
// key:私钥
|
||||
// 返回值:
|
||||
// []byte:解密后的数据
|
||||
// error:错误信息
|
||||
func RSADecrypt(ciphertext, key []byte) ([]byte, error) {
|
||||
var err error
|
||||
var block *pem.Block
|
||||
block, _ = pem.Decode(key)
|
||||
if block == nil {
|
||||
return nil, errors.New("private key error")
|
||||
}
|
||||
|
||||
var pri *rsa.PrivateKey
|
||||
pri, err = x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var data = packageData(ciphertext, pri.PublicKey.N.BitLen()/8)
|
||||
var plainData []byte = make([]byte, 0, 0)
|
||||
|
||||
for _, d := range data {
|
||||
var p, e = rsa.DecryptPKCS1v15(rand.Reader, pri, d)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
plainData = append(plainData, p...)
|
||||
}
|
||||
return plainData, nil
|
||||
}
|
||||
|
||||
// 基于RSA PKCS1V15进行签名
|
||||
// src:待签名的原始字符串
|
||||
// key:签名用的私钥
|
||||
// hash:签名配置
|
||||
// 返回值:
|
||||
// []byte:得到的签名字节流
|
||||
// error:错误信息
|
||||
func SignPKCS1v15(src, key []byte, hash crypto.Hash) ([]byte, error) {
|
||||
var h = hash.New()
|
||||
h.Write(src)
|
||||
var hashed = h.Sum(nil)
|
||||
|
||||
var err error
|
||||
var block *pem.Block
|
||||
block, _ = pem.Decode(key)
|
||||
if block == nil {
|
||||
return nil, errors.New("private key error")
|
||||
}
|
||||
|
||||
var pri *rsa.PrivateKey
|
||||
pri, err = x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rsa.SignPKCS1v15(rand.Reader, pri, hash, hashed)
|
||||
}
|
||||
|
||||
// 验证RSA PKCS1V15进行签名
|
||||
// src:待签名的原始字符串
|
||||
// sig:签名字节流
|
||||
// key:签名用的私钥
|
||||
// hash:签名配置
|
||||
// 返回值:
|
||||
// error:错误信息
|
||||
func VerifyPKCS1v15(src, sig, key []byte, hash crypto.Hash) error {
|
||||
var h = hash.New()
|
||||
h.Write(src)
|
||||
var hashed = h.Sum(nil)
|
||||
|
||||
var err error
|
||||
var block *pem.Block
|
||||
block, _ = pem.Decode(key)
|
||||
if block == nil {
|
||||
return errors.New("public key error")
|
||||
}
|
||||
|
||||
var pubInterface interface{}
|
||||
pubInterface, err = x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var pub = pubInterface.(*rsa.PublicKey)
|
||||
|
||||
return rsa.VerifyPKCS1v15(pub, hash, hashed, sig)
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package qcloud
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"goutil/mathUtil"
|
||||
"goutil/smsUtil/sms"
|
||||
)
|
||||
|
||||
const (
|
||||
SINGLE_SMS_URL = "https://yun.tim.qq.com/v5/tlssmssvr/sendsms"
|
||||
MULTI_SMS_URL = "https://yun.tim.qq.com/v5/tlssmssvr/sendmultisms2"
|
||||
)
|
||||
|
||||
// 创建msg类型短信(直接发送短信内容)
|
||||
// 参数:
|
||||
//
|
||||
// appid
|
||||
// appkey
|
||||
// nation []string 国家代码 eg: 86
|
||||
// numbers []string 电话号码
|
||||
// msg string 短信内容
|
||||
// extend string 通道扩展码,可选字段,默认没有开通(需要填空串)
|
||||
// ext string 用户的session内容,腾讯server回包中会原样返回,可选字段,不需要就填空
|
||||
//
|
||||
// nation、numbers 需要一一对应 (nation[0]将与numbers[0]组合)
|
||||
// msg 必须与已通过审核的模板匹配
|
||||
func NewMsgSms(appid, appkey string,
|
||||
nation, numbers []string,
|
||||
msg, extend, ext string) (sms.Sms, error) {
|
||||
|
||||
return generateSms(appid, appkey,
|
||||
nation, numbers,
|
||||
extend, ext,
|
||||
newMsgSmsField(0, msg),
|
||||
nil)
|
||||
}
|
||||
|
||||
// 创建tmpl类型短信(通过模板发送短信)
|
||||
// 参数:
|
||||
//
|
||||
// appid
|
||||
// appkey
|
||||
// nation []string 国家代码 eg: 86
|
||||
// numbers []string 电话号码
|
||||
// tmplID int 模板ID
|
||||
// params []string 模板参数
|
||||
// sign string 短信签名(前缀)
|
||||
// extend string 通道扩展码,可选字段,默认没有开通(需要填空串)
|
||||
// ext string 用户的session内容,腾讯server回包中会原样返回,可选字段,不需要就填空
|
||||
//
|
||||
// nation、numbers 需要一一对应 (nation[0]将与numbers[0]组合)
|
||||
func NewTmplSms(appid, appkey string,
|
||||
nation, numbers []string,
|
||||
tmplID int, params []string,
|
||||
sign, extend, ext string) (sms.Sms, error) {
|
||||
|
||||
return generateSms(appid, appkey,
|
||||
nation, numbers,
|
||||
extend, ext,
|
||||
nil,
|
||||
newTmplSmsField(sign, tmplID, params))
|
||||
|
||||
}
|
||||
|
||||
// create qcloud sms instance
|
||||
func generateSms(appid, appkey string,
|
||||
nation, numbers []string,
|
||||
extend, ext string,
|
||||
msg *msgSmsField,
|
||||
tmpl *tmplSmsField) (s sms.Sms, err error) {
|
||||
|
||||
err = validateMobile(nation, numbers)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var url string
|
||||
// 区分
|
||||
if len(nation) > 1 {
|
||||
url = MULTI_SMS_URL
|
||||
} else {
|
||||
url = SINGLE_SMS_URL
|
||||
}
|
||||
|
||||
// 生成随机数、时间戳,并计算签名
|
||||
rnd := mathUtil.GetRand().GetRandRangeInt(100000, 999999)
|
||||
timestap := time.Now().Unix()
|
||||
sig := calcSig(appkey, rnd, timestap, numbers)
|
||||
|
||||
// 生成公共字段
|
||||
comField := newCommonField(sig, timestap, extend, ext, generateTelField(nation, numbers))
|
||||
|
||||
// 生成smsData
|
||||
data := newSmsData(comField, msg, tmpl)
|
||||
|
||||
// 生成qcloudsms
|
||||
s = newSms(url, data, rnd, appid)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// calculate sign-string for phone numbers
|
||||
func calcSig(appkey string, rnd int, tm int64, numbers []string) string {
|
||||
mobile := strings.Join(numbers, ",")
|
||||
|
||||
sum := sha256.Sum256([]byte(fmt.Sprintf("appkey=%v&random=%v&time=%v&mobile=%v",
|
||||
appkey, rnd, tm, mobile)))
|
||||
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
// 验证地区代码与手机号数量是否匹配
|
||||
func validateMobile(nation, numbers []string) error {
|
||||
if len(nation) != len(numbers) {
|
||||
return errors.New("loadReq: nation、numbers 数量不同")
|
||||
} else if len(nation) == 0 {
|
||||
return errors.New("loadReq: nation、numbers 不能为空")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 生成Tel字段
|
||||
// 当多个号码时,生成[]telField
|
||||
// 单个号码时,生成telField
|
||||
func generateTelField(nation, numbers []string) interface{} {
|
||||
res := make([](*telField), len(nation))
|
||||
|
||||
for i := 0; i < len(nation); i++ {
|
||||
res[i] = newTelField(nation[i], numbers[i])
|
||||
}
|
||||
|
||||
if len(res) == 1 {
|
||||
return res[0]
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
Reference in New Issue
Block a user