git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/crypto/signature.go (about)

     1  package frostfscrypto
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
     8  )
     9  
    10  // Signature represents a confirmation of data integrity received by the
    11  // digital signature mechanism.
    12  //
    13  // Signature is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.Signature
    14  // message. See ReadFromV2 / WriteToV2 methods.
    15  //
    16  // Note that direct typecast is not safe and may result in loss of compatibility:
    17  //
    18  //	_ = Signature(refs.Signature{}) // not recommended
    19  type Signature refs.Signature
    20  
    21  // ReadFromV2 reads Signature from the refs.Signature message. Checks if the
    22  // message conforms to FrostFS API V2 protocol.
    23  //
    24  // See also WriteToV2.
    25  func (x *Signature) ReadFromV2(m refs.Signature) error {
    26  	if len(m.GetKey()) == 0 {
    27  		return errors.New("missing public key")
    28  	} else if len(m.GetSign()) == 0 {
    29  		return errors.New("missing signature")
    30  	}
    31  
    32  	switch m.GetScheme() {
    33  	default:
    34  		return fmt.Errorf("unsupported scheme %v", m.GetSign())
    35  	case
    36  		refs.ECDSA_SHA512,
    37  		refs.ECDSA_RFC6979_SHA256,
    38  		refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT:
    39  	}
    40  
    41  	*x = Signature(m)
    42  
    43  	return nil
    44  }
    45  
    46  // WriteToV2 writes Signature to the refs.Signature message.
    47  // The message must not be nil.
    48  //
    49  // See also ReadFromV2.
    50  func (x Signature) WriteToV2(m *refs.Signature) {
    51  	*m = (refs.Signature)(x)
    52  }
    53  
    54  // Calculate signs data using Signer and encodes public key for subsequent
    55  // verification.
    56  //
    57  // Signer MUST NOT be nil.
    58  //
    59  // See also Verify.
    60  func (x *Signature) Calculate(signer Signer, data []byte) error {
    61  	signature, err := signer.Sign(data)
    62  	if err != nil {
    63  		return fmt.Errorf("signer %T failure: %w", signer, err)
    64  	}
    65  
    66  	pub := signer.Public()
    67  
    68  	key := make([]byte, pub.MaxEncodedSize())
    69  	key = key[:pub.Encode(key)]
    70  
    71  	m := (*refs.Signature)(x)
    72  
    73  	m.SetScheme(refs.SignatureScheme(signer.Scheme()))
    74  	m.SetSign(signature)
    75  	m.SetKey(key)
    76  
    77  	return nil
    78  }
    79  
    80  // Verify verifies data signature using encoded public key. True means valid
    81  // signature.
    82  //
    83  // Verify fails if signature scheme is not supported (see RegisterScheme).
    84  //
    85  // See also Calculate.
    86  func (x Signature) Verify(data []byte) bool {
    87  	m := (*refs.Signature)(&x)
    88  
    89  	f, ok := publicKeys[Scheme(m.GetScheme())]
    90  	if !ok {
    91  		return false
    92  	}
    93  
    94  	key := f()
    95  
    96  	err := key.Decode(m.GetKey())
    97  	if err != nil {
    98  		return false
    99  	}
   100  
   101  	return key.Verify(data, m.GetSign())
   102  }