Merge branch 'blockvision_main'

This commit is contained in:
miancan
2024-05-31 16:47:06 +08:00
5 changed files with 167 additions and 30 deletions

10
constant/intent.go Normal file
View File

@@ -0,0 +1,10 @@
package constant
type IntentScope = uint8
const (
TransactionDataIntentScope IntentScope = 0
TransactionEffectsIntentScope IntentScope = 1
CheckpointSummaryIntentScope IntentScope = 2
PersonalMessageIntentScope IntentScope = 3
)

27
models/intent.go Normal file
View File

@@ -0,0 +1,27 @@
package models
import "github.com/block-vision/sui-go-sdk/constant"
type AppId int
const (
Sui AppId = 0
)
type IntentVersion int
const (
V0 IntentVersion = 0
)
func IntentWithScope(intentScope constant.IntentScope) []int {
return []int{int(intentScope), int(V0), int(Sui)}
}
func NewMessageWithIntent(message []byte, scope constant.IntentScope) []byte {
intent := []byte{scope, 0, 0}
intentMessage := make([]byte, len(intent)+len(message))
copy(intentMessage, intent)
copy(intentMessage[len(intent):], message)
return intentMessage
}

View File

@@ -5,9 +5,13 @@ import (
"crypto/ed25519"
"encoding/base64"
"encoding/hex"
"golang.org/x/crypto/blake2b"
"fmt"
"log"
"strings"
"github.com/block-vision/sui-go-sdk/constant"
"golang.org/x/crypto/blake2b"
)
type InputObjectKind map[string]interface{}
@@ -38,6 +42,12 @@ type HexData struct {
data []byte
}
type SignaturePubkeyPair struct {
SignatureScheme string
Signature []byte
PubKey []byte
}
func NewHexData(str string) (*HexData, error) {
if strings.HasPrefix(str, "0x") || strings.HasPrefix(str, "0X") {
str = str[2:]
@@ -113,7 +123,7 @@ func (txn *TxnMetaData) SignSerializedSigWith(privateKey ed25519.PrivateKey) *Si
}
return &SignedTransactionSerializedSig{
TxBytes: txn.TxBytes,
Signature: toSerializedSignature(sigBytes, privateKey.Public().(ed25519.PublicKey)),
Signature: ToSerializedSignature(sigBytes, privateKey.Public().(ed25519.PublicKey)),
}
}
@@ -125,7 +135,7 @@ func messageWithIntent(message []byte) []byte {
return intentMessage
}
func toSerializedSignature(signature, pubKey []byte) string {
func ToSerializedSignature(signature, pubKey []byte) string {
signatureLen := len(signature)
pubKeyLen := len(pubKey)
serializedSignature := make([]byte, 1+signatureLen+pubKeyLen)
@@ -134,3 +144,76 @@ func toSerializedSignature(signature, pubKey []byte) string {
copy(serializedSignature[1+signatureLen:], pubKey)
return base64.StdEncoding.EncodeToString(serializedSignature)
}
func FromSerializedSignature(serializedSignature string) (*SignaturePubkeyPair, error) {
_bytes, err := base64.StdEncoding.DecodeString(serializedSignature)
if err != nil {
return nil, err
}
signatureScheme := parseSignatureScheme(_bytes[0])
if strings.EqualFold(serializedSignature, "") {
return nil, fmt.Errorf("multiSig is not supported")
}
signature := _bytes[1 : len(_bytes)-32]
pubKeyBytes := _bytes[1+len(signature):]
keyPair := &SignaturePubkeyPair{
SignatureScheme: signatureScheme,
Signature: signature,
PubKey: pubKeyBytes,
}
return keyPair, nil
}
func parseSignatureScheme(scheme byte) string {
switch scheme {
case 0:
return "ED25519"
case 1:
return "Secp256k1"
case 2:
return "Secp256r1"
case 3:
return "MultiSig"
default:
return "ED25519"
}
}
func VerifyPersonalMessage(message string, signature string) (signer string, pass bool, err error) {
b64Message := base64.StdEncoding.EncodeToString([]byte(message))
return VerifyMessage(b64Message, signature, constant.PersonalMessageIntentScope)
}
func VerifyTransaction(b64Message string, signature string) (signer string, pass bool, err error) {
return VerifyMessage(b64Message, signature, constant.TransactionDataIntentScope)
}
func VerifyMessage(message, signature string, scope constant.IntentScope) (signer string, pass bool, err error) {
b64Bytes, _ := base64.StdEncoding.DecodeString(message)
messageBytes := NewMessageWithIntent(b64Bytes, scope)
serializedSignature, err := FromSerializedSignature(signature)
if err != nil {
return "", false, err
}
digest := blake2b.Sum256(messageBytes)
pass = ed25519.Verify(serializedSignature.PubKey[:], digest[:], serializedSignature.Signature)
signer = Ed25519PublicKeyToSuiAddress(serializedSignature.PubKey)
if err != nil {
return "", false, fmt.Errorf("invalid signer %v", err)
}
return
}
func Ed25519PublicKeyToSuiAddress(pubKey []byte) string {
newPubkey := []byte{byte(SigFlagEd25519)}
newPubkey = append(newPubkey, pubKey...)
addrBytes := blake2b.Sum256(newPubkey)
return fmt.Sprintf("0x%s", hex.EncodeToString(addrBytes[:])[:64])
}

View File

@@ -1,27 +0,0 @@
package signer
type AppId int
const (
Sui AppId = 0
)
type IntentVersion int
const (
V0 IntentVersion = 0
)
type IntentScope int
const (
TransactionData IntentScope = 0
TransactionEffects IntentScope = 1
CheckpointSummary IntentScope = 2
PersonalMessage IntentScope = 3
)
func IntentWithScope(intentScope IntentScope) []int {
return []int{int(intentScope), int(V0), int(Sui)}
}

View File

@@ -1,9 +1,14 @@
package signer
import (
"crypto"
"crypto/ed25519"
"encoding/base64"
"encoding/hex"
"github.com/block-vision/sui-go-sdk/common/keypair"
"github.com/block-vision/sui-go-sdk/constant"
"github.com/block-vision/sui-go-sdk/models"
"github.com/tyler-smith/go-bip39"
"golang.org/x/crypto/blake2b"
)
@@ -49,3 +54,42 @@ func NewSignertWithMnemonic(mnemonic string) (*Signer, error) {
}
return NewSigner(key.Key), nil
}
type SignedMessageSerializedSig struct {
Message string `json:"message"`
Signature string `json:"signature"`
}
func (s *Signer) SignMessage(data string, scope constant.IntentScope) (*SignedMessageSerializedSig, error) {
txBytes, _ := base64.StdEncoding.DecodeString(data)
message := models.NewMessageWithIntent(txBytes, scope)
digest := blake2b.Sum256(message)
var noHash crypto.Hash
sigBytes, err := s.PriKey.Sign(nil, digest[:], noHash)
if err != nil {
return nil, err
}
ret := &SignedMessageSerializedSig{
Message: data,
Signature: models.ToSerializedSignature(sigBytes, s.PriKey.Public().(ed25519.PublicKey)),
}
return ret, nil
}
func (s *Signer) SignTransaction(b64TxBytes string) (*models.SignedTransactionSerializedSig, error) {
result, err := s.SignMessage(b64TxBytes, constant.PersonalMessageIntentScope)
if err != nil {
return nil, err
}
return &models.SignedTransactionSerializedSig{
TxBytes: result.Message,
Signature: result.Signature,
}, nil
}
func (s *Signer) SignPersonalMessage(message string) (*SignedMessageSerializedSig, error) {
b64Message := base64.StdEncoding.EncodeToString([]byte(message))
return s.SignMessage(b64Message, constant.PersonalMessageIntentScope)
}