2020-08-12 14:03:11 +00:00
|
|
|
package signature
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/ecdsa"
|
2022-03-15 13:54:47 +00:00
|
|
|
"encoding/base64"
|
2022-02-22 11:25:43 +00:00
|
|
|
"fmt"
|
2020-08-12 14:03:11 +00:00
|
|
|
|
2022-02-22 11:25:43 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
2022-03-15 13:54:47 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/v2/util/signature/walletconnect"
|
2020-08-12 14:03:11 +00:00
|
|
|
crypto "github.com/nspcc-dev/neofs-crypto"
|
|
|
|
)
|
|
|
|
|
|
|
|
type cfg struct {
|
2022-03-02 10:15:36 +00:00
|
|
|
schemeFixed bool
|
|
|
|
scheme refs.SignatureScheme
|
2022-04-11 11:23:10 +00:00
|
|
|
buffer []byte
|
2020-08-12 14:03:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func defaultCfg() *cfg {
|
2022-03-02 10:15:36 +00:00
|
|
|
return new(cfg)
|
2022-02-22 11:25:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func verify(cfg *cfg, data []byte, sig *refs.Signature) error {
|
2022-03-02 10:15:36 +00:00
|
|
|
if !cfg.schemeFixed {
|
|
|
|
cfg.scheme = sig.GetScheme()
|
2022-02-22 11:25:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub := crypto.UnmarshalPublicKey(sig.GetKey())
|
2022-03-15 13:54:47 +00:00
|
|
|
if pub == nil {
|
|
|
|
return crypto.ErrEmptyPublicKey
|
|
|
|
}
|
2022-03-02 10:15:36 +00:00
|
|
|
|
|
|
|
switch cfg.scheme {
|
2022-02-22 11:25:43 +00:00
|
|
|
case refs.ECDSA_SHA512:
|
|
|
|
return crypto.Verify(pub, data, sig.GetSign())
|
|
|
|
case refs.ECDSA_RFC6979_SHA256:
|
|
|
|
return crypto.VerifyRFC6979(pub, data, sig.GetSign())
|
2022-03-15 13:54:47 +00:00
|
|
|
case refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT:
|
|
|
|
buf := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
|
|
|
|
base64.StdEncoding.Encode(buf, data)
|
|
|
|
if !walletconnect.Verify(pub, buf, sig.GetSign()) {
|
|
|
|
return crypto.ErrInvalidSignature
|
|
|
|
}
|
|
|
|
return nil
|
2022-02-22 11:25:43 +00:00
|
|
|
default:
|
2022-03-02 10:15:36 +00:00
|
|
|
return fmt.Errorf("unsupported signature scheme %s", cfg.scheme)
|
2022-02-22 11:25:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-02 10:15:36 +00:00
|
|
|
func sign(cfg *cfg, key *ecdsa.PrivateKey, data []byte) ([]byte, error) {
|
|
|
|
switch cfg.scheme {
|
2022-02-22 11:25:43 +00:00
|
|
|
case refs.ECDSA_SHA512:
|
|
|
|
return crypto.Sign(key, data)
|
|
|
|
case refs.ECDSA_RFC6979_SHA256:
|
|
|
|
return crypto.SignRFC6979(key, data)
|
2022-03-15 13:54:47 +00:00
|
|
|
case refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT:
|
|
|
|
buf := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
|
|
|
|
base64.StdEncoding.Encode(buf, data)
|
|
|
|
return walletconnect.Sign(key, buf)
|
2022-02-22 11:25:43 +00:00
|
|
|
default:
|
2022-03-02 10:15:36 +00:00
|
|
|
panic(fmt.Sprintf("unsupported scheme %s", cfg.scheme))
|
2020-08-12 14:03:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func SignWithRFC6979() SignOption {
|
|
|
|
return func(c *cfg) {
|
2022-03-02 10:15:36 +00:00
|
|
|
c.schemeFixed = true
|
|
|
|
c.scheme = refs.ECDSA_RFC6979_SHA256
|
2020-08-12 14:03:11 +00:00
|
|
|
}
|
|
|
|
}
|
2022-04-11 11:23:10 +00:00
|
|
|
|
|
|
|
// WithBuffer allows providing pre-allocated buffer for signature verification.
|
|
|
|
func WithBuffer(buf []byte) SignOption {
|
|
|
|
return func(c *cfg) {
|
|
|
|
c.buffer = buf
|
|
|
|
}
|
|
|
|
}
|
2022-03-15 13:54:47 +00:00
|
|
|
|
|
|
|
func SignWithWalletConnect() SignOption {
|
|
|
|
return func(c *cfg) {
|
|
|
|
c.scheme = refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT
|
|
|
|
}
|
|
|
|
}
|