frostfs-sdk-go/crypto/signature.go
Airat Arifullin 6281a25556
All checks were successful
/ DCO (pull_request) Successful in 1m17s
/ Lint (pull_request) Successful in 2m7s
/ Tests (1.19) (pull_request) Successful in 5m56s
/ Tests (1.20) (pull_request) Successful in 6m37s
[#100] types: Make sdk types as protobuf wrappers
Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-07-12 19:08:37 +03:00

112 lines
2.6 KiB
Go

package frostfscrypto
import (
"errors"
"fmt"
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
"github.com/golang/protobuf/proto"
)
// Signature represents a confirmation of data integrity received by the
// digital signature mechanism.
//
// Signature is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.Signature
// message. See ReadFromV2 / WriteToV2 methods.
//
// Note that direct typecast is not safe and may result in loss of compatibility:
//
// _ = Signature(refs.Signature{}) // not recommended
type Signature struct {
signature *refsgrpc.Signature
}
func NewSignature() Signature {
return Signature{
signature: &refsgrpc.Signature{},
}
}
// ReadFromV2 reads Signature from the refs.Signature message. Checks if the
// message conforms to FrostFS API V2 protocol.
//
// See also WriteToV2.
func (x *Signature) ReadFromV2(m *refsgrpc.Signature) error {
if len(m.GetKey()) == 0 {
return errors.New("missing public key")
} else if len(m.GetSign()) == 0 {
return errors.New("missing signature")
}
switch m.GetScheme() {
default:
return fmt.Errorf("unsupported scheme %v", m.GetSign())
case
refsgrpc.SignatureScheme_ECDSA_SHA512,
refsgrpc.SignatureScheme_ECDSA_RFC6979_SHA256,
refsgrpc.SignatureScheme_ECDSA_RFC6979_SHA256_WALLET_CONNECT:
}
if x.signature == nil {
x.signature = new(refsgrpc.Signature)
}
proto.Merge(x.signature, m)
return nil
}
// WriteToV2 writes Signature to the refs.Signature message.
// The message must not be nil.
//
// See also ReadFromV2.
func (x *Signature) WriteToV2(m *refsgrpc.Signature) {
m.Reset()
proto.Merge(m, x.signature)
}
// Calculate signs data using Signer and encodes public key for subsequent
// verification.
//
// Signer MUST NOT be nil.
//
// See also Verify.
func (x *Signature) Calculate(signer Signer, data []byte) error {
signature, err := signer.Sign(data)
if err != nil {
return fmt.Errorf("signer %T failure: %w", signer, err)
}
pub := signer.Public()
key := make([]byte, pub.MaxEncodedSize())
key = key[:pub.Encode(key)]
m := new(refsgrpc.Signature)
m.SetScheme(refsgrpc.SignatureScheme(signer.Scheme()))
m.SetSign(signature)
m.SetKey(key)
return x.ReadFromV2(m)
}
// Verify verifies data signature using encoded public key. True means valid
// signature.
//
// Verify fails if signature scheme is not supported (see RegisterScheme).
//
// See also Calculate.
func (x *Signature) Verify(data []byte) bool {
f, ok := publicKeys[Scheme(x.signature.GetScheme())]
if !ok {
return false
}
key := f()
err := key.Decode(x.signature.GetKey())
if err != nil {
return false
}
return key.Verify(data, x.signature.GetSign())
}