-
Notifications
You must be signed in to change notification settings - Fork 0
/
hash.go
118 lines (100 loc) · 3.28 KB
/
hash.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package transit
import (
"context"
"crypto/hmac"
"crypto/sha256"
"crypto/sha512"
"encoding/base64"
"encoding/hex"
"fmt"
"hash"
"strconv"
"github.com/PumpkinSeed/heimdall/internal/errors"
"github.com/PumpkinSeed/heimdall/pkg/structs"
"github.com/hashicorp/vault/sdk/helper/keysutil"
)
func (t Transit) Hash(ctx context.Context, inputB64 string, algo structs.HashType, format string) (string, error) {
input, err := base64.StdEncoding.DecodeString(inputB64)
if err != nil {
return "", errors.Wrap(err, "transit hash unable to decode input as base64", errors.CodePkgCryptoTransitHashInputFormat)
}
if format == "" {
format = "hex"
}
if algo == structs.HashType_EmptyHashType {
algo = structs.HashType_HashTypeSHA2256
}
switch format {
case "hex", "base64":
default:
return "", errors.Newf(errors.CodePkgCryptoTransitHashOutputFormat, "transit hash unsupported encoding format %s; must be \"hex\" or \"base64\"", format)
}
var hf hash.Hash
switch algo {
case structs.HashType_HashTypeSHA2256:
hf = sha256.New()
case structs.HashType_HashTypeSHA2224:
hf = sha256.New224()
case structs.HashType_HashTypeSHA2384:
hf = sha512.New384()
case structs.HashType_HashTypeSHA2512:
hf = sha512.New()
default:
return "", errors.Newf(errors.CodePkgCryptoTransitHashAlgorithmFormat, "transit hash unsupported algorithm \"%s\"", algo)
}
hf.Write(input)
retBytes := hf.Sum(nil)
var retStr string
switch format {
case "hex":
retStr = hex.EncodeToString(retBytes)
case "base64":
retStr = base64.StdEncoding.EncodeToString(retBytes)
}
return retStr, nil
}
func (t Transit) HMAC(ctx context.Context, keyName, inputB64, algo string, keyVersion int, engineName string) (string, error) {
key, err := t.GetKey(ctx, keyName, engineName)
if err != nil {
return "", errors.Wrap(err, "transit hmac get key error", errors.CodePkgCryptoTransitHMACGetKey)
}
if algo == "" {
algo = "sha2-256"
}
switch {
case keyVersion == 0:
// Allowed, will use latest; set explicitly here to ensure the string
// is generated properly
keyVersion = key.LatestVersion
case keyVersion == key.LatestVersion:
// Allowed
case key.MinEncryptionVersion > 0 && keyVersion < key.MinEncryptionVersion:
key.Unlock()
return "", errors.New("transit hmac cannot generate HMAC: version is too old (disallowed by policy)", errors.CodePkgCryptoTransitHMACKeyVersion)
}
k, err := key.HMACKey(keyVersion)
if err != nil {
key.Unlock()
return "", errors.New("transit hmac HMAC creation failed", errors.CodePkgCryptoTransitHMAC)
}
if key == nil {
key.Unlock()
return "", errors.New("transit hmac key value could not be computed", errors.CodePkgCryptoTransitHMACCompute)
}
hashAlgorithm, ok := keysutil.HashTypeMap[algo]
if !ok {
key.Unlock()
return "", errors.Newf(errors.CodePkgCryptoTransitHMACUnsupportedAlgo, "transit hmac unsupported algorithm %q", hashAlgorithm)
}
hashAlg := keysutil.HashFuncMap[hashAlgorithm]
input, err := base64.StdEncoding.DecodeString(inputB64)
if err != nil {
return "", errors.Wrap(err, "transit hmac unable to decode input as base64", errors.CodePkgCryptoTransitHMACInputFormat)
}
var hf = hmac.New(hashAlg, k)
hf.Write(input)
retBytes := hf.Sum(nil)
return fmt.Sprintf("vault:v%s:%s",
strconv.Itoa(keyVersion), base64.StdEncoding.EncodeToString(retBytes),
), nil
}