github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/chat/flip/secret.go (about)

     1  package flip
     2  
     3  import (
     4  	"crypto/hmac"
     5  	"crypto/rand"
     6  	"crypto/sha256"
     7  	"fmt"
     8  	"sort"
     9  
    10  	chat1 "github.com/keybase/client/go/protocol/chat1"
    11  	gregor1 "github.com/keybase/client/go/protocol/gregor1"
    12  )
    13  
    14  func (s *Secret) XOR(t Secret) *Secret {
    15  	for i, b := range t {
    16  		s[i] = b ^ s[i]
    17  	}
    18  	return s
    19  }
    20  
    21  func (s Secret) IsNil() bool {
    22  	return bytesAreNil(s[:])
    23  }
    24  
    25  func bytesAreNil(v []byte) bool {
    26  	for _, b := range v {
    27  		if b != byte(0) {
    28  			return false
    29  		}
    30  	}
    31  	return true
    32  }
    33  
    34  func (s Secret) Hash() Secret {
    35  	h := sha256.New()
    36  	_, err := h.Write(s[:])
    37  	if err != nil {
    38  		panic(err)
    39  	}
    40  	tmp := h.Sum(nil)
    41  	var ret Secret
    42  	copy(ret[:], tmp)
    43  	return ret
    44  }
    45  
    46  func (s Secret) Eq(t Secret) bool {
    47  	return hmac.Equal(s[:], t[:])
    48  }
    49  
    50  type CommitmentPayload struct {
    51  	_struct bool                 `codec:",toarray"` //nolint
    52  	V       Version              `codec:"v" json:"v"`
    53  	U       gregor1.UID          `codec:"u" json:"u"`
    54  	D       gregor1.DeviceID     `codec:"d" json:"d"`
    55  	C       chat1.ConversationID `codec:"c" json:"c"`
    56  	G       chat1.FlipGameID     `codec:"i" json:"i"`
    57  	S       Time                 `codec:"s" json:"s"`
    58  }
    59  
    60  func (s Secret) computeCommitment(cp CommitmentPayload) (Commitment, error) {
    61  	var ret Commitment
    62  	hm := hmac.New(sha256.New, s[:])
    63  	raw, err := msgpackEncode(cp)
    64  	if err != nil {
    65  		return ret, err
    66  	}
    67  	_, err = hm.Write(raw)
    68  	if err != nil {
    69  		panic(err)
    70  	}
    71  	tmp := hm.Sum(nil)
    72  	copy(ret[:], tmp)
    73  	return ret, nil
    74  }
    75  
    76  func (c Commitment) Eq(d Commitment) bool {
    77  	return hmac.Equal(c[:], d[:])
    78  }
    79  
    80  func GenerateSecret() Secret {
    81  	var ret Secret
    82  	n, err := rand.Read(ret[:])
    83  	if n != len(ret) {
    84  		panic("failed to generate secret; short random read")
    85  	}
    86  	if err != nil {
    87  		panic(fmt.Sprintf("failed to generated secret: %s", err.Error()))
    88  	}
    89  	return ret
    90  }
    91  
    92  func checkUserDeviceCommitments(v []UserDeviceCommitment) bool {
    93  	for i := 1; i < len(v); i++ {
    94  		if !v[i-1].Ud.LessThan(v[i].Ud) {
    95  			return false
    96  		}
    97  	}
    98  	return true
    99  }
   100  
   101  func sortUserDeviceCommitments(v []UserDeviceCommitment) {
   102  	if !checkUserDeviceCommitments(v) {
   103  		sort.Slice(v, func(i, j int) bool { return v[i].Ud.LessThan(v[j].Ud) })
   104  	}
   105  }
   106  
   107  func hashUserDeviceCommitments(v []UserDeviceCommitment) (Hash, error) {
   108  	var ret Hash
   109  	sortUserDeviceCommitments(v)
   110  	raw, err := msgpackEncode(v)
   111  	if err != nil {
   112  		return ret, err
   113  	}
   114  	h := sha256.New()
   115  	_, err = h.Write(raw)
   116  	if err != nil {
   117  		panic(err)
   118  	}
   119  	tmp := h.Sum(nil)
   120  	copy(ret[:], tmp)
   121  	return ret, nil
   122  }