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 ¬EnoughSharesError{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 }