forked from smarty-archives/go-aws-auth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsign4.go
88 lines (66 loc) · 2.63 KB
/
sign4.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
package awsauth
import (
"encoding/hex"
"net/http"
)
func hashedCanonicalRequestV4(req *http.Request, meta *metadata) string {
// TASK 1. http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
payload := readAndReplaceBody(req)
payloadHash := hashSHA256(payload)
req.Header.Set("X-Amz-Content-Sha256", payloadHash)
contentType := req.Header.Get("Content-Type")
reqTs := req.Header.Get("X-Amz-Date")
headersToSign := concat("\n", "content-type:"+contentType, "host:"+req.Host, "x-amz-content-sha256:"+payloadHash, "x-amz-date:"+reqTs) + "\n"
meta.signedHeaders = "content-type;host;x-amz-content-sha256;x-amz-date"
canonicalRequest := concat("\n", req.Method, req.URL.Path, req.URL.Query().Encode(), headersToSign, meta.signedHeaders, payloadHash)
return hashSHA256([]byte(canonicalRequest))
}
func stringToSignV4(req *http.Request, hashedCanonReq string, meta *metadata) string {
// TASK 2. http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html
requestTs := req.Header.Get("X-Amz-Date")
meta.algorithm = "AWS4-HMAC-SHA256"
meta.service, meta.region = serviceAndRegion(req.Host)
meta.date = tsDateV4(requestTs)
meta.credentialScope = concat("/", meta.date, meta.region, meta.service, "aws4_request")
return concat("\n", meta.algorithm, requestTs, meta.credentialScope, hashedCanonReq)
}
func signatureV4(signingKey []byte, stringToSign string) string {
// TASK 3. http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
return hex.EncodeToString(hmacSHA256(signingKey, stringToSign))
}
func prepareRequestV4(req *http.Request) *http.Request {
necessaryDefaults := map[string]string{
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"X-Amz-Date": timestampV4(),
}
for header, value := range necessaryDefaults {
if req.Header.Get(header) == "" {
req.Header.Set(header, value)
}
}
if req.URL.Path == "" {
req.URL.Path += "/"
}
return req
}
func signingKeyV4(secretKey, date, region, service string) []byte {
kDate := hmacSHA256([]byte("AWS4"+secretKey), date)
kRegion := hmacSHA256(kDate, region)
kService := hmacSHA256(kRegion, service)
kSigning := hmacSHA256(kService, "aws4_request")
return kSigning
}
func buildAuthHeaderV4(signature string, meta *metadata) string {
credential := Keys.AccessKeyID + "/" + meta.credentialScope
return meta.algorithm +
" Credential=" + credential +
", SignedHeaders=" + meta.signedHeaders +
", Signature=" + signature
}
func timestampV4() string {
return now().Format(timeFormatV4)
}
func tsDateV4(timestamp string) string {
return timestamp[:8]
}
const timeFormatV4 = "20060102T150405Z"