github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/kbfshash/hash.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package kbfshash 6 7 import ( 8 "crypto/hmac" 9 "crypto/sha256" 10 "encoding" 11 "encoding/hex" 12 "fmt" 13 14 "github.com/keybase/client/go/kbfs/cache" 15 "github.com/pkg/errors" 16 ) 17 18 // See https://keybase.io/admin-docs/hash-format for the design doc 19 // for the keybase hash format. 20 21 const ( 22 // MinHashByteLength is the minimum number of bytes a valid 23 // keybase hash can be, including the 1 byte for the type. 24 MinHashByteLength = 33 25 26 // DefaultHashByteLength is the number of bytes in a default 27 // keybase hash. 28 DefaultHashByteLength = 1 + sha256.Size 29 30 // MaxHashByteLength is the maximum number of bytes a valid 31 // keybase hash can be, including the 1 byte for the type. 32 MaxHashByteLength = 129 33 34 // MinHashStringLength is the minimum number of characters in 35 // the string representation (hex encoding) of a valid keybase 36 // hash. 37 MinHashStringLength = 2 * MinHashByteLength 38 39 // DefaultHashStringLength is the number of characters in the 40 // string representation of a default keybase hash. 41 DefaultHashStringLength = 2 * DefaultHashByteLength 42 43 // MaxHashStringLength is the maximum number of characters the 44 // string representation of a valid keybase hash can be. 45 MaxHashStringLength = 2 * MaxHashByteLength 46 ) 47 48 // HashType is the type of a keybase hash. 49 type HashType byte 50 51 const ( 52 // InvalidHash is the zero HashType value, which is invalid. 53 InvalidHash HashType = 0 54 // SHA256Hash is the type of a SHA256 hash. 55 SHA256Hash HashType = 1 56 // SHA256HashV2 is the type of a SHA256 hash over V2-encrypted data. 57 SHA256HashV2 HashType = 2 58 59 // MaxHashType is the highest-supported hash type. 60 MaxHashType HashType = SHA256HashV2 61 62 // TemporaryHashType is a hash type to be used for random 63 // byte-strings that can be used in place of real hashes. 64 TemporaryHashType HashType = 0xff 65 ) 66 67 // MaxDefaultHash is the maximum value of RawDefaultHash 68 var MaxDefaultHash = RawDefaultHash{ 69 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 70 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 71 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 72 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 73 } 74 75 func (t HashType) String() string { 76 switch t { 77 case InvalidHash: 78 return "InvalidHash" 79 case SHA256Hash: 80 return "SHA256Hash" 81 case SHA256HashV2: 82 return "SHA256HashV2" 83 default: 84 return fmt.Sprintf("HashType(%d)", t) 85 } 86 } 87 88 // DefaultHashType is the current default keybase hash type. 89 const DefaultHashType HashType = SHA256Hash 90 91 // DefaultHashNew is a function that creates a new hash.Hash object 92 // with the default hash. 93 var DefaultHashNew = sha256.New 94 95 // RawDefaultHash is the type for the raw bytes of a default keybase 96 // hash. This is exposed for use as in-memory keys. 97 type RawDefaultHash [sha256.Size]byte 98 99 // DoRawDefaultHash computes the default keybase hash of the given 100 // data, and returns the type and the raw hash bytes. 101 func DoRawDefaultHash(p []byte) (HashType, RawDefaultHash) { 102 return DefaultHashType, RawDefaultHash(sha256.Sum256(p)) 103 } 104 105 // Copy returns a copied RawDefaultHash 106 func (rdh *RawDefaultHash) Copy() *RawDefaultHash { 107 if rdh == nil { 108 return nil 109 } 110 hashCopy := RawDefaultHash{} 111 copy(hashCopy[:], rdh[:]) 112 return &hashCopy 113 } 114 115 // Hash is the type of a keybase hash. 116 type Hash struct { 117 // Stored as a string so that this can be used as a map key. 118 h string 119 } 120 121 var _ encoding.BinaryMarshaler = Hash{} 122 var _ encoding.BinaryUnmarshaler = (*Hash)(nil) 123 124 var _ encoding.TextMarshaler = Hash{} 125 var _ encoding.TextUnmarshaler = (*Hash)(nil) 126 127 // HashFromRaw creates a hash from a type and raw hash data. If the 128 // returned error is nil, the returned Hash is valid. 129 func HashFromRaw(hashType HashType, rawHash []byte) (Hash, error) { 130 return HashFromBytes(append([]byte{byte(hashType)}, rawHash...)) 131 } 132 133 // HashFromBytes creates a hash from the given byte array. If the 134 // returned error is nil, the returned Hash is valid. 135 func HashFromBytes(data []byte) (Hash, error) { 136 h := Hash{string(data)} 137 if !h.IsValid() { 138 return Hash{}, errors.WithStack(InvalidHashError{h}) 139 } 140 return h, nil 141 } 142 143 // HashFromString creates a hash from the given string. If the 144 // returned error is nil, the returned Hash is valid. 145 func HashFromString(dataStr string) (Hash, error) { 146 data, err := hex.DecodeString(dataStr) 147 if err != nil { 148 return Hash{}, errors.WithStack(err) 149 } 150 return HashFromBytes(data) 151 } 152 153 // DefaultHash computes the hash of the given data with the default 154 // hash type. 155 func DefaultHash(buf []byte) (Hash, error) { 156 hashType, rawHash := DoRawDefaultHash(buf) 157 return HashFromRaw(hashType, rawHash[:]) 158 } 159 160 // DoHash computes the hash of the given data with the given hash 161 // type. 162 func DoHash(buf []byte, ht HashType) (Hash, error) { 163 switch ht { 164 case SHA256Hash, SHA256HashV2: 165 default: 166 return Hash{}, errors.WithStack(UnknownHashTypeError{ht}) 167 } 168 _, rawHash := DoRawDefaultHash(buf) 169 return HashFromRaw(ht, rawHash[:]) 170 } 171 172 func (h Hash) hashType() HashType { 173 return HashType(h.h[0]) 174 } 175 176 // GetHashType returns the type of this hash. 177 func (h Hash) GetHashType() HashType { 178 return h.hashType() 179 } 180 181 func (h Hash) hashData() []byte { 182 return []byte(h.h[1:]) 183 } 184 185 // IsValid returns whether the hash is valid. Note that a hash with an 186 // unknown version is still valid. 187 func (h Hash) IsValid() bool { 188 if len(h.h) < MinHashByteLength { 189 return false 190 } 191 if len(h.h) > MaxHashByteLength { 192 return false 193 } 194 195 if h.hashType() == InvalidHash { 196 return false 197 } 198 199 return true 200 } 201 202 // Bytes returns the bytes of the hash. 203 func (h Hash) Bytes() []byte { 204 return []byte(h.h) 205 } 206 207 func (h Hash) String() string { 208 return hex.EncodeToString([]byte(h.h)) 209 } 210 211 // MarshalBinary implements the encoding.BinaryMarshaler interface for 212 // Hash. Returns an error if the hash is invalid and not the zero 213 // hash. 214 func (h Hash) MarshalBinary() (data []byte, err error) { 215 if h == (Hash{}) { 216 return nil, nil 217 } 218 219 if !h.IsValid() { 220 return nil, errors.WithStack(InvalidHashError{h}) 221 } 222 223 return []byte(h.h), nil 224 } 225 226 // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface 227 // for Hash. Returns an error if the given byte array is non-empty and 228 // the hash is invalid. 229 func (h *Hash) UnmarshalBinary(data []byte) error { 230 if len(data) == 0 { 231 *h = Hash{} 232 return nil 233 } 234 235 h.h = string(data) 236 if !h.IsValid() { 237 err := InvalidHashError{*h} 238 *h = Hash{} 239 return errors.WithStack(err) 240 } 241 242 return nil 243 } 244 245 // Verify makes sure that the hash matches the given data and returns 246 // an error otherwise. 247 func (h Hash) Verify(buf []byte) error { 248 if !h.IsValid() { 249 return errors.WithStack(InvalidHashError{h}) 250 } 251 252 expectedH, err := DoHash(buf, h.hashType()) 253 if err != nil { 254 return err 255 } 256 257 if h != expectedH { 258 return errors.WithStack(HashMismatchError{expectedH, h}) 259 } 260 return nil 261 } 262 263 // MarshalText implements the encoding.TextMarshaler interface for 264 // Hash. 265 func (h Hash) MarshalText() ([]byte, error) { 266 return []byte(h.String()), nil 267 } 268 269 // UnmarshalText implements the encoding.TextUnmarshaler interface 270 // for Hash. 271 func (h *Hash) UnmarshalText(data []byte) error { 272 newH, err := HashFromString(string(data)) 273 if err != nil { 274 return err 275 } 276 *h = newH 277 return nil 278 } 279 280 const ptrSize = 4 << (^uintptr(0) >> 63) // stolen from runtime/internal/sys 281 282 // Size implements the cache.Measurable interface. 283 func (h *Hash) Size() int { 284 return len(h.h) + ptrSize 285 } 286 287 var _ cache.Measurable = (*Hash)(nil) 288 289 // HMAC is the type of a keybase hash that is an HMAC. 290 // 291 // All the constants for Hash also apply to HMAC. 292 type HMAC struct { 293 h Hash 294 } 295 296 var _ encoding.BinaryMarshaler = HMAC{} 297 var _ encoding.BinaryUnmarshaler = (*HMAC)(nil) 298 299 var _ encoding.TextMarshaler = HMAC{} 300 var _ encoding.TextUnmarshaler = (*HMAC)(nil) 301 302 // DefaultHMAC computes the HMAC with the given key of the given data 303 // using the default hash. 304 func DefaultHMAC(key, buf []byte) (HMAC, error) { 305 mac := hmac.New(DefaultHashNew, key) 306 _, err := mac.Write(buf) 307 if err != nil { 308 return HMAC{}, err 309 } 310 h, err := HashFromRaw(DefaultHashType, mac.Sum(nil)) 311 if err != nil { 312 return HMAC{}, err 313 } 314 return HMAC{h}, nil 315 } 316 317 func (hmac HMAC) hashType() HashType { 318 return hmac.h.hashType() 319 } 320 321 func (hmac HMAC) hashData() []byte { 322 return hmac.h.hashData() 323 } 324 325 // IsValid returns whether the HMAC is valid. Note that an HMAC with an 326 // unknown version is still valid. 327 func (hmac HMAC) IsValid() bool { 328 return hmac.h.IsValid() 329 } 330 331 // Bytes returns the bytes of the HMAC. 332 func (hmac HMAC) Bytes() []byte { 333 return hmac.h.Bytes() 334 } 335 336 func (hmac HMAC) String() string { 337 return hmac.h.String() 338 } 339 340 // MarshalBinary implements the encoding.BinaryMarshaler interface for 341 // HMAC. Returns an error if the HMAC is invalid and not the zero 342 // HMAC. 343 func (hmac HMAC) MarshalBinary() (data []byte, err error) { 344 return hmac.h.MarshalBinary() 345 } 346 347 // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface 348 // for HMAC. Returns an error if the given byte array is non-empty and 349 // the HMAC is invalid. 350 func (hmac *HMAC) UnmarshalBinary(data []byte) error { 351 return hmac.h.UnmarshalBinary(data) 352 } 353 354 // MarshalText implements the encoding.TextMarshaler interface for 355 // HMAC. 356 func (hmac HMAC) MarshalText() ([]byte, error) { 357 return hmac.h.MarshalText() 358 } 359 360 // UnmarshalText implements the encoding.TextUnmarshaler interface 361 // for HMAC. 362 func (hmac *HMAC) UnmarshalText(data []byte) error { 363 return hmac.h.UnmarshalText(data) 364 } 365 366 // Verify makes sure that the HMAC matches the given data. 367 func (hmac HMAC) Verify(key, buf []byte) error { 368 if !hmac.IsValid() { 369 return errors.WithStack(InvalidHashError{hmac.h}) 370 } 371 372 // Once we have multiple hash types we'll need to expand this. 373 t := hmac.hashType() 374 if t != DefaultHashType { 375 return errors.WithStack(UnknownHashTypeError{t}) 376 } 377 378 expectedHMAC, err := DefaultHMAC(key, buf) 379 if err != nil { 380 return err 381 } 382 if hmac != expectedHMAC { 383 return errors.WithStack( 384 HashMismatchError{expectedHMAC.h, hmac.h}) 385 } 386 return nil 387 }