package wallet_sdk import ( "crypto/rand" "encoding/hex" "encoding/pem" "fmt" hds "git.yuanzoo.cn/zhangzhengqiang/popi-zxl/third_party/official/gosdk_demo/zxsdk/wallet_sdk/hdsignature" "git.yuanzoo.cn/zhangzhengqiang/popi-zxl/third_party/official/gosdk_demo/zxsdk/wallet_sdk/mnemonics" "math/big" "strconv" "time" ) 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 }