github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/uidmap/hardcoded_uids.go (about) 1 package uidmap 2 3 import ( 4 "bytes" 5 "compress/zlib" 6 "fmt" 7 "io" 8 "sort" 9 "sync" 10 11 "github.com/keybase/client/go/libkb" 12 keybase1 "github.com/keybase/client/go/protocol/keybase1" 13 ) 14 15 var offsets []uint32 16 var usernames []byte 17 var once sync.Once 18 19 // Map of sorted location -> unsorted location, so we can binary search the usernames 20 var usernameSortOrder []uint16 21 var usoOnce sync.Once 22 23 func findInit() { 24 once.Do(func() { 25 initUsernameOffsets() 26 initUsernames() 27 }) 28 } 29 30 func usernameFindInit() { 31 usoOnce.Do(initUsernameSort) 32 } 33 34 func usernameBytesAtSortedIndex(i int) []byte { 35 j := usernameSortOrder[i] 36 o := offsets[j] 37 return usernames[o : o+uint32(lengths[j])] 38 } 39 40 func usernameAtSortedIndex(i int) string { 41 return string(usernameBytesAtSortedIndex(i)) 42 } 43 44 func initUsernameSort() { 45 findInit() 46 usernameSortOrder = make([]uint16, len(lengths)) 47 for i := 0; i < len(lengths); i++ { 48 usernameSortOrder[i] = uint16(i) 49 } 50 sort.SliceStable(usernameSortOrder, func(i, j int) bool { 51 return bytes.Compare(usernameBytesAtSortedIndex(i), usernameBytesAtSortedIndex(j)) < 0 52 }) 53 } 54 55 type bufWriter struct { 56 b []byte 57 n int 58 } 59 60 func (b *bufWriter) Write(p []byte) (int, error) { 61 copy(b.b[b.n:], p) 62 b.n += len(p) 63 return len(p), nil 64 } 65 66 func initUsernameOffsets() { 67 var offset uint32 68 offsets = make([]uint32, len(lengths)) 69 for index, length := range lengths { 70 offsets[index] = offset 71 offset += uint32(length) 72 } 73 } 74 75 func initUsernames() { 76 // 77 // The list of usernames is computed as such: 78 // 1. Sort all exceptions by UID 79 // 2. concatenate all username strings after sorting in 1 80 // 3. Tolower the blob 81 // 4. run through zlib 82 // 5. Also, along with (2), record the length of all of the usernames, and insert into an array 83 // 6. Compute running offsets by cumsum'ing the values in 5. 84 // 85 zip, err := zlib.NewReader(bytes.NewReader(usernamesCompressed[:])) 86 if err != nil { 87 panic(err) 88 } 89 usernames = make([]byte, usernamesLen) 90 buf := bufWriter{usernames, 0} 91 n, err := io.Copy(&buf, zip) 92 if err != nil { 93 panic(err) 94 } 95 if n != usernamesLen { 96 panic(fmt.Sprintf("bad expansion: wanted %d bytes but got %d", usernamesLen, n)) 97 } 98 zip.Close() 99 } 100 101 func uidBytesAt(i int) []byte { 102 start := i * keybase1.UID_LEN 103 return uids[start : start+keybase1.UID_LEN] 104 } 105 106 func uidAt(i int) keybase1.UID { 107 ret, _ := keybase1.UIDFromSlice(uidBytesAt(i)) 108 return ret 109 } 110 111 func findHardcodedUsername(u libkb.NormalizedUsername) keybase1.UID { 112 usernameFindInit() 113 l := len(lengths) 114 searchFor := []byte(u.String()) 115 doCmp := func(i int) int { 116 ret := bytes.Compare(searchFor, usernameBytesAtSortedIndex(i)) 117 return ret 118 } 119 n := sort.Search(l, func(i int) bool { 120 return doCmp(i) <= 0 121 }) 122 if n == l || doCmp(n) != 0 { 123 return keybase1.UID("") 124 } 125 return uidAt(int(usernameSortOrder[n])) 126 } 127 128 // Returns empty name if not found 129 func findHardcoded(uid keybase1.UID) libkb.NormalizedUsername { 130 findInit() 131 searchFor := uid.ToBytes() 132 if len(searchFor) != keybase1.UID_LEN { 133 // wrong uid size 134 return libkb.NormalizedUsername("") 135 } 136 l := len(uids) / keybase1.UID_LEN 137 doCmp := func(i int) int { 138 return bytes.Compare(searchFor, uidBytesAt(i)) 139 } 140 n := sort.Search(l, func(i int) bool { 141 return doCmp(i) <= 0 142 }) 143 if n == l || doCmp(n) != 0 { 144 return libkb.NormalizedUsername("") 145 } 146 offset := offsets[n] 147 s := string(usernames[offset : offset+uint32(lengths[n])]) 148 return libkb.NewNormalizedUsername(s) 149 } 150 151 func checkUIDAgainstUsername(uid keybase1.UID, un libkb.NormalizedUsername) bool { 152 found := findHardcoded(uid) 153 if !found.IsNil() { 154 return found.Eq(un) 155 } 156 computed := libkb.UsernameToUID(un.String()) 157 return computed.Equal(uid) 158 }