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  }