feat:邮储支付加密
This commit is contained in:
parent
2543a0fd4d
commit
274e5cea4d
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,2 @@
|
|||
* 来源于 github.com/tjfoc/gmsm
|
||||
* 修改适配 邮储对接
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
package sm2
|
||||
|
||||
// reference to ecdsa
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"github.com/tjfoc/gmsm/sm3"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
var (
|
||||
default_uid = []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}
|
||||
)
|
||||
|
||||
type PublicKey struct {
|
||||
elliptic.Curve
|
||||
X, Y *big.Int
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
D *big.Int
|
||||
}
|
||||
|
||||
type sm2Signature struct {
|
||||
R, S *big.Int
|
||||
}
|
||||
|
||||
func (priv *PrivateKey) Public() crypto.PublicKey {
|
||||
return &priv.PublicKey
|
||||
}
|
||||
|
||||
var errZeroParam = errors.New("zero parameter")
|
||||
var one = new(big.Int).SetInt64(1)
|
||||
var two = new(big.Int).SetInt64(2)
|
||||
|
||||
func (priv *PrivateKey) Sign(random io.Reader, msg []byte, signer crypto.SignerOpts) ([]byte, error) {
|
||||
r, s, err := Sm2Sign(priv, msg, nil, random)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return asn1.Marshal(sm2Signature{r, s})
|
||||
}
|
||||
|
||||
func Sm2Sign(priv *PrivateKey, msg, uid []byte, random io.Reader) (r, s *big.Int, err error) {
|
||||
digest, err := priv.PublicKey.Sm3Digest(msg, uid)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
e := new(big.Int).SetBytes(digest)
|
||||
c := priv.PublicKey.Curve
|
||||
N := c.Params().N
|
||||
if N.Sign() == 0 {
|
||||
return nil, nil, errZeroParam
|
||||
}
|
||||
var k *big.Int
|
||||
for { // 调整算法细节以实现SM2
|
||||
for {
|
||||
k, err = randFieldElement(c, random)
|
||||
if err != nil {
|
||||
r = nil
|
||||
return
|
||||
}
|
||||
r, _ = priv.Curve.ScalarBaseMult(k.Bytes())
|
||||
r.Add(r, e)
|
||||
r.Mod(r, N)
|
||||
if r.Sign() != 0 {
|
||||
if t := new(big.Int).Add(r, k); t.Cmp(N) != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
rD := new(big.Int).Mul(priv.D, r)
|
||||
s = new(big.Int).Sub(k, rD)
|
||||
d1 := new(big.Int).Add(priv.D, one)
|
||||
d1Inv := new(big.Int).ModInverse(d1, N)
|
||||
s.Mul(s, d1Inv)
|
||||
s.Mod(s, N)
|
||||
if s.Sign() != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (pub *PublicKey) Sm3Digest(msg, uid []byte) ([]byte, error) {
|
||||
if len(uid) == 0 {
|
||||
uid = default_uid
|
||||
}
|
||||
|
||||
za, err := getZ(pub, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e, err := msgHash(za, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e.Bytes(), nil
|
||||
}
|
||||
|
||||
func Sm2Verify(pub *PublicKey, msg, uid []byte, r, s *big.Int) bool {
|
||||
c := pub.Curve
|
||||
N := c.Params().N
|
||||
one := new(big.Int).SetInt64(1)
|
||||
if r.Cmp(one) < 0 || s.Cmp(one) < 0 {
|
||||
return false
|
||||
}
|
||||
if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 {
|
||||
return false
|
||||
}
|
||||
if len(uid) == 0 {
|
||||
uid = default_uid
|
||||
}
|
||||
za, err := getZ(pub, uid)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
e, err := msgHash(za, msg)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
t := new(big.Int).Add(r, s)
|
||||
t.Mod(t, N)
|
||||
if t.Sign() == 0 {
|
||||
return false
|
||||
}
|
||||
var x *big.Int
|
||||
x1, y1 := c.ScalarBaseMult(s.Bytes())
|
||||
x2, y2 := c.ScalarMult(pub.X, pub.Y, t.Bytes())
|
||||
x, _ = c.Add(x1, y1, x2, y2)
|
||||
|
||||
x.Add(x, e)
|
||||
x.Mod(x, N)
|
||||
return x.Cmp(r) == 0
|
||||
}
|
||||
|
||||
func msgHash(za, msg []byte) (*big.Int, error) {
|
||||
e := sm3.New()
|
||||
e.Write(za)
|
||||
e.Write(msg)
|
||||
return new(big.Int).SetBytes(e.Sum(nil)[:32]), nil
|
||||
}
|
||||
|
||||
func bigIntToByte(n *big.Int) []byte {
|
||||
byteArray := n.Bytes()
|
||||
// If the most significant byte's most significant bit is set,
|
||||
// prepend a 0 byte to the slice to avoid being interpreted as a negative number.
|
||||
if (byteArray[0] & 0x80) != 0 {
|
||||
byteArray = append([]byte{0}, byteArray...)
|
||||
}
|
||||
return byteArray
|
||||
}
|
||||
|
||||
func getZ(pub *PublicKey, uid []byte) ([]byte, error) {
|
||||
z := sm3.New()
|
||||
uidLen := len(uid) * 8
|
||||
entla := []byte{byte(uidLen >> 8), byte(uidLen & 255)}
|
||||
z.Write(entla)
|
||||
z.Write(uid)
|
||||
|
||||
// a 先写死,原来的没有暴露
|
||||
z.Write(bigIntToByte(sm2P256ToBig(&sm2P256.a)))
|
||||
z.Write(bigIntToByte(sm2P256.B))
|
||||
z.Write(bigIntToByte(sm2P256.Gx))
|
||||
z.Write(bigIntToByte(sm2P256.Gy))
|
||||
|
||||
z.Write(bigIntToByte(pub.X))
|
||||
z.Write(bigIntToByte(pub.Y))
|
||||
return z.Sum(nil), nil
|
||||
}
|
||||
|
||||
func randFieldElement(c elliptic.Curve, random io.Reader) (k *big.Int, err error) {
|
||||
if random == nil {
|
||||
random = rand.Reader //If there is no external trusted random source,please use rand.Reader to instead of it.
|
||||
}
|
||||
params := c.Params()
|
||||
b := make([]byte, params.BitSize/8+8)
|
||||
_, err = io.ReadFull(random, b)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
k = new(big.Int).SetBytes(b)
|
||||
n := new(big.Int).Sub(params.N, one)
|
||||
k.Mod(k, n)
|
||||
k.Add(k, one)
|
||||
return
|
||||
}
|
||||
|
||||
func GenerateKey(random io.Reader) (*PrivateKey, error) {
|
||||
c := P256Sm2()
|
||||
if random == nil {
|
||||
random = rand.Reader //If there is no external trusted random source,please use rand.Reader to instead of it.
|
||||
}
|
||||
params := c.Params()
|
||||
b := make([]byte, params.BitSize/8+8)
|
||||
_, err := io.ReadFull(random, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k := new(big.Int).SetBytes(b)
|
||||
n := new(big.Int).Sub(params.N, two)
|
||||
k.Mod(k, n)
|
||||
k.Add(k, one)
|
||||
priv := new(PrivateKey)
|
||||
priv.PublicKey.Curve = c
|
||||
priv.D = k
|
||||
priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
|
||||
|
||||
return priv, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package sm2
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func ReadPrivateKeyFromHex(Dhex string) (*PrivateKey, error) {
|
||||
c := P256Sm2()
|
||||
d, err := hex.DecodeString(Dhex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k := new(big.Int).SetBytes(d)
|
||||
params := c.Params()
|
||||
one := new(big.Int).SetInt64(1)
|
||||
n := new(big.Int).Sub(params.N, one)
|
||||
if k.Cmp(n) >= 0 {
|
||||
return nil, errors.New("privateKey's D is overflow.")
|
||||
}
|
||||
priv := new(PrivateKey)
|
||||
priv.PublicKey.Curve = c
|
||||
priv.D = k
|
||||
priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
func ReadPublicKeyFromHex(Qhex string) (*PublicKey, error) {
|
||||
q, err := hex.DecodeString(Qhex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(q) == 65 && q[0] == byte(0x04) {
|
||||
q = q[1:]
|
||||
}
|
||||
if len(q) != 64 {
|
||||
return nil, errors.New("publicKey is not uncompressed.")
|
||||
}
|
||||
pub := new(PublicKey)
|
||||
pub.Curve = P256Sm2()
|
||||
pub.X = new(big.Int).SetBytes(q[:32])
|
||||
pub.Y = new(big.Int).SetBytes(q[32:])
|
||||
return pub, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"PaymentCenter/app/third/paymentService/psbc/internal/sm2"
|
||||
"bytes"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
zzsm2 "github.com/ZZMarquis/gm/sm2"
|
||||
"github.com/tjfoc/gmsm/sm3"
|
||||
"github.com/tjfoc/gmsm/x509"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func Sm2Decrypt(privateKey *sm2.PrivateKey, encryptData []byte) ([]byte, error) {
|
||||
C1Byte := make([]byte, 65)
|
||||
copy(C1Byte, encryptData[:65])
|
||||
x, y := elliptic.Unmarshal(privateKey.Curve, C1Byte)
|
||||
dBC1X, dBC1Y := privateKey.Curve.ScalarMult(x, y, bigIntToByte(privateKey.D))
|
||||
dBC1Bytes := elliptic.Marshal(privateKey.Curve, dBC1X, dBC1Y)
|
||||
|
||||
kLen := len(encryptData) - 65 - 32
|
||||
t, err := kdf(dBC1Bytes, kLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
M := make([]byte, kLen)
|
||||
for i := 0; i < kLen; i++ {
|
||||
M[i] = encryptData[65+i] ^ t[i]
|
||||
}
|
||||
|
||||
C3 := make([]byte, 32)
|
||||
copy(C3, encryptData[len(encryptData)-32:])
|
||||
u := calculateHash(dBC1X, M, dBC1Y)
|
||||
|
||||
if bytes.Compare(u, C3) == 0 {
|
||||
return M, nil
|
||||
} else {
|
||||
return nil, errors.New("解密失败")
|
||||
}
|
||||
}
|
||||
|
||||
func Sm2Encrypt(publicKey *sm2.PublicKey, m []byte) ([]byte, error) {
|
||||
kLen := len(m)
|
||||
var C1, t []byte
|
||||
var err error
|
||||
var kx, ky *big.Int
|
||||
for {
|
||||
k, _ := rand.Int(rand.Reader, publicKey.Params().N)
|
||||
C1x, C1y := zzsm2.GetSm2P256V1().ScalarBaseMult(bigIntToByte(k))
|
||||
// C1x, C1y := sm2.P256Sm2().ScalarBaseMult(bigIntToByte(k))
|
||||
C1 = elliptic.Marshal(publicKey.Curve, C1x, C1y)
|
||||
|
||||
kx, ky = publicKey.ScalarMult(publicKey.X, publicKey.Y, bigIntToByte(k))
|
||||
kpbBytes := elliptic.Marshal(publicKey, kx, ky)
|
||||
t, err = kdf(kpbBytes, kLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !isAllZero(t) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
C2 := make([]byte, kLen)
|
||||
for i := 0; i < kLen; i++ {
|
||||
C2[i] = m[i] ^ t[i]
|
||||
}
|
||||
|
||||
C3 := calculateHash(kx, m, ky)
|
||||
|
||||
r := make([]byte, 0, len(C1)+len(C2)+len(C3))
|
||||
r = append(r, C1...)
|
||||
r = append(r, C2...)
|
||||
r = append(r, C3...)
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func isAllZero(m []byte) bool {
|
||||
for i := 0; i < len(m); i++ {
|
||||
if m[i] != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func calculateHash(x *big.Int, M []byte, y *big.Int) []byte {
|
||||
digest := sm3.New()
|
||||
digest.Write(bigIntToByte(x))
|
||||
digest.Write(M)
|
||||
digest.Write(bigIntToByte(y))
|
||||
result := digest.Sum(nil)[:32]
|
||||
return result
|
||||
}
|
||||
|
||||
func bigIntToByte(n *big.Int) []byte {
|
||||
byteArray := n.Bytes()
|
||||
// If the most significant byte's most significant bit is set,
|
||||
// prepend a 0 byte to the slice to avoid being interpreted as a negative number.
|
||||
if (byteArray[0] & 0x80) != 0 {
|
||||
byteArray = append([]byte{0}, byteArray...)
|
||||
}
|
||||
return byteArray
|
||||
}
|
||||
|
||||
func kdf(Z []byte, klen int) ([]byte, error) {
|
||||
ct := 1
|
||||
end := (klen + 31) / 32
|
||||
result := make([]byte, 0)
|
||||
for i := 1; i <= end; i++ {
|
||||
b, err := sm3hash(Z, toByteArray(ct))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, b...)
|
||||
ct++
|
||||
}
|
||||
last, err := sm3hash(Z, toByteArray(ct))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if klen%32 == 0 {
|
||||
result = append(result, last...)
|
||||
} else {
|
||||
result = append(result, last[:klen%32]...)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func sm3hash(sources ...[]byte) ([]byte, error) {
|
||||
b, err := joinBytes(sources...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
md := make([]byte, 32)
|
||||
h := x509.SM3.New()
|
||||
h.Write(b)
|
||||
h.Sum(md[:0])
|
||||
return md, nil
|
||||
}
|
||||
|
||||
func joinBytes(params ...[]byte) ([]byte, error) {
|
||||
var buffer bytes.Buffer
|
||||
for i := 0; i < len(params); i++ {
|
||||
_, err := buffer.Write(params[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
func toByteArray(i int) []byte {
|
||||
byteArray := []byte{
|
||||
byte(i >> 24),
|
||||
byte((i & 16777215) >> 16),
|
||||
byte((i & 65535) >> 8),
|
||||
byte(i & 255),
|
||||
}
|
||||
return byteArray
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GenerateSM4Key() []byte {
|
||||
str := "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"
|
||||
buffer := make([]byte, 16)
|
||||
for i := 0; i < 16; i++ {
|
||||
nextInt, _ := rand.Int(rand.Reader, big.NewInt(int64(len(str))))
|
||||
buffer[i] = str[nextInt.Int64()]
|
||||
}
|
||||
return buffer
|
||||
}
|
||||
func GenerateSM4Key128() []byte {
|
||||
str := "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"
|
||||
buffer := make([]byte, 128)
|
||||
for i := 0; i < 128; i++ {
|
||||
nextInt, _ := rand.Int(rand.Reader, big.NewInt(int64(len(str))))
|
||||
buffer[i] = str[nextInt.Int64()]
|
||||
}
|
||||
return buffer
|
||||
}
|
||||
|
||||
func GenAccessToken(token string) string {
|
||||
if token != "" {
|
||||
return token
|
||||
}
|
||||
now := time.Now()
|
||||
return strings.ToUpper(Md5Hash(now.Format("2006A01B02CD15E04F05"), ""))
|
||||
}
|
||||
|
||||
func Md5Hash(password, salt string) string {
|
||||
m := md5.New()
|
||||
m.Write([]byte(salt + password))
|
||||
return hex.EncodeToString(m.Sum(nil))
|
||||
}
|
||||
|
||||
// GetSM4IV 获取SM4的IV
|
||||
func GetSM4IV() []byte {
|
||||
return []byte("UISwD9fW6cFh9SNS")
|
||||
}
|
||||
|
||||
func Padding(input []byte, mode int) []byte {
|
||||
if input == nil {
|
||||
return nil
|
||||
} else {
|
||||
var ret []byte
|
||||
if mode == 1 {
|
||||
p := 16 - len(input)%16
|
||||
ret = make([]byte, len(input)+p)
|
||||
copy(ret, input)
|
||||
|
||||
for i := 0; i < p; i++ {
|
||||
ret[len(input)+i] = byte(p)
|
||||
}
|
||||
} else {
|
||||
p := input[len(input)-1]
|
||||
ret = make([]byte, len(input)-int(p))
|
||||
copy(ret, input[:len(input)-int(p)])
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
// 0值填充函数
|
||||
// ZeroPadding 零填充
|
||||
func ZeroPadding(data []byte, blockSize int) []byte {
|
||||
padding := blockSize - len(data)%blockSize
|
||||
if padding == 0 {
|
||||
padding = blockSize // 强制对齐
|
||||
}
|
||||
return append(data, bytes.Repeat([]byte{0x00}, padding)...)
|
||||
}
|
||||
Loading…
Reference in New Issue