[#78] POC wallet connect 2.0 verification
This commit is contained in:
parent
fc13e5407c
commit
24749d87bd
2 changed files with 116 additions and 0 deletions
|
@ -4,6 +4,7 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
|
@ -64,3 +65,50 @@ func TestSign(t *testing.T) {
|
|||
_, err = prepareBearerToken(bt, false, false)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestWalletConnect20Signature(t *testing.T) {
|
||||
stV10 := &SessionToken{
|
||||
BearerToken: BearerToken{
|
||||
Token: "ChAMDRXN+epG44eLachkJJQKEhsKGTV0c7bhRT/GDdQsm7gPCNG63g4isq97/E8aBgixAhjNASIhAzFSJMOEdkH6YbJYhHN0w1wrgiz/QFPZvQ2D/8oqNrQjMgQIARAB",
|
||||
Signature: "87f54d849fc887dfda7546b4edde6f83397cea798a0c5edf979149659007fbe868e7d8a3b6813c56a81c266a5d28956b28b59ba87cd6aff09d518bcfe11474276e5c3d4d714eb13d43601cae70aef11e",
|
||||
Key: "027e9b7e3b9f07b6bcb59b050f11616c78f433806d4314f7c72e5ac1d9f4d1fb02",
|
||||
},
|
||||
Verb: 1,
|
||||
}
|
||||
|
||||
stV20 := &SessionToken{
|
||||
BearerToken: BearerToken{
|
||||
Token: "ChBLgy6hRhBIpJVysyjM84OUEhsKGTV0c7bhRT/GDdQsm7gPCNG63g4isq97/E8aBgi0AhjQASIhAkwGSfK6lIf6HkuzG1YSSeFn5D/qIesknvBFTGN8qod5MgQIARAB",
|
||||
Signature: "e286951bfd1cc172b70fcd6a832d2121a5a635493a5b15c385b8001e676576df308898615cc25efc7fd649a7b3052453338b96671776d498c15cf032fdb072ec30f30aba0bb9375c6575fac8a4d4a19d",
|
||||
Key: "027e9b7e3b9f07b6bcb59b050f11616c78f433806d4314f7c72e5ac1d9f4d1fb02",
|
||||
},
|
||||
Verb: 1,
|
||||
}
|
||||
|
||||
_, err1 := prepareSessionToken(stV10, true)
|
||||
require.NoError(t, err1)
|
||||
|
||||
err2 := prepareSessionToken2(stV20)
|
||||
require.NoError(t, err2)
|
||||
|
||||
}
|
||||
|
||||
func prepareSessionToken2(st *SessionToken) error {
|
||||
data := []byte(st.Token)
|
||||
|
||||
signature, err := hex.DecodeString(st.Signature)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't decode signature: %w", err)
|
||||
}
|
||||
|
||||
ownerKey, err := keys.NewPublicKeyFromString(st.Key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't fetch session token owner key: %w", err)
|
||||
}
|
||||
|
||||
if !Verify((*ecdsa.PublicKey)(ownerKey), data, signature) {
|
||||
return fmt.Errorf("invalid signature")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
68
handlers/wallet_connect.go
Normal file
68
handlers/wallet_connect.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
)
|
||||
|
||||
const (
|
||||
// saltSize is the salt size added to signed message.
|
||||
saltSize = 16
|
||||
// signatureLen is the length of RFC6979 signature.
|
||||
signatureLen = 64
|
||||
)
|
||||
|
||||
// SignedMessage contains mirrors `SignedMessage` struct from the WalletConnect API.
|
||||
// https://neon.coz.io/wksdk/core/modules.html#SignedMessage
|
||||
type SignedMessage struct {
|
||||
Data []byte
|
||||
Message []byte
|
||||
PublicKey []byte
|
||||
Salt []byte
|
||||
}
|
||||
|
||||
// Verify verifies message using WalletConnect API.
|
||||
func Verify(p *ecdsa.PublicKey, data, sign []byte) bool {
|
||||
if len(sign) != signatureLen+saltSize {
|
||||
return false
|
||||
}
|
||||
|
||||
//salt := sign[signatureLen:]
|
||||
return VerifyMessage(p, SignedMessage{
|
||||
Data: sign[:signatureLen],
|
||||
Message: data,
|
||||
//Salt: salt,
|
||||
})
|
||||
}
|
||||
|
||||
// SignMessage signs message with a private key and returns structure similar to
|
||||
// `signMessage` of the WalletConnect API.
|
||||
// https://github.com/CityOfZion/wallet-connect-sdk/blob/eca3e5a4d9707c7a9c4d2828a7bf64222ce563ef/packages/wallet-connect-sdk-core/src/index.ts#L318
|
||||
// https://github.com/CityOfZion/neon-wallet/blob/a5a3ded5d2db80649a528a195a5914709df2d587/app/context/WalletConnect/helpers.js#L185
|
||||
func SignMessage(p *ecdsa.PrivateKey, msg []byte) (SignedMessage, error) {
|
||||
// It seems we have to fix sing in neofs-crypto
|
||||
// https://github.com/CityOfZion/neon-js/blob/f316675898117cddf03ea089e3177ef05877845f/packages/neon-core/src/wallet/signing.ts#L23
|
||||
// https://github.com/CityOfZion/neon-js/blob/f316675898117cddf03ea089e3177ef05877845f/packages/neon-core/src/u/basic/curve.ts#L32
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// VerifyMessage verifies message with a private key and returns structure similar to
|
||||
// `verifyMessage` of WalletConnect API.
|
||||
// https://github.com/CityOfZion/wallet-connect-sdk/blob/eca3e5a4d9707c7a9c4d2828a7bf64222ce563ef/packages/wallet-connect-sdk-core/src/index.ts#L345
|
||||
// https://github.com/CityOfZion/neon-wallet/blob/a5a3ded5d2db80649a528a195a5914709df2d587/app/context/WalletConnect/helpers.js#L197
|
||||
func VerifyMessage(p *ecdsa.PublicKey, m SignedMessage) bool {
|
||||
if p == nil {
|
||||
x, y := elliptic.UnmarshalCompressed(elliptic.P256(), m.PublicKey)
|
||||
if x == nil || y == nil {
|
||||
return false
|
||||
}
|
||||
p = &ecdsa.PublicKey{
|
||||
Curve: elliptic.P256(),
|
||||
X: x,
|
||||
Y: y,
|
||||
}
|
||||
}
|
||||
return crypto.VerifyRFC6979(p, m.Message, m.Data) == nil
|
||||
}
|
Reference in a new issue