Initial commit
This commit is contained in:
@@ -0,0 +1,300 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user