github.com/smugmug/godynamo@v0.0.0-20151122084750-7913028f6623/auth_v4/tasks/tasks.go (about)

     1  // Manages signing tasks required by AWS Auth v4 requests to DynamoDB.
     2  // See http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
     3  // for more information on v4 signed requests.
     4  package tasks
     5  
     6  import (
     7  	"crypto/hmac"
     8  	"crypto/sha256"
     9  	"encoding/hex"
    10  	"github.com/smugmug/godynamo/aws_const"
    11  	"hash"
    12  	"strings"
    13  	"time"
    14  )
    15  
    16  // MakeSignature returns a auth_v4 signature from the `string to sign` variable.
    17  // May be useful for creating v4 requests for services other than DynamoDB.
    18  func MakeSignature(string2sign, zone, service, secret string) string {
    19  	kCredentials, _ := cacheable_hmacs(zone, service, secret)
    20  	var kSigning_hmac_sha256 hash.Hash = hmac.New(sha256.New, kCredentials)
    21  	kSigning_hmac_sha256.Write([]byte(string2sign))
    22  	kSigning := kSigning_hmac_sha256.Sum(nil)
    23  	return hex.EncodeToString(kSigning)
    24  }
    25  
    26  // Return the byte slice for the cacheable hmac, along with the date string
    27  // that describes its time of creation.
    28  func cacheable_hmacs(zone, service, secret string) ([]byte, string) {
    29  	t := time.Now().UTC()
    30  	gmt_yyyymmdd := t.Format(aws_const.ISODATEFMT)
    31  
    32  	init_secret := []byte("AWS4" + secret)
    33  	var kDate_hmac_sha256 hash.Hash = hmac.New(sha256.New, init_secret)
    34  	kDate_hmac_sha256.Write([]byte(gmt_yyyymmdd))
    35  	kDate := kDate_hmac_sha256.Sum(nil)
    36  
    37  	var kRegion_hmac_sha256 hash.Hash = hmac.New(sha256.New, kDate)
    38  	kRegion_hmac_sha256.Write([]byte(zone))
    39  	kRegion := kRegion_hmac_sha256.Sum(nil)
    40  
    41  	var kService_hmac_sha256 hash.Hash = hmac.New(sha256.New, kRegion)
    42  	kService_hmac_sha256.Write([]byte(service))
    43  	kService := kService_hmac_sha256.Sum(nil)
    44  
    45  	var kCredentials_hmac_sha256 hash.Hash = hmac.New(sha256.New, kService)
    46  	kCredentials_hmac_sha256.Write([]byte("aws4_request"))
    47  	return kCredentials_hmac_sha256.Sum(nil), gmt_yyyymmdd
    48  }
    49  
    50  // CanonicalRequest will create the aws v4 `canonical request`.
    51  // This function is specific to DynamoDB.
    52  func CanonicalRequest(host, port, amzDateHdr, amzTargetHdr, hexPayload string) string {
    53  	// Some AWS services use the x-amz-target header. Some don't. Allow it to
    54  	// be passed as empty when not used.
    55  	amzTarget_list_elt := ""
    56  	amzTarget_val := ""
    57  	if amzTargetHdr != "" {
    58  		amzTarget_val = strings.ToLower(aws_const.AMZ_TARGET_HDR) + ":" +
    59  			amzTargetHdr + "\n"
    60  		amzTarget_list_elt = ";x-amz-target"
    61  	}
    62  	return aws_const.METHOD + "\n" +
    63  		"/" + "\n" +
    64  		"" + "\n" +
    65  		strings.ToLower(aws_const.CONTENT_TYPE_HDR) + ":" +
    66  		aws_const.CTYPE + "\n" +
    67  		strings.ToLower("host") + ":" +
    68  		host + ":" +
    69  		port + "\n" +
    70  		strings.ToLower(aws_const.X_AMZ_DATE_HDR) + ":" +
    71  		amzDateHdr + "\n" +
    72  		amzTarget_val +
    73  		"\n" +
    74  		"content-type;host;x-amz-date" + amzTarget_list_elt + "\n" +
    75  		hexPayload
    76  }
    77  
    78  // String2Sign will create the aws v4 `string to sign` from the `canoncial request`.
    79  // May be useful for creating v4 requests for services other than DynamoDB.
    80  func String2Sign(t time.Time, canonical_request, zone, service string) string {
    81  	var h256 hash.Hash = sha256.New()
    82  	h256.Write([]byte(canonical_request))
    83  	hexCanonReq := hex.EncodeToString([]byte(h256.Sum(nil)))
    84  	return "AWS4-HMAC-SHA256" + "\n" +
    85  		t.UTC().Format(aws_const.ISO8601FMT_CONDENSED) + "\n" +
    86  		t.UTC().Format(aws_const.ISODATEFMT) + "/" +
    87  		zone +
    88  		"/" + service + "/aws4_request" + "\n" +
    89  		hexCanonReq
    90  }