forked from TrueCloudLab/frostfs-sdk-go
[#190] crypto/ecdsa: Use separate types for RFC-6979 signature algo
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
7fe75d2cd9
commit
9f20d74d76
9 changed files with 105 additions and 124 deletions
|
@ -219,11 +219,8 @@ func (b *Token) Sign(key ecdsa.PrivateKey) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var sig neofscrypto.Signature
|
var sig neofscrypto.Signature
|
||||||
var signer neofsecdsa.Signer
|
|
||||||
|
|
||||||
signer.SetKey(key)
|
err = sig.Calculate(neofsecdsa.Signer(key), data)
|
||||||
|
|
||||||
err = sig.Calculate(signer, data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("calculate signature: %w", err)
|
return fmt.Errorf("calculate signature: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,12 +90,8 @@ func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResCon
|
||||||
}
|
}
|
||||||
|
|
||||||
var sig neofscrypto.Signature
|
var sig neofscrypto.Signature
|
||||||
var signer neofsecdsa.Signer
|
|
||||||
|
|
||||||
signer.SetKey(c.prm.key)
|
err = sig.Calculate(neofsecdsa.SignerRFC6979(c.prm.key), data)
|
||||||
signer.MakeDeterministic()
|
|
||||||
|
|
||||||
err = sig.Calculate(signer, data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("calculate signature: %w", err)
|
return nil, fmt.Errorf("calculate signature: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -442,12 +438,8 @@ func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (*
|
||||||
}
|
}
|
||||||
|
|
||||||
var sig neofscrypto.Signature
|
var sig neofscrypto.Signature
|
||||||
var signer neofsecdsa.Signer
|
|
||||||
|
|
||||||
signer.SetKey(c.prm.key)
|
err = sig.Calculate(neofsecdsa.SignerRFC6979(c.prm.key), data)
|
||||||
signer.MakeDeterministic()
|
|
||||||
|
|
||||||
err = sig.Calculate(signer, data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("calculate signature: %w", err)
|
return nil, fmt.Errorf("calculate signature: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -664,12 +656,8 @@ func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sig neofscrypto.Signature
|
var sig neofscrypto.Signature
|
||||||
var signer neofsecdsa.Signer
|
|
||||||
|
|
||||||
signer.SetKey(c.prm.key)
|
err = sig.Calculate(neofsecdsa.SignerRFC6979(c.prm.key), data)
|
||||||
signer.MakeDeterministic()
|
|
||||||
|
|
||||||
err = sig.Calculate(signer, data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("calculate signature: %w", err)
|
return nil, fmt.Errorf("calculate signature: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,17 +23,10 @@ func TestSignature(t *testing.T) {
|
||||||
|
|
||||||
for _, f := range []func() neofscrypto.Signer{
|
for _, f := range []func() neofscrypto.Signer{
|
||||||
func() neofscrypto.Signer {
|
func() neofscrypto.Signer {
|
||||||
var key neofsecdsa.Signer
|
return neofsecdsa.Signer(k.PrivateKey)
|
||||||
key.SetKey(k.PrivateKey)
|
|
||||||
|
|
||||||
return &key
|
|
||||||
},
|
},
|
||||||
func() neofscrypto.Signer {
|
func() neofscrypto.Signer {
|
||||||
var key neofsecdsa.Signer
|
return neofsecdsa.SignerRFC6979(k.PrivateKey)
|
||||||
key.SetKey(k.PrivateKey)
|
|
||||||
key.MakeDeterministic()
|
|
||||||
|
|
||||||
return &key
|
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
signer := f()
|
signer := f()
|
||||||
|
|
|
@ -8,9 +8,6 @@ func init() {
|
||||||
})
|
})
|
||||||
|
|
||||||
neofscrypto.RegisterScheme(neofscrypto.ECDSA_DETERMINISTIC_SHA256, func() neofscrypto.PublicKey {
|
neofscrypto.RegisterScheme(neofscrypto.ECDSA_DETERMINISTIC_SHA256, func() neofscrypto.PublicKey {
|
||||||
var key PublicKey
|
return new(PublicKeyRFC6979)
|
||||||
key.MakeDeterministic()
|
|
||||||
|
|
||||||
return &key
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,28 +11,11 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PublicKey implements neofscrypto.PublicKey based on ECDSA.
|
// PublicKey is a wrapper over ecdsa.PublicKey used for NeoFS needs.
|
||||||
|
// Provides neofscrypto.PublicKey interface.
|
||||||
//
|
//
|
||||||
// Supported schemes:
|
// Instances MUST be initialized from ecdsa.PublicKey using type conversion.
|
||||||
// - neofscrypto.ECDSA_SHA512 (default)
|
type PublicKey ecdsa.PublicKey
|
||||||
// - neofscrypto.ECDSA_DETERMINISTIC_SHA256
|
|
||||||
type PublicKey struct {
|
|
||||||
deterministic bool
|
|
||||||
|
|
||||||
key ecdsa.PublicKey
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetKey specifies ecdsa.PublicKey to be used for ECDSA signature verification.
|
|
||||||
func (x *PublicKey) SetKey(key ecdsa.PublicKey) {
|
|
||||||
x.key = key
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeDeterministic makes PublicKey to use Deterministic ECDSA scheme
|
|
||||||
// (see neofscrypto.ECDSA_DETERMINISTIC_SHA256). By default,
|
|
||||||
// neofscrypto.ECDSA_SHA512 is used.
|
|
||||||
func (x *PublicKey) MakeDeterministic() {
|
|
||||||
x.deterministic = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MaxEncodedSize returns size of the compressed ECDSA public key.
|
// MaxEncodedSize returns size of the compressed ECDSA public key.
|
||||||
func (x PublicKey) MaxEncodedSize() int {
|
func (x PublicKey) MaxEncodedSize() int {
|
||||||
|
@ -50,7 +33,7 @@ func (x PublicKey) Encode(buf []byte) int {
|
||||||
panic(fmt.Sprintf("too short buffer %d", len(buf)))
|
panic(fmt.Sprintf("too short buffer %d", len(buf)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return copy(buf, (*keys.PublicKey)(&x.key).Bytes())
|
return copy(buf, (*keys.PublicKey)(&x).Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode decodes compressed binary representation of the PublicKey.
|
// Decode decodes compressed binary representation of the PublicKey.
|
||||||
|
@ -62,7 +45,7 @@ func (x *PublicKey) Decode(data []byte) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
x.key = (ecdsa.PublicKey)(*pub)
|
*x = (PublicKey)(*pub)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -86,18 +69,58 @@ func unmarshalXY(data []byte) (x *big.Int, y *big.Int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify verifies data signature calculated by algorithm depending on
|
// Verify verifies data signature calculated by ECDSA algorithm with SHA-512 hashing.
|
||||||
// PublicKey state:
|
|
||||||
// - Deterministic ECDSA with SHA-256 hashing if MakeDeterministic called
|
|
||||||
// - ECDSA with SHA-512 hashing, otherwise
|
|
||||||
func (x PublicKey) Verify(data, signature []byte) bool {
|
func (x PublicKey) Verify(data, signature []byte) bool {
|
||||||
if x.deterministic {
|
|
||||||
h := sha256.Sum256(data)
|
|
||||||
return (*keys.PublicKey)(&x.key).Verify(signature, h[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
h := sha512.Sum512(data)
|
h := sha512.Sum512(data)
|
||||||
r, s := unmarshalXY(signature)
|
r, s := unmarshalXY(signature)
|
||||||
|
|
||||||
return r != nil && s != nil && ecdsa.Verify(&x.key, h[:], r, s)
|
return r != nil && s != nil && ecdsa.Verify((*ecdsa.PublicKey)(&x), h[:], r, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublicKeyRFC6979 is a wrapper over ecdsa.PublicKey used for NeoFS needs.
|
||||||
|
// Provides neofscrypto.PublicKey interface.
|
||||||
|
//
|
||||||
|
// Instances MUST be initialized from ecdsa.PublicKey using type conversion.
|
||||||
|
type PublicKeyRFC6979 ecdsa.PublicKey
|
||||||
|
|
||||||
|
// MaxEncodedSize returns size of the compressed ECDSA public key.
|
||||||
|
func (x PublicKeyRFC6979) MaxEncodedSize() int {
|
||||||
|
return 33
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode encodes ECDSA public key in compressed form into buf.
|
||||||
|
// Uses exactly MaxEncodedSize bytes of the buf.
|
||||||
|
//
|
||||||
|
// Encode panics if buf length is less than MaxEncodedSize.
|
||||||
|
//
|
||||||
|
// See also Decode.
|
||||||
|
func (x PublicKeyRFC6979) Encode(buf []byte) int {
|
||||||
|
if len(buf) < 33 {
|
||||||
|
panic(fmt.Sprintf("too short buffer %d", len(buf)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy(buf, (*keys.PublicKey)(&x).Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode decodes binary representation of the ECDSA public key.
|
||||||
|
//
|
||||||
|
// See also Encode.
|
||||||
|
func (x *PublicKeyRFC6979) Decode(data []byte) error {
|
||||||
|
pub, err := keys.NewPublicKeyFromBytes(data, elliptic.P256())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*x = (PublicKeyRFC6979)(*pub)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify verifies data signature calculated by deterministic ECDSA algorithm
|
||||||
|
// with SHA-256 hashing.
|
||||||
|
//
|
||||||
|
// See also RFC 6979.
|
||||||
|
func (x PublicKeyRFC6979) Verify(data, signature []byte) bool {
|
||||||
|
h := sha256.Sum256(data)
|
||||||
|
return (*keys.PublicKey)(&x).Verify(signature, h[:])
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,53 +10,23 @@ import (
|
||||||
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Signer implements neofscrypto.Signer based on ECDSA.
|
// Signer wraps ecdsa.PrivateKey and represents signer based on ECDSA with
|
||||||
|
// SHA-512 hashing. Provides neofscrypto.Signer interface.
|
||||||
//
|
//
|
||||||
// Supported schemes:
|
// Instances MUST be initialized from ecdsa.PrivateKey using type conversion.
|
||||||
// - neofscrypto.ECDSA_SHA512 (default)
|
type Signer ecdsa.PrivateKey
|
||||||
// - neofscrypto.ECDSA_DETERMINISTIC_SHA256
|
|
||||||
//
|
|
||||||
// Instances MUST be initialized with ecdsa.PrivateKey using SetKey.
|
|
||||||
type Signer struct {
|
|
||||||
deterministic bool
|
|
||||||
|
|
||||||
key ecdsa.PrivateKey
|
// Scheme returns neofscrypto.ECDSA_SHA512.
|
||||||
}
|
// Implements neofscrypto.Signer.
|
||||||
|
|
||||||
// SetKey specifies ecdsa.PrivateKey to be used for ECDSA signature calculation.
|
|
||||||
func (x *Signer) SetKey(key ecdsa.PrivateKey) {
|
|
||||||
x.key = key
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeDeterministic makes Signer to use Deterministic ECDSA scheme
|
|
||||||
// (see neofscrypto.ECDSA_DETERMINISTIC_SHA256). By default,
|
|
||||||
// neofscrypto.ECDSA_SHA512 is used.
|
|
||||||
func (x *Signer) MakeDeterministic() {
|
|
||||||
x.deterministic = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scheme returns signature scheme depending on Signer state:
|
|
||||||
// - neofscrypto.ECDSA_DETERMINISTIC_SHA256 if MakeDeterministic called
|
|
||||||
// - neofscrypto.ECDSA_SHA512 otherwise.
|
|
||||||
func (x Signer) Scheme() neofscrypto.Scheme {
|
func (x Signer) Scheme() neofscrypto.Scheme {
|
||||||
if x.deterministic {
|
|
||||||
return neofscrypto.ECDSA_DETERMINISTIC_SHA256
|
|
||||||
}
|
|
||||||
|
|
||||||
return neofscrypto.ECDSA_SHA512
|
return neofscrypto.ECDSA_SHA512
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign signs data with algorithm depending on Signer state:
|
// Sign signs data using ECDSA algorithm with SHA-512 hashing.
|
||||||
// - Deterministic ECDSA with SHA-256 hashing if MakeDeterministic called
|
// Implements neofscrypto.Signer.
|
||||||
// - ECDSA with SHA-512 hashing, otherwise
|
|
||||||
func (x Signer) Sign(data []byte) ([]byte, error) {
|
func (x Signer) Sign(data []byte) ([]byte, error) {
|
||||||
if x.deterministic {
|
|
||||||
p := keys.PrivateKey{PrivateKey: x.key}
|
|
||||||
return p.Sign(data), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
h := sha512.Sum512(data)
|
h := sha512.Sum512(data)
|
||||||
r, s, err := ecdsa.Sign(rand.Reader, &x.key, h[:])
|
r, s, err := ecdsa.Sign(rand.Reader, (*ecdsa.PrivateKey)(&x), h[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -64,13 +34,35 @@ func (x Signer) Sign(data []byte) ([]byte, error) {
|
||||||
return elliptic.Marshal(elliptic.P256(), r, s), nil
|
return elliptic.Marshal(elliptic.P256(), r, s), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Public initializes PublicKey and returns it as neofscrypto.PublicKey.
|
||||||
|
// Implements neofscrypto.Signer.
|
||||||
func (x Signer) Public() neofscrypto.PublicKey {
|
func (x Signer) Public() neofscrypto.PublicKey {
|
||||||
var pub PublicKey
|
return (*PublicKey)(&x.PublicKey)
|
||||||
pub.SetKey(x.key.PublicKey)
|
|
||||||
|
|
||||||
if x.deterministic {
|
|
||||||
pub.MakeDeterministic()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pub
|
// SignerRFC6979 wraps ecdsa.PrivateKey and represents signer based on deterministic
|
||||||
|
// ECDSA with SHA-256 hashing (RFC 6979). Provides neofscrypto.Signer interface.
|
||||||
|
//
|
||||||
|
// Instances SHOULD be initialized from ecdsa.PrivateKey using type conversion.
|
||||||
|
type SignerRFC6979 ecdsa.PrivateKey
|
||||||
|
|
||||||
|
// Scheme returns neofscrypto.ECDSA_DETERMINISTIC_SHA256.
|
||||||
|
// Implements neofscrypto.Signer.
|
||||||
|
func (x SignerRFC6979) Scheme() neofscrypto.Scheme {
|
||||||
|
return neofscrypto.ECDSA_DETERMINISTIC_SHA256
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign signs data using deterministic ECDSA algorithm with SHA-256 hashing.
|
||||||
|
// Implements neofscrypto.Signer.
|
||||||
|
//
|
||||||
|
// See also RFC 6979.
|
||||||
|
func (x SignerRFC6979) Sign(data []byte) ([]byte, error) {
|
||||||
|
p := keys.PrivateKey{PrivateKey: (ecdsa.PrivateKey)(x)}
|
||||||
|
return p.Sign(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public initializes PublicKeyRFC6979 and returns it as neofscrypto.PublicKey.
|
||||||
|
// Implements neofscrypto.Signer.
|
||||||
|
func (x SignerRFC6979) Public() neofscrypto.PublicKey {
|
||||||
|
return (*PublicKeyRFC6979)(&x.PublicKey)
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,11 +123,8 @@ func (id ID) CalculateIDSignature(key ecdsa.PrivateKey) (neofscrypto.Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
var sig neofscrypto.Signature
|
var sig neofscrypto.Signature
|
||||||
var signer neofsecdsa.Signer
|
|
||||||
|
|
||||||
signer.SetKey(key)
|
return sig, sig.Calculate(neofsecdsa.Signer(key), data)
|
||||||
|
|
||||||
return sig, sig.Calculate(signer, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal marshals ID into a protobuf binary form.
|
// Marshal marshals ID into a protobuf binary form.
|
||||||
|
|
|
@ -277,11 +277,8 @@ func (x *GlobalTrust) Sign(key *ecdsa.PrivateKey) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var sig neofscrypto.Signature
|
var sig neofscrypto.Signature
|
||||||
var signer neofsecdsa.Signer
|
|
||||||
|
|
||||||
signer.SetKey(*key)
|
err = sig.Calculate(neofsecdsa.Signer(*key), data)
|
||||||
|
|
||||||
err = sig.Calculate(signer, data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("calculate signature: %w", err)
|
return fmt.Errorf("calculate signature: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,11 +176,8 @@ func (t *Token) Sign(key *ecdsa.PrivateKey) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var sig neofscrypto.Signature
|
var sig neofscrypto.Signature
|
||||||
var signer neofsecdsa.Signer
|
|
||||||
|
|
||||||
signer.SetKey(*key)
|
err = sig.Calculate(neofsecdsa.Signer(*key), digest)
|
||||||
|
|
||||||
err = sig.Calculate(signer, digest)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue