github.com/decred/politeia@v1.4.0/util/convert.go (about)

     1  // Copyright (c) 2017-2019 The Decred developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package util
     6  
     7  import (
     8  	"crypto/sha256"
     9  	"encoding/hex"
    10  	"fmt"
    11  
    12  	dcrtime "github.com/decred/dcrtime/api/v1"
    13  	pdv1 "github.com/decred/politeia/politeiad/api/v1"
    14  	pdv2 "github.com/decred/politeia/politeiad/api/v1"
    15  	"github.com/decred/politeia/politeiad/api/v1/identity"
    16  )
    17  
    18  // ConvertSignature converts a hex encoded signature to a proper sized byte
    19  // slice.
    20  func ConvertSignature(s string) ([identity.SignatureSize]byte, error) {
    21  	sb, err := hex.DecodeString(s)
    22  	if err != nil {
    23  		return [identity.SignatureSize]byte{}, err
    24  	}
    25  	if len(sb) != identity.SignatureSize {
    26  		return [identity.SignatureSize]byte{},
    27  			fmt.Errorf("invalid signature length")
    28  	}
    29  	var sig [identity.SignatureSize]byte
    30  	copy(sig[:], sb)
    31  	return sig, nil
    32  }
    33  
    34  // ConvertStringToken verifies and converts a string token to a proper sized
    35  // byte slice. This function accepts both the full length token and token
    36  // prefixes.
    37  func ConvertStringToken(token string) ([]byte, error) {
    38  	switch {
    39  	case len(token) == pdv2.TokenSize*2:
    40  		// Tstore backend token; continue
    41  	case len(token) != pdv1.TokenSize*2:
    42  		// Git backend token; continue
    43  	case len(token) == pdv1.TokenPrefixLength:
    44  		// Token prefix; continue
    45  	default:
    46  		return nil, fmt.Errorf("invalid token size")
    47  	}
    48  	// If the token length is an odd number of characters, append a
    49  	// 0 digit as padding to prevent a hex.ErrLenth (odd length hex
    50  	// string) error when decoding.
    51  	if len(token)%2 == 1 {
    52  		token = token + "0"
    53  	}
    54  	blob, err := hex.DecodeString(token)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	return blob, nil
    59  }
    60  
    61  // Digest returns the SHA256 of a byte slice.
    62  func Digest(b []byte) []byte {
    63  	h := sha256.New()
    64  	h.Write(b)
    65  	return h.Sum(nil)
    66  }
    67  
    68  // IsDigest determines if a string is a valid SHA256 digest.
    69  func IsDigest(digest string) bool {
    70  	return dcrtime.RegexpSHA256.MatchString(digest)
    71  }
    72  
    73  // ConvertDigest converts a string into a digest.
    74  func ConvertDigest(d string) ([sha256.Size]byte, bool) {
    75  	var digest [sha256.Size]byte
    76  	if !IsDigest(d) {
    77  		return digest, false
    78  	}
    79  
    80  	dd, err := hex.DecodeString(d)
    81  	if err != nil {
    82  		return digest, false
    83  	}
    84  	copy(digest[:], dd)
    85  
    86  	return digest, true
    87  }
    88  
    89  // TokenToPrefix returns a substring a token of length pd.TokenPrefixLength,
    90  // or the token itself, whichever is shorter.
    91  func TokenToPrefix(token string) string {
    92  	if len(token) > pdv1.TokenPrefixLength {
    93  		return token[0:pdv1.TokenPrefixLength]
    94  	} else {
    95  		return token
    96  	}
    97  }
    98  
    99  // TokensToPrefixes calls TokenToPrefix on a slice of tokens.
   100  func TokensToPrefixes(tokens []string) []string {
   101  	prefixes := make([]string, 0, len(tokens))
   102  	for _, token := range tokens {
   103  		prefixes = append(prefixes, TokenToPrefix(token))
   104  	}
   105  	return prefixes
   106  }