至信SDK
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
6.7 KiB

package wallet_sdk
import (
"crypto/rand"
"encoding/hex"
"encoding/pem"
"fmt"
"math/big"
"strconv"
"time"
hds "wallet_sdk/hdsignature"
"wallet_sdk/mnemonics"
)
const (
defaultEntropy = 128
)
var (
defaultIndexPathPrefix = []uint32{66, 0, 0, 0}
)
// Mnemonics
func CreateMnemonic() (string, error) {
entropy, err := mnemonics.NewEntropy(defaultEntropy)
if err != nil {
return "", err
}
return mnemonics.NewMnemonic(entropy)
}
// HD Signature
// DeriveKeyPair derives key pair strings for the node m/66/0/0/0/index
func DeriveKeyPair(mnemonic string, index uint32) (string, string, error) {
return DeriveKeyPairEncrypted(mnemonic, index, nil)
}
func DeriveKeyPairEncrypted(mnemonic string, index uint32, password []byte) (string, string, error) {
msk, _, err := hds.CreateMasterKey(mnemonic)
if err != nil {
return "", "", err
}
psk, err := msk.DeriveKeyPairObjFromFullPath(defaultIndexPathPrefix)
if err != nil {
return "", "", err
}
sk, err := psk.DeriveChildPrivateKey(index)
if err != nil {
return "", "", err
}
skPEM, err := sk.GetPrunedPEM(password)
if err != nil {
return "", "", err
}
pkPEM, err := sk.GetPublicKey().GetPrunedPEM()
if err != nil {
return "", "", err
}
return skPEM, pkPEM, nil
}
// DeriveKeyPairFullPath derives key pair strings for the node m/path[0]/...
func DeriveKeyPairFullPath(mnemonic string, path []uint32) (string, string, error) {
return DeriveKeyPairFullPathEncrypted(mnemonic, path, nil)
}
func DeriveKeyPairFullPathEncrypted(mnemonic string, path []uint32, password []byte) (string, string, error) {
msk, _, err := hds.CreateMasterKey(mnemonic)
if err != nil {
return "", "", err
}
sk, err := msk.DeriveKeyPairObjFromFullPath(path)
if err != nil {
return "", "", err
}
skPEM, err := sk.GetPrunedPEM(password)
if err != nil {
return "", "", err
}
pkPEM, err := sk.GetPublicKey().GetPrunedPEM()
if err != nil {
return "", "", err
}
return skPEM, pkPEM, nil
}
func PriKey2PubKey(pri string) (string, error) {
return EncryptedPriKey2PubKey(pri, nil)
}
func EncryptedPriKey2PubKey(pri string, password []byte) (string, error) {
sk, err := hds.ParsePrivateKey([]byte(pri), password)
if err != nil {
return "", err
}
return sk.GetPublicKey().GetPrunedPEM()
}
func PubKey2Address(pubKey string) (string, error) {
pk, err := hds.ParsePublicKey([]byte(pubKey))
if err != nil {
return "", err
}
return pk.GetAddress()
}
func PriKey2Address(priKey string) (string, error) {
return EncryptedPriKey2Address(priKey, nil)
}
func EncryptedPriKey2Address(priKey string, password []byte) (string, error) {
sk, err := hds.ParsePrivateKey([]byte(priKey), password)
if err != nil {
return "", err
}
return sk.GetAddress()
}
func SignByPriKey(priKey string, data string) (string, error) {
return SignByEncryptedPriKey(priKey, data, nil)
}
func SignByEncryptedPriKey(priKey string, data string, password []byte) (string, error) {
sk, err := hds.ParsePrivateKey([]byte(priKey), password)
if err != nil {
return "", err
}
sig, err := sk.Sign(data)
if err != nil {
return "", err
}
sigHex := hex.EncodeToString(sig)
return sigHex, nil
}
func VerifyByPubKey(pubKey string, signedData string, data string) (bool, error) {
pk, err := hds.ParsePublicKey([]byte(pubKey))
if err != nil {
return false, err
}
sig, err := hex.DecodeString(signedData)
if err != nil {
return false, err
}
return pk.Verify(data, sig)
}
func GetBase64PrivateKey(priKey string) (string, error) {
return GetBase64EncryptedPrivateKey(priKey, nil)
}
func GetBase64EncryptedPrivateKey(priKey string, password []byte) (string, error) {
sk, err := hds.ParsePrivateKey([]byte(priKey), password)
if err != nil {
return "", err
}
return sk.GetBase64String(password)
}
func GetBase64PublicKey(pubKey string) (string, error) {
pk, err := hds.ParsePublicKey([]byte(pubKey))
if err != nil {
return "", err
}
return pk.GetBase64String()
}
// Certificate with SM2 public key
// Create certificate request (csr)
func CreateCSR(priKey string, templateStr string) (string, error) {
return CreateCSRFromEncryptedPrivateKey(priKey, templateStr, nil)
}
func CreateCSRFromEncryptedPrivateKey(priKey string, templateStr string, password []byte) (string, error) {
sk, err := hds.ParsePrivateKey([]byte(priKey), password)
if err != nil {
return "", err
}
csr, err := sk.CreateCSRFromTemplatePEM(templateStr)
if err != nil {
return "", err
}
return string(csr), nil
}
func CheckSignatureValidity(sig string) (bool, error) {
sigBytes, err := hex.DecodeString(sig)
if err != nil {
return false, err
}
if len(sigBytes) < hds.SigMinLength || len(sigBytes) > hds.SigMaxLength {
return false, fmt.Errorf("invalid signature length (%d)", len(sig))
}
return true, nil
}
func CheckPublicKeyValidity(pubKey string) (bool, error) {
pubKeyBlock, _ := pem.Decode([]byte(pubKey))
if pubKeyBlock == nil {
return false, fmt.Errorf("invalid public key encoding")
}
if len(pubKeyBlock.Bytes) < hds.PubKeyMinLength || len(pubKeyBlock.Bytes) > hds.PubKeyMaxLength {
return false, fmt.Errorf("invalid public key length (%d)", len(pubKeyBlock.Bytes))
}
return true, nil
}
func CheckAddressValidity(address string) (bool, error) {
addressBytes := []byte(address)
prefix := string(addressBytes[:2])
pkHash := addressBytes[2:]
if len(pkHash) != hds.HDWAddressLength*2 {
return false, fmt.Errorf("hash part should be %d bytes", hds.HDWAddressLength*2)
}
_, err := hex.DecodeString(string(pkHash))
if err != nil {
return false, err
}
switch prefix {
case hds.ZXAddrPrefix, hds.ZXAddrPrefixV1, hds.ZXAddrPrefixV2, hds.ZXAddrPrefixV3:
return true, nil
default:
return false, fmt.Errorf("invalid prefix")
}
}
type SignData struct {
Signature string
SignatureTime string
Nonce int
}
const (
MaxRandNum = 1000000
MinRandNum = 100000
)
func GenerateApiSign(appId, appKey string) (signData *SignData, err error) {
now := time.Now()
signTime := strconv.FormatInt(now.UnixNano()/1e6, 10)
nonce, err := generateNonce()
if err != nil {
return nil, err
}
signData = &SignData{}
signStr := ""
if appId != "" && appKey != "" {
signStr = appId + "&" + appKey + "&" + signTime + "&" + strconv.Itoa(nonce)
} else {
signStr = signTime + "&" + strconv.Itoa(nonce)
}
sign, err := hds.SM3HMAC([]byte(appKey), []byte(signStr))
if err != nil {
return nil, err
}
signData.Signature = hex.EncodeToString(sign)
signData.SignatureTime = signTime
signData.Nonce = nonce
return signData, nil
}
func generateNonce() (int, error) {
b := new(big.Int).SetInt64(MaxRandNum)
randNum, err := rand.Int(rand.Reader, b)
if err != nil {
return -1, err
}
nonce := int(randNum.Int64())
if nonce < MinRandNum {
nonce = nonce + MinRandNum
}
return nonce, nil
}