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 }