github.com/onflow/flow-go/crypto@v0.24.8/thresholdsign.go (about)

     1  package crypto
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  )
     7  
     8  // A threshold signature scheme allows any subset of (t+1)
     9  // valid signature shares to reconstruct the threshold signature.
    10  // Up to (t) shares do not reveal any information about the threshold
    11  // signature.
    12  // Although the API allows using arbitrary values of (t),
    13  // the threshold signature scheme is secure in the presence of up to (t)
    14  // malicious participants when (t < n/2).
    15  // In order to optimize equally for unforgeability and robustness,
    16  // the input threshold value (t) should be set to t = floor((n-1)/2).
    17  
    18  const (
    19  	// ThresholdSignMinSize is the minimum size of a group participating in a threshold signature protocol
    20  	ThresholdSignMinSize = MinimumThreshold + 1
    21  	// ThresholdSignMaxSize is the maximum size of a group participating in a threshold signature protocol
    22  	ThresholdSignMaxSize = DKGMaxSize
    23  )
    24  
    25  // ThresholdSignatureInspector is an inspector of the threshold signature protocol.
    26  // The interface only allows inspecting the threshold signing protocol without taking part in it.
    27  type ThresholdSignatureInspector interface {
    28  	// VerifyShare verifies the input signature against the stored message and stored
    29  	// key at the input index. This function does not update the internal state.
    30  	// The function is thread-safe.
    31  	// Returns:
    32  	//  - (true, nil) if the signature is valid
    33  	//  - (false, nil) if `orig` is a valid index but the signature share is invalid
    34  	//  - (false, InvalidInputsError) if `orig` is an invalid index value
    35  	//  - (false, error) for all other unexpected errors
    36  	VerifyShare(orig int, share Signature) (bool, error)
    37  
    38  	// VerifyThresholdSignature verifies the input signature against the stored
    39  	// message and stored group public key. It does not update the internal state.
    40  	// The function is thread-safe.
    41  	// Returns:
    42  	//  - (true, nil) if the signature is valid
    43  	//  - (false, nil) if the signature is invalid
    44  	//  - (false, error) for all other unexpected errors
    45  	VerifyThresholdSignature(thresholdSignature Signature) (bool, error)
    46  
    47  	// EnoughShares indicates whether enough shares have been accumulated in order to reconstruct
    48  	// a group signature. This function is thread safe and locks the internal state.
    49  	// Returns:
    50  	//  - true if and only if at least (threshold+1) shares were added
    51  	EnoughShares() bool
    52  
    53  	// TrustedAdd adds a signature share to the internal pool of shares
    54  	// without verifying the signature against the message and the participant's
    55  	// public key. This function is thread safe and locks the internal state.
    56  	//
    57  	// The share is only added if the signer index is valid and has not been
    58  	// added yet. Moreover, the share is added only if not enough shares were collected.
    59  	// The function returns:
    60  	//  - (true, nil) if enough signature shares were already collected and no error occurred
    61  	//  - (false, nil) if not enough shares were collected and no error occurred
    62  	//  - (false, InvalidInputsError) if index is invalid
    63  	//  - (false, duplicatedSignerError) if a signature for the index was previously added
    64  	TrustedAdd(orig int, share Signature) (bool, error)
    65  
    66  	// VerifyAndAdd verifies a signature share (same as `VerifyShare`),
    67  	// and may or may not add the share to the local pool of shares.
    68  	// This function is thread safe and locks the internal state.
    69  	//
    70  	// The share is only added if the signature is valid, the signer index is valid and has not been
    71  	// added yet. Moreover, the share is added only if not enough shares were collected.
    72  	// Boolean returns:
    73  	//  - First boolean output is true if the share is valid and no error is returned, and false otherwise.
    74  	//  - Second boolean output is true if enough shares were collected and no error is returned, and false otherwise.
    75  	// Error returns:
    76  	//  - invalidInputsError if input index is invalid. A signature that doesn't verify against the signer's
    77  	//    public key is not considered an invalid input.
    78  	//  - duplicatedSignerError if signer was already added.
    79  	//  - other errors if an unexpected exception occurred.
    80  	VerifyAndAdd(orig int, share Signature) (bool, bool, error)
    81  
    82  	// HasShare checks whether the internal map contains the share of the given index.
    83  	// This function is thread safe.
    84  	// The function errors with InvalidInputsError if the index is invalid.
    85  	HasShare(orig int) (bool, error)
    86  
    87  	// ThresholdSignature returns the threshold signature if the threshold was reached.
    88  	// The threshold signature is reconstructed only once and is cached for subsequent calls.
    89  	//
    90  	// Returns:
    91  	// - (signature, nil) if no error occurred
    92  	// - (nil, notEnoughSharesError) if not enough shares were collected
    93  	// - (nil, invalidSignatureError) if at least one collected share does not serialize to a valid BLS signature.
    94  	// - (nil, invalidInputsError) if the constructed signature failed to verify against the group public key and stored message. This post-verification
    95  	//    is required  for safety, as `TrustedAdd` allows adding invalid signatures.
    96  	// - (nil, error) for any other unexpected error.
    97  	ThresholdSignature() (Signature, error)
    98  }
    99  
   100  // ThresholdSignatureParticipant is a participant in a threshold signature protocol.
   101  // A participant is able to participate in a threshold signing protocol as well as inspecting the
   102  // protocol.
   103  type ThresholdSignatureParticipant interface {
   104  	ThresholdSignatureInspector
   105  	// SignShare generates a signature share using the current private key share.
   106  	//
   107  	// The function does not add the share to the internal pool of shares and do
   108  	// not update the internal state.
   109  	// This function is thread safe
   110  	// No error is expected unless an unexpected exception occurs
   111  	SignShare() (Signature, error)
   112  }
   113  
   114  // duplicatedSignerError is an error returned when TrustedAdd or VerifyAndAdd encounter
   115  // a signature share that has been already added to the internal state.
   116  type duplicatedSignerError struct {
   117  	error
   118  }
   119  
   120  // duplicatedSignerErrorf constructs a new duplicatedSignerError
   121  func duplicatedSignerErrorf(msg string, args ...interface{}) error {
   122  	return &duplicatedSignerError{error: fmt.Errorf(msg, args...)}
   123  }
   124  
   125  // IsDuplicatedSignerError checks if the input error is a duplicatedSignerError
   126  func IsDuplicatedSignerError(err error) bool {
   127  	var target *duplicatedSignerError
   128  	return errors.As(err, &target)
   129  }
   130  
   131  // notEnoughSharesError is an error returned when ThresholdSignature is called
   132  // and not enough shares have been collected.
   133  type notEnoughSharesError struct {
   134  	error
   135  }
   136  
   137  // notEnoughSharesErrorf constructs a new notEnoughSharesError
   138  func notEnoughSharesErrorf(msg string, args ...interface{}) error {
   139  	return &notEnoughSharesError{error: fmt.Errorf(msg, args...)}
   140  }
   141  
   142  // IsNotEnoughSharesError checks if the input error is a notEnoughSharesError
   143  func IsNotEnoughSharesError(err error) bool {
   144  	var target *notEnoughSharesError
   145  	return errors.As(err, &target)
   146  }