github.com/cloudflare/circl@v1.5.0/tss/rsa/signShare.go (about) 1 package rsa 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "math" 7 "math/big" 8 ) 9 10 // SignShare represents a portion of a signature. It is generated when a message is signed by a KeyShare. t SignShare's are then combined by calling CombineSignShares, where t is the Threshold. 11 type SignShare struct { 12 xi *big.Int 13 14 Index uint 15 16 Players uint 17 Threshold uint 18 } 19 20 func (s SignShare) String() string { 21 return fmt.Sprintf("(t,n): (%v,%v) index: %v xi: 0x%v", 22 s.Threshold, s.Players, s.Index, s.xi.Text(16)) 23 } 24 25 // MarshalBinary encodes SignShare into a byte array in a format readable by UnmarshalBinary. 26 // Note: Only Index's up to math.MaxUint16 are supported 27 func (s *SignShare) MarshalBinary() ([]byte, error) { 28 // | Players: uint16 | Threshold: uint16 | Index: uint16 | xiLen: uint16 | xi: []byte | 29 30 if s.Players > math.MaxUint16 { 31 return nil, fmt.Errorf("rsa_threshold: signshare marshall: Players is too big to fit in a uint16") 32 } 33 34 if s.Threshold > math.MaxUint16 { 35 return nil, fmt.Errorf("rsa_threshold: signshare marshall: Threshold is too big to fit in a uint16") 36 } 37 38 if s.Index > math.MaxUint16 { 39 return nil, fmt.Errorf("rsa_threshold: signshare marshall: Index is too big to fit in a uint16") 40 } 41 42 players := uint16(s.Players) 43 threshold := uint16(s.Threshold) 44 index := uint16(s.Index) 45 46 xiBytes := s.xi.Bytes() 47 xiLen := len(xiBytes) 48 49 if xiLen > math.MaxInt16 { 50 return nil, fmt.Errorf("rsa_threshold: signshare marshall: xiBytes is too big to fit it's length in a uint16") 51 } 52 53 if xiLen == 0 { 54 xiLen = 1 55 xiBytes = []byte{0} 56 } 57 58 blen := 2 + 2 + 2 + 2 + xiLen 59 out := make([]byte, blen) 60 61 binary.BigEndian.PutUint16(out[0:2], players) 62 binary.BigEndian.PutUint16(out[2:4], threshold) 63 binary.BigEndian.PutUint16(out[4:6], index) 64 65 binary.BigEndian.PutUint16(out[6:8], uint16(xiLen)) 66 67 copy(out[8:8+xiLen], xiBytes) 68 69 return out, nil 70 } 71 72 // UnmarshalBinary converts a byte array outputted from Marshall into a SignShare or returns an error if the value is invalid 73 func (s *SignShare) UnmarshalBinary(data []byte) error { 74 // | Players: uint16 | Threshold: uint16 | Index: uint16 | xiLen: uint16 | xi: []byte | 75 if len(data) < 8 { 76 return fmt.Errorf("rsa_threshold: signshare unmarshalKeyShareTest failed: data length was too short for reading Players, Threshold, Index, and xiLen") 77 } 78 79 players := binary.BigEndian.Uint16(data[0:2]) 80 threshold := binary.BigEndian.Uint16(data[2:4]) 81 index := binary.BigEndian.Uint16(data[4:6]) 82 xiLen := binary.BigEndian.Uint16(data[6:8]) 83 84 if xiLen == 0 { 85 return fmt.Errorf("rsa_threshold: signshare unmarshalKeyShareTest failed: xi is a required field but xiLen was 0") 86 } 87 88 if uint16(len(data[8:])) < xiLen { 89 return fmt.Errorf("rsa_threshold: signshare unmarshalKeyShareTest failed: data length was too short for reading xi, needed: %d found: %d", xiLen, len(data[6:])) 90 } 91 92 xi := big.Int{} 93 bytes := make([]byte, xiLen) 94 copy(bytes, data[8:8+xiLen]) 95 xi.SetBytes(bytes) 96 97 s.Players = uint(players) 98 s.Threshold = uint(threshold) 99 s.Index = uint(index) 100 s.xi = &xi 101 102 return nil 103 }