加密调整
This commit is contained in:
parent
721808e543
commit
2af26fb728
|
|
@ -1,19 +0,0 @@
|
||||||
package cmb
|
|
||||||
|
|
||||||
import (
|
|
||||||
sm22 "voucher/internal/pkg/cmb/sm2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Smx struct {
|
|
||||||
Sm *sm22.Sm2
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSmx(privateKey, publicKey string) (*Smx, error) {
|
|
||||||
return &Smx{
|
|
||||||
Sm: sm22.NewSm2().SetHexPrivateKey(privateKey).SetHexPublicKey(publicKey),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Smx) Sign(input string) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/elliptic"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
One = new(big.Int).SetInt64(1)
|
||||||
|
DefaultUid = []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}
|
||||||
|
VerifyFalse = []byte{0x30}
|
||||||
|
VerifyTrue = []byte{0x31}
|
||||||
|
)
|
||||||
|
|
||||||
|
type CipherType int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
C1C2C3 CipherType = 1
|
||||||
|
C1C3C2 CipherType = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type PublicKey struct {
|
||||||
|
elliptic.Curve
|
||||||
|
X, Y *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrivateKey struct {
|
||||||
|
*PublicKey
|
||||||
|
D *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Signature struct {
|
||||||
|
R, S *big.Int
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,387 @@
|
||||||
|
package cmbv2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/asn1"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"github.com/ZZMarquis/gm/sm4"
|
||||||
|
"io"
|
||||||
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
"voucher/internal/pkg/cmb/sm2/sdk"
|
||||||
|
"voucher/internal/pkg/cmbv2/model"
|
||||||
|
"voucher/internal/pkg/cmbv2/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Cmb struct {
|
||||||
|
publicKey *model.PublicKey
|
||||||
|
privateKey *model.PrivateKey
|
||||||
|
|
||||||
|
cipherType model.CipherType
|
||||||
|
c3Len int
|
||||||
|
uid []byte
|
||||||
|
|
||||||
|
sdk sdk.SDK
|
||||||
|
|
||||||
|
sm2P256 *utils.Sm2P256Curve
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCmb(privateKey, sopPublicKey string) (*Cmb, error) {
|
||||||
|
cmb := &Cmb{
|
||||||
|
c3Len: 32,
|
||||||
|
uid: model.DefaultUid,
|
||||||
|
cipherType: model.C1C3C2,
|
||||||
|
|
||||||
|
sdk: sdk.NewBaseSdk(),
|
||||||
|
}
|
||||||
|
|
||||||
|
sm2P256 := utils.NewP256Sm2()
|
||||||
|
cmb.sm2P256 = &sm2P256
|
||||||
|
|
||||||
|
if err := cmb.setHexPrivateKey(privateKey); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cmb.setHexPublicKey(sopPublicKey); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmb, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) setHexPublicKey(hexStr string) error {
|
||||||
|
|
||||||
|
d, err := hex.DecodeString(hexStr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("publicKey is not hex string: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
s.publicKey, err = utils.HexToPublicKey(s.sm2P256, d)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("parse publicKey err: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) setHexPrivateKey(hexStr string) error {
|
||||||
|
|
||||||
|
d, err := hex.DecodeString(hexStr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("privateKey is not hex string: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
s.privateKey, err = utils.HexToPrivateKey(s.sm2P256, d)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("parse privateKey err: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) Encrypt(input []byte) (string, error) {
|
||||||
|
|
||||||
|
if input == nil {
|
||||||
|
return "", fmt.Errorf("加密元数据 is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
sm4Key := utils.GenerateSM4Key()
|
||||||
|
iv := utils.GetSM4IV()
|
||||||
|
|
||||||
|
encryptedBody, err := sm4.CBCEncrypt(sm4Key, iv, utils.Padding(input, 1))
|
||||||
|
|
||||||
|
keyAndIv := utils.AssemblingByteArray(sm4Key, iv)
|
||||||
|
|
||||||
|
data := []byte(base64.StdEncoding.EncodeToString(keyAndIv))
|
||||||
|
|
||||||
|
kvTmp, err := s.encrypt(data)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s|%s", base64.StdEncoding.EncodeToString([]byte(kvTmp)), base64.StdEncoding.EncodeToString(encryptedBody)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) encrypt(data []byte) ([]byte, error) {
|
||||||
|
|
||||||
|
c2 := make([]byte, len(data))
|
||||||
|
copy(c2, data)
|
||||||
|
|
||||||
|
var c1 []byte
|
||||||
|
var kx, ky *big.Int
|
||||||
|
for {
|
||||||
|
k, err := rand.Int(rand.Reader, s.publicKey.Params().N)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("rand error: %v", err)
|
||||||
|
}
|
||||||
|
c1x, c1y := s.publicKey.Curve.ScalarBaseMult(k.Bytes())
|
||||||
|
c1 = elliptic.Marshal(s.publicKey.Curve, c1x, c1y)
|
||||||
|
kx, ky = s.publicKey.Curve.ScalarMult(s.publicKey.X, s.publicKey.Y, k.Bytes())
|
||||||
|
|
||||||
|
err = s.sdk.Kdf(s.publicKey, kx, ky, c2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("kdf error: %v", err)
|
||||||
|
}
|
||||||
|
if s.encrypted(c2, data) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c3 := s.sdk.CalculateHash(kx, data, ky)
|
||||||
|
|
||||||
|
c1Len := len(c1)
|
||||||
|
c2Len := len(c2)
|
||||||
|
c3Len := len(c3)
|
||||||
|
|
||||||
|
toData := make([]byte, c1Len+c2Len+c3Len)
|
||||||
|
|
||||||
|
if s.cipherType == model.C1C2C3 {
|
||||||
|
copy(toData[:c1Len], c1)
|
||||||
|
copy(toData[c1Len:c1Len+c2Len], c2)
|
||||||
|
copy(toData[c1Len+c2Len:], c3)
|
||||||
|
} else if s.cipherType == model.C1C3C2 {
|
||||||
|
copy(toData[:c1Len], c1)
|
||||||
|
copy(toData[c1Len:c1Len+c3Len], c3)
|
||||||
|
copy(toData[c1Len+c3Len:], c2)
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("cipher type not support")
|
||||||
|
}
|
||||||
|
|
||||||
|
return toData, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) encrypted(encData []byte, in []byte) bool {
|
||||||
|
encDataLen := len(encData)
|
||||||
|
|
||||||
|
for i := 0; i != encDataLen; i++ {
|
||||||
|
if encData[i] != in[i] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) Decrypt(input string) (string, error) {
|
||||||
|
|
||||||
|
tmpDataArr := strings.Split(input, "|")
|
||||||
|
if len(tmpDataArr) != 2 {
|
||||||
|
return "", fmt.Errorf("数据格式错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
keyAndIvStr := tmpDataArr[0]
|
||||||
|
encryptedBody := tmpDataArr[1]
|
||||||
|
|
||||||
|
data, err := base64.StdEncoding.DecodeString(keyAndIvStr)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("data is not base64 string: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
kvBase64Tmp, err := s.decrypt(data)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
kvTmp, err := base64.StdEncoding.DecodeString(kvBase64Tmp)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(kvTmp) != 33 {
|
||||||
|
return "", fmt.Errorf("iv长度不等于33")
|
||||||
|
}
|
||||||
|
|
||||||
|
plainKey := kvTmp[0:16]
|
||||||
|
plainIv := kvTmp[17:33]
|
||||||
|
|
||||||
|
data2, err := base64.StdEncoding.DecodeString(encryptedBody)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
plainText, err := sm4.CBCDecrypt(plainKey, plainIv, data2)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(utils.Padding(plainText, 0)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) decrypt(data []byte) (string, error) {
|
||||||
|
|
||||||
|
c1Len := 65
|
||||||
|
C1Byte := make([]byte, c1Len)
|
||||||
|
copy(C1Byte, data[:c1Len])
|
||||||
|
|
||||||
|
x, y := elliptic.Unmarshal(s.privateKey.Curve, C1Byte)
|
||||||
|
dBC1X, dBC1Y := s.privateKey.Curve.ScalarMult(x, y, s.privateKey.D.Bytes())
|
||||||
|
|
||||||
|
c2Len := len(data) - c1Len - s.c3Len
|
||||||
|
c2 := make([]byte, c2Len)
|
||||||
|
c3 := make([]byte, s.c3Len)
|
||||||
|
|
||||||
|
if s.cipherType == model.C1C2C3 {
|
||||||
|
copy(c2, data[c1Len:c1Len+c2Len])
|
||||||
|
copy(c3, data[c1Len+c2Len:])
|
||||||
|
} else if s.cipherType == model.C1C3C2 {
|
||||||
|
copy(c3, data[c1Len:c1Len+s.c3Len])
|
||||||
|
copy(c2, data[c1Len+s.c3Len:])
|
||||||
|
} else {
|
||||||
|
return "", fmt.Errorf("cipher type not support")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.sdk.Kdf(s.privateKey.Curve, dBC1X, dBC1Y, c2); err != nil {
|
||||||
|
return "", fmt.Errorf("kdf error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
u := s.sdk.CalculateHash(dBC1X, c2, dBC1Y)
|
||||||
|
if bytes.Compare(u, c3) == 0 {
|
||||||
|
return string(c2), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("decrypt error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) Sign(input []byte) (string, error) {
|
||||||
|
|
||||||
|
signData, err := s.sign(input)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64.StdEncoding.EncodeToString(signData), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) sign(data []byte) ([]byte, error) {
|
||||||
|
|
||||||
|
z := s.sdk.GetZ(s.privateKey.PublicKey.X, s.privateKey.PublicKey.Y, s.uid)
|
||||||
|
e := s.sdk.GetE(z, data)
|
||||||
|
|
||||||
|
c := s.privateKey.PublicKey.Curve
|
||||||
|
N := c.Params().N
|
||||||
|
|
||||||
|
if N.Sign() == 0 {
|
||||||
|
return nil, fmt.Errorf("invalid curve order")
|
||||||
|
}
|
||||||
|
|
||||||
|
var k, r, sb *big.Int
|
||||||
|
var err error
|
||||||
|
for {
|
||||||
|
for {
|
||||||
|
k, err = s.randFieldElement(c, rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("randFieldElement: %+v", err)
|
||||||
|
}
|
||||||
|
r, _ = s.privateKey.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(s.privateKey.D, r)
|
||||||
|
sb = new(big.Int).Sub(k, rD)
|
||||||
|
d1 := new(big.Int).Add(s.privateKey.D, model.One)
|
||||||
|
d1Inv := new(big.Int).ModInverse(d1, N)
|
||||||
|
sb.Mul(sb, d1Inv)
|
||||||
|
sb.Mod(sb, N)
|
||||||
|
if sb.Sign() != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signature := model.Signature{R: r, S: sb}
|
||||||
|
|
||||||
|
si, err := asn1.Marshal(signature)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("asn1.Marshal: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return si, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) randFieldElement(c elliptic.Curve, random io.Reader) (k *big.Int, err error) {
|
||||||
|
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, model.One)
|
||||||
|
k.Mod(k, n)
|
||||||
|
k.Add(k, model.One)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) Verify(input, sign string) (bool, error) {
|
||||||
|
|
||||||
|
signBytes, err := base64.StdEncoding.DecodeString(sign)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("signature is not base64 string: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
signature := model.Signature{}
|
||||||
|
_, err = asn1.Unmarshal(signBytes, &signature)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("signature is not asn1: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
ok := s.verify([]byte(input), signature)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) verifyBool(data []byte) bool {
|
||||||
|
if bytes.Equal(data, model.VerifyTrue) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cmb) verify(data []byte, signature model.Signature) bool {
|
||||||
|
|
||||||
|
c := s.publicKey.Curve
|
||||||
|
N := c.Params().N
|
||||||
|
|
||||||
|
if signature.R.Cmp(model.One) < 0 || signature.S.Cmp(model.One) < 0 {
|
||||||
|
return s.verifyBool(model.VerifyFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
if signature.R.Cmp(N) >= 0 || signature.S.Cmp(N) >= 0 {
|
||||||
|
return s.verifyBool(model.VerifyFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
z := s.sdk.GetZ(s.publicKey.X, s.publicKey.Y, s.uid)
|
||||||
|
e := s.sdk.GetE(z, data)
|
||||||
|
t := new(big.Int).Add(signature.R, signature.S)
|
||||||
|
t.Mod(t, N)
|
||||||
|
|
||||||
|
if t.Sign() == 0 {
|
||||||
|
return s.verifyBool(model.VerifyFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
var x *big.Int
|
||||||
|
x1, y1 := c.ScalarBaseMult(signature.S.Bytes())
|
||||||
|
x2, y2 := c.ScalarMult(s.publicKey.X, s.publicKey.Y, t.Bytes())
|
||||||
|
x, _ = c.Add(x1, y1, x2, y2)
|
||||||
|
|
||||||
|
x.Add(x, e)
|
||||||
|
x.Mod(x, N)
|
||||||
|
if x.Cmp(signature.R) == 0 {
|
||||||
|
return s.verifyBool(model.VerifyTrue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.verifyBool(model.VerifyFalse)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package cmbv2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCmb_EncryptDecrypt(t *testing.T) {
|
||||||
|
priKey := "8d39ff3d2559258c163f4510f082727f51531e1953ab203d5ab1ea4a6d94fd73"
|
||||||
|
pukKey := "04d827a7dbaaa358ce45b8c7794a7f54819f5c175005a702370e47f135ef6f5f9732758b1474f218419fe9e87f90c28c3b05f08254c651db27df35fae67b77b2e4"
|
||||||
|
|
||||||
|
n, err := NewCmb(priKey, pukKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("NewCmb() error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content := `{"name":"zhangxx","phoneNo":"137xxxxxxxx"}`
|
||||||
|
|
||||||
|
got, err := n.Encrypt([]byte(content))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Encrypt() error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(got)
|
||||||
|
|
||||||
|
got2, err := n.Decrypt(got)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Decrypt() error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(got2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCmb_SignVerify(t *testing.T) {
|
||||||
|
priKey := "8d39ff3d2559258c163f4510f082727f51531e1953ab203d5ab1ea4a6d94fd73"
|
||||||
|
pukKey := "04d827a7dbaaa358ce45b8c7794a7f54819f5c175005a702370e47f135ef6f5f9732758b1474f218419fe9e87f90c28c3b05f08254c651db27df35fae67b77b2e4"
|
||||||
|
|
||||||
|
n, err := NewCmb(priKey, pukKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("NewCmb() error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content := `{"name":"zhangxx","phoneNo":"137xxxxxxxx"}`
|
||||||
|
|
||||||
|
got, err := n.Sign([]byte(content))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Sign() error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(got)
|
||||||
|
|
||||||
|
got2, err := n.Verify(content, got)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Verify() error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(got2)
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,329 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/md5"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha1"
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/sha512"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/asn1"
|
||||||
|
"fmt"
|
||||||
|
"hash"
|
||||||
|
"math/big"
|
||||||
|
"reflect"
|
||||||
|
"voucher/internal/pkg/cmb/sm2/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* reference to RFC5959 and RFC2898
|
||||||
|
*/
|
||||||
|
|
||||||
|
var (
|
||||||
|
oidPBES2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 13} // id-PBES2(PBES2)
|
||||||
|
oidPBKDF2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 12} // id-PBKDF2
|
||||||
|
|
||||||
|
oidAES128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2}
|
||||||
|
oidAES256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42}
|
||||||
|
|
||||||
|
oidKEYMD5 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 5}
|
||||||
|
oidKEYSHA1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 7}
|
||||||
|
oidKEYSHA256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 9}
|
||||||
|
oidKEYSHA512 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 11}
|
||||||
|
|
||||||
|
oidSM2 = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
|
||||||
|
)
|
||||||
|
|
||||||
|
type Sm2PrivateKey struct {
|
||||||
|
Version int
|
||||||
|
PrivateKey []byte
|
||||||
|
NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
|
||||||
|
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type pkcs8 struct {
|
||||||
|
Version int
|
||||||
|
Algo pkix.AlgorithmIdentifier
|
||||||
|
PrivateKey []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncryptedPrivateKeyInfo reference to https://www.rfc-editor.org/rfc/rfc5958.txt
|
||||||
|
type EncryptedPrivateKeyInfo struct {
|
||||||
|
EncryptionAlgorithm Pbes2Algorithms
|
||||||
|
EncryptedData []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pbes2Algorithms reference to https://www.ietf.org/rfc/rfc2898.txt
|
||||||
|
type Pbes2Algorithms struct {
|
||||||
|
IdPBES2 asn1.ObjectIdentifier
|
||||||
|
Pbes2Params Pbes2Params
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pbes2Params reference to https://www.ietf.org/rfc/rfc2898.txt
|
||||||
|
type Pbes2Params struct {
|
||||||
|
KeyDerivationFunc Pbes2KDfs // PBES2-KDFs
|
||||||
|
EncryptionScheme Pbes2Encs // PBES2-Encs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pbes2KDfs reference to https://www.ietf.org/rfc/rfc2898.txt
|
||||||
|
type Pbes2KDfs struct {
|
||||||
|
IdPBKDF2 asn1.ObjectIdentifier
|
||||||
|
Pkdf2Params Pkdf2Params
|
||||||
|
}
|
||||||
|
type Pbes2Encs struct {
|
||||||
|
EncryAlgo asn1.ObjectIdentifier
|
||||||
|
IV []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pkdf2Params reference to https://www.ietf.org/rfc/rfc2898.txt
|
||||||
|
type Pkdf2Params struct {
|
||||||
|
Salt []byte
|
||||||
|
IterationCount int
|
||||||
|
Prf pkix.AlgorithmIdentifier
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePrivateKey(bytes []byte, pwd []byte) (*model.PrivateKey, error) {
|
||||||
|
var priKey Sm2PrivateKey
|
||||||
|
var err error
|
||||||
|
if pwd == nil {
|
||||||
|
priKey, err = ParsePKCS8UnEncryptedPrivateKey(bytes)
|
||||||
|
} else {
|
||||||
|
priKey, err = ParsePKCS8EncryptedPrivateKey(bytes, pwd)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parse private key err: %s", err.Error())
|
||||||
|
}
|
||||||
|
curve := NewP256Sm2()
|
||||||
|
k := new(big.Int).SetBytes(priKey.PrivateKey)
|
||||||
|
curveOrder := curve.Params().N
|
||||||
|
if k.Cmp(curveOrder) >= 0 {
|
||||||
|
return nil, fmt.Errorf("invalid elliptic curve private key value")
|
||||||
|
}
|
||||||
|
privateKey := make([]byte, (curveOrder.BitLen()+7)/8)
|
||||||
|
for len(priKey.PrivateKey) > len(privateKey) {
|
||||||
|
if priKey.PrivateKey[0] != 0 {
|
||||||
|
return nil, fmt.Errorf("invalid private key")
|
||||||
|
}
|
||||||
|
priKey.PrivateKey = priKey.PrivateKey[1:]
|
||||||
|
}
|
||||||
|
copy(privateKey[len(privateKey)-len(priKey.PrivateKey):], priKey.PrivateKey)
|
||||||
|
x, y := curve.ScalarBaseMult(privateKey)
|
||||||
|
return &model.PrivateKey{
|
||||||
|
PublicKey: &model.PublicKey{
|
||||||
|
Curve: curve,
|
||||||
|
X: x,
|
||||||
|
Y: y,
|
||||||
|
},
|
||||||
|
D: k,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePKCS8UnEncryptedPrivateKey(bytes []byte) (Sm2PrivateKey, error) {
|
||||||
|
var pk pkcs8
|
||||||
|
var priKey Sm2PrivateKey
|
||||||
|
|
||||||
|
if _, err := asn1.Unmarshal(bytes, &pk); err != nil {
|
||||||
|
return priKey, err
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(pk.Algo.Algorithm, oidSM2) {
|
||||||
|
return priKey, fmt.Errorf("not sm2 elliptic curve")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := asn1.Unmarshal(pk.PrivateKey, &priKey); err != nil {
|
||||||
|
return priKey, fmt.Errorf("privateKey is not sm2 private key: %s", err.Error())
|
||||||
|
}
|
||||||
|
return priKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePKCS8EncryptedPrivateKey(bytes, pwd []byte) (Sm2PrivateKey, error) {
|
||||||
|
var keyInfo EncryptedPrivateKeyInfo
|
||||||
|
var priKey Sm2PrivateKey
|
||||||
|
_, err := asn1.Unmarshal(bytes, &keyInfo)
|
||||||
|
if err != nil {
|
||||||
|
return priKey, fmt.Errorf("privateKey is not sm2 encrypted private key: %s", err.Error())
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(keyInfo.EncryptionAlgorithm.IdPBES2, oidPBES2) {
|
||||||
|
return priKey, fmt.Errorf("x509: only support PBES2")
|
||||||
|
}
|
||||||
|
encryptionScheme := keyInfo.EncryptionAlgorithm.Pbes2Params.EncryptionScheme
|
||||||
|
keyDerivationFunc := keyInfo.EncryptionAlgorithm.Pbes2Params.KeyDerivationFunc
|
||||||
|
if !reflect.DeepEqual(keyDerivationFunc.IdPBKDF2, oidPBKDF2) {
|
||||||
|
return priKey, fmt.Errorf("x509: only support PBKDF2")
|
||||||
|
}
|
||||||
|
pkdf2Params := keyDerivationFunc.Pkdf2Params
|
||||||
|
if !reflect.DeepEqual(encryptionScheme.EncryAlgo, oidAES128CBC) &&
|
||||||
|
!reflect.DeepEqual(encryptionScheme.EncryAlgo, oidAES256CBC) {
|
||||||
|
return priKey, fmt.Errorf("x509: only support AES")
|
||||||
|
}
|
||||||
|
iv := encryptionScheme.IV
|
||||||
|
salt := pkdf2Params.Salt
|
||||||
|
iter := pkdf2Params.IterationCount
|
||||||
|
encryptedKey := keyInfo.EncryptedData
|
||||||
|
var key []byte
|
||||||
|
switch {
|
||||||
|
case pkdf2Params.Prf.Algorithm.Equal(oidKEYMD5):
|
||||||
|
key = pbkdf(pwd, salt, iter, 32, md5.New)
|
||||||
|
break
|
||||||
|
case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA1):
|
||||||
|
key = pbkdf(pwd, salt, iter, 32, sha1.New)
|
||||||
|
break
|
||||||
|
case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA256):
|
||||||
|
key = pbkdf(pwd, salt, iter, 32, sha256.New)
|
||||||
|
break
|
||||||
|
case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA512):
|
||||||
|
key = pbkdf(pwd, salt, iter, 32, sha512.New)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return priKey, fmt.Errorf("x509: unknown hash algorithm")
|
||||||
|
}
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return priKey, err
|
||||||
|
}
|
||||||
|
mode := cipher.NewCBCDecrypter(block, iv)
|
||||||
|
mode.CryptBlocks(encryptedKey, encryptedKey)
|
||||||
|
return ParsePKCS8UnEncryptedPrivateKey(encryptedKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy from crypto/pbkdf2.go
|
||||||
|
func pbkdf(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
|
||||||
|
prf := hmac.New(h, password)
|
||||||
|
hashLen := prf.Size()
|
||||||
|
numBlocks := (keyLen + hashLen - 1) / hashLen
|
||||||
|
|
||||||
|
var buf [4]byte
|
||||||
|
dk := make([]byte, 0, numBlocks*hashLen)
|
||||||
|
U := make([]byte, hashLen)
|
||||||
|
for block := 1; block <= numBlocks; block++ {
|
||||||
|
// N.B.: || means concatenation, ^ means XOR
|
||||||
|
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
|
||||||
|
// U_1 = PRF(password, salt || uint(i))
|
||||||
|
prf.Reset()
|
||||||
|
prf.Write(salt)
|
||||||
|
buf[0] = byte(block >> 24)
|
||||||
|
buf[1] = byte(block >> 16)
|
||||||
|
buf[2] = byte(block >> 8)
|
||||||
|
buf[3] = byte(block)
|
||||||
|
prf.Write(buf[:4])
|
||||||
|
dk = prf.Sum(dk)
|
||||||
|
T := dk[len(dk)-hashLen:]
|
||||||
|
copy(U, T)
|
||||||
|
|
||||||
|
// U_n = PRF(password, U_(n-1))
|
||||||
|
for n := 2; n <= iter; n++ {
|
||||||
|
prf.Reset()
|
||||||
|
prf.Write(U)
|
||||||
|
U = U[:0]
|
||||||
|
U = prf.Sum(U)
|
||||||
|
for x := range U {
|
||||||
|
T[x] ^= U[x]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dk[:keyLen]
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalSm2PrivateKey(key *model.PrivateKey, pwd []byte) ([]byte, error) {
|
||||||
|
if pwd == nil {
|
||||||
|
return MarshalSm2UnEncryptedPrivateKey(key)
|
||||||
|
}
|
||||||
|
return MarshalSm2EncryptedPrivateKey(key, pwd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalSm2EncryptedPrivateKey(priKey *model.PrivateKey, pwd []byte) ([]byte, error) {
|
||||||
|
der, err := MarshalSm2UnEncryptedPrivateKey(priKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
iter := 2048
|
||||||
|
salt := make([]byte, 8)
|
||||||
|
iv := make([]byte, 16)
|
||||||
|
rand.Reader.Read(salt)
|
||||||
|
rand.Reader.Read(iv)
|
||||||
|
key := pbkdf(pwd, salt, iter, 32, sha1.New) // 默认是SHA1
|
||||||
|
padding := aes.BlockSize - len(der)%aes.BlockSize
|
||||||
|
if padding > 0 {
|
||||||
|
n := len(der)
|
||||||
|
der = append(der, make([]byte, padding)...)
|
||||||
|
for i := 0; i < padding; i++ {
|
||||||
|
der[n+i] = byte(padding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
encryptedKey := make([]byte, len(der))
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
mode := cipher.NewCBCEncrypter(block, iv)
|
||||||
|
mode.CryptBlocks(encryptedKey, der)
|
||||||
|
var algorithmIdentifier pkix.AlgorithmIdentifier
|
||||||
|
algorithmIdentifier.Algorithm = oidKEYSHA1
|
||||||
|
algorithmIdentifier.Parameters.Tag = 5
|
||||||
|
algorithmIdentifier.Parameters.IsCompound = false
|
||||||
|
algorithmIdentifier.Parameters.FullBytes = []byte{5, 0}
|
||||||
|
keyDerivationFunc := Pbes2KDfs{
|
||||||
|
oidPBKDF2,
|
||||||
|
Pkdf2Params{
|
||||||
|
salt,
|
||||||
|
iter,
|
||||||
|
algorithmIdentifier,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
encryptionScheme := Pbes2Encs{
|
||||||
|
oidAES256CBC,
|
||||||
|
iv,
|
||||||
|
}
|
||||||
|
pbes2Algorithms := Pbes2Algorithms{
|
||||||
|
oidPBES2,
|
||||||
|
Pbes2Params{
|
||||||
|
keyDerivationFunc,
|
||||||
|
encryptionScheme,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
encryptedPkey := EncryptedPrivateKeyInfo{
|
||||||
|
pbes2Algorithms,
|
||||||
|
encryptedKey,
|
||||||
|
}
|
||||||
|
return asn1.Marshal(encryptedPkey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalSm2UnEncryptedPrivateKey(key *model.PrivateKey) ([]byte, error) {
|
||||||
|
var r pkcs8
|
||||||
|
var pri Sm2PrivateKey
|
||||||
|
var algo pkix.AlgorithmIdentifier
|
||||||
|
|
||||||
|
algo.Algorithm = oidSM2
|
||||||
|
algo.Parameters.Class = 0
|
||||||
|
algo.Parameters.Tag = 6
|
||||||
|
algo.Parameters.IsCompound = false
|
||||||
|
algo.Parameters.FullBytes = []byte{6, 8, 42, 129, 28, 207, 85, 1, 130, 45} // asn1.Marshal(asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301})
|
||||||
|
pri.Version = 1
|
||||||
|
pri.NamedCurveOID = oidNamedCurveP256SM2
|
||||||
|
pri.PublicKey = asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}
|
||||||
|
pri.PrivateKey = key.D.Bytes()
|
||||||
|
r.Version = 0
|
||||||
|
r.Algo = algo
|
||||||
|
r.PrivateKey, _ = asn1.Marshal(pri)
|
||||||
|
return asn1.Marshal(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalSm2PublicKey(key *model.PublicKey) ([]byte, error) {
|
||||||
|
var r PKIXPublicKey
|
||||||
|
var algo pkix.AlgorithmIdentifier
|
||||||
|
|
||||||
|
if key.Curve.Params() != NewP256Sm2().Params() {
|
||||||
|
return nil, fmt.Errorf("x509: unsupported elliptic curve")
|
||||||
|
}
|
||||||
|
algo.Algorithm = oidSM2
|
||||||
|
algo.Parameters.Class = 0
|
||||||
|
algo.Parameters.Tag = 6
|
||||||
|
algo.Parameters.IsCompound = false
|
||||||
|
algo.Parameters.FullBytes = []byte{6, 8, 42, 129, 28, 207, 85, 1, 130, 45} // asn1.Marshal(asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301})
|
||||||
|
r.Algo = algo
|
||||||
|
r.BitString = asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}
|
||||||
|
return asn1.Marshal(r)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,209 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
"voucher/internal/pkg/cmbv2/model"
|
||||||
|
"voucher/internal/pkg/helper"
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSM4IV 获取SM4的IV
|
||||||
|
func GetSM4IV() []byte {
|
||||||
|
return RandomBytes(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandomBytes(length int) []byte {
|
||||||
|
str := "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"
|
||||||
|
buffer := make([]byte, length)
|
||||||
|
for i := 0; i < 16; i++ {
|
||||||
|
nextInt, _ := rand.Int(rand.Reader, big.NewInt(int64(len(str))))
|
||||||
|
buffer[i] = str[nextInt.Int64()]
|
||||||
|
}
|
||||||
|
return buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AssemblingByteArray(key, iv []byte) []byte {
|
||||||
|
os := make([]byte, 0)
|
||||||
|
os = append(os, key...)
|
||||||
|
os = append(os, []byte("|")...)
|
||||||
|
os = append(os, iv...)
|
||||||
|
return os
|
||||||
|
}
|
||||||
|
|
||||||
|
func SortStructStr(req interface{}) string {
|
||||||
|
kvRows := helper.SortStructFieldsByKey(req)
|
||||||
|
|
||||||
|
var strToBeSigned strings.Builder
|
||||||
|
for _, kv := range kvRows {
|
||||||
|
if kv.Key == "sign" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if kv.Value == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
strToBeSigned.WriteString(fmt.Sprintf("%s=%s&", kv.Key, kv.Value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimRight(strToBeSigned.String(), "&")
|
||||||
|
}
|
||||||
|
|
||||||
|
func BigIntToByte(n *big.Int) []byte {
|
||||||
|
byteArray := n.Bytes()
|
||||||
|
|
||||||
|
// If the bytes is not a multiple of 32, pad with zero bytes.
|
||||||
|
byteArrLen := len(byteArray)
|
||||||
|
KeyBytes := 32
|
||||||
|
if byteArrLen == KeyBytes {
|
||||||
|
return byteArray
|
||||||
|
}
|
||||||
|
byteArray = append(make([]byte, KeyBytes-byteArrLen), byteArray...)
|
||||||
|
|
||||||
|
// 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 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 HexToPrivateKey(params *Sm2P256Curve, d []byte) (*model.PrivateKey, error) {
|
||||||
|
k := new(big.Int).SetBytes(d)
|
||||||
|
|
||||||
|
c := NewP256Sm2()
|
||||||
|
|
||||||
|
//params := c.Params()
|
||||||
|
n := new(big.Int).Sub(params.N, model.One)
|
||||||
|
if k.Cmp(n) >= 0 {
|
||||||
|
return nil, fmt.Errorf("privateKey is overflow")
|
||||||
|
}
|
||||||
|
|
||||||
|
pri := &model.PrivateKey{
|
||||||
|
PublicKey: &model.PublicKey{},
|
||||||
|
D: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
pri.PublicKey.Curve = c
|
||||||
|
pri.D = k
|
||||||
|
pri.PublicKey.X, pri.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
|
||||||
|
|
||||||
|
return pri, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func HexToPublicKey(curve *Sm2P256Curve, d []byte) (*model.PublicKey, error) {
|
||||||
|
|
||||||
|
if len(d) == 65 && d[0] == byte(0x04) {
|
||||||
|
d = d[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(d) != 64 {
|
||||||
|
return nil, fmt.Errorf("publicKey is not 64 bytes: %d", len(d))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub := new(model.PublicKey)
|
||||||
|
|
||||||
|
pub.Curve = curve
|
||||||
|
|
||||||
|
pub.X = new(big.Int).SetBytes(d[:32])
|
||||||
|
pub.Y = new(big.Int).SetBytes(d[32:])
|
||||||
|
|
||||||
|
return pub, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrivateKeyToHex(key *model.PrivateKey) string {
|
||||||
|
return key.D.Text(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PublicKeyToHex(key *model.PublicKey) string {
|
||||||
|
x := key.X.Bytes()
|
||||||
|
y := key.Y.Bytes()
|
||||||
|
if n := len(x); n < 32 {
|
||||||
|
x = append(zeroByteSlice()[:32-n], x...)
|
||||||
|
}
|
||||||
|
if n := len(y); n < 32 {
|
||||||
|
y = append(zeroByteSlice()[:32-n], y...)
|
||||||
|
}
|
||||||
|
var c []byte
|
||||||
|
c = append(c, x...)
|
||||||
|
c = append(c, y...)
|
||||||
|
c = append([]byte{0x04}, c...)
|
||||||
|
return hex.EncodeToString(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 32byte
|
||||||
|
func zeroByteSlice() []byte {
|
||||||
|
return []byte{
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HexToSignature(hexStr string) (s model.Signature, err error) {
|
||||||
|
signData, err := hex.DecodeString(hexStr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rBy := make([]byte, 33)
|
||||||
|
copy(rBy[1:], signData[:32])
|
||||||
|
rBy[0] = 0x00
|
||||||
|
s.R = new(big.Int).SetBytes(rBy)
|
||||||
|
|
||||||
|
sBy := make([]byte, 33)
|
||||||
|
copy(sBy[1:], signData[32:64])
|
||||||
|
sBy[0] = 0x00
|
||||||
|
s.S = new(big.Int).SetBytes(sBy)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/asn1"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"voucher/internal/pkg/cmb/sm2/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
oidNamedCurveP256SM2 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301} // I get the SM2 ID through parsing the pem file generated by gmssl
|
||||||
|
)
|
||||||
|
|
||||||
|
// PKIXPublicKey reflects a PKIX public key structure. See SubjectPublicKeyInfo
|
||||||
|
// in RFC 3280.
|
||||||
|
type PKIXPublicKey struct {
|
||||||
|
Algo pkix.AlgorithmIdentifier
|
||||||
|
BitString asn1.BitString
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePublicKey(bytes []byte) (*model.PublicKey, error) {
|
||||||
|
var pk PKIXPublicKey
|
||||||
|
if _, err := asn1.Unmarshal(bytes, &pk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(pk.Algo.Algorithm, oidSM2) {
|
||||||
|
return nil, fmt.Errorf("not sm2 elliptic curve")
|
||||||
|
}
|
||||||
|
curve := NewP256Sm2()
|
||||||
|
x, y := elliptic.Unmarshal(curve, pk.BitString.Bytes)
|
||||||
|
return &model.PublicKey{
|
||||||
|
Curve: curve,
|
||||||
|
X: x,
|
||||||
|
Y: y,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue