Signature V4 AWS S3 Put Python



import sys, os, base64, datetime, hashlib, hmac 
import requests

access_key = ''
secret_key = ''
t = datetime.datetime.utcnow()
amz_date = t.strftime('%Y%m%dT%H%M%SZ')
date_stamp = t.strftime('%Y%m%d')
method = 'PUT'
service = 's3'
host = 'jeff.s3.amazonaws.com'
region = 'us-east-1'
content_title = 'myfile.txt'
content = "Hello My World!".encode(encoding='utf-8')
#content_acl = 'public-read';  #if acl is not provided object defaults to private
content_type = 'text/plain';
payload_hash = hashlib.sha256(content).hexdigest()

def sign(key, msg):
    return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
def getSignatureKey(key, date_stamp, regionName, serviceName):
    kDate = sign(('AWS4' + key).encode('utf-8'), date_stamp)
    kRegion = sign(kDate, regionName)
    kService = sign(kRegion, serviceName)
    kSigning = sign(kService, 'aws4_request')
    return kSigning


dictRequestHeaders = {}
dictRequestHeaders['content-type'] = content_type
dictRequestHeaders['date'] = amz_date
dictRequestHeaders['host'] = host
dictRequestHeaders['x-amz-acl'] = content_acl
dictRequestHeaders['x-amz-content-sha256'] = payload_hash

lstRequestHeaders = []
lstRequestHeaders.append(content_type)
lstRequestHeaders.append(amz_date)
lstRequestHeaders.append(host)
lstRequestHeaders.append(content_acl)
lstRequestHeaders.append(payload_hash)


lstCanonicalHeaders = []
lstCanonicalHeaders.append('content-type' + ':' + content_type)
lstCanonicalHeaders.append('date' + ':' + amz_date)
lstCanonicalHeaders.append('host' + ':' + host)
#lstCanonicalHeaders.append('x-amz-acl' + ':' + content_acl)
lstCanonicalHeaders.append('x-amz-content-sha256' + ':' + payload_hash)


strCanonicalHeaders = '\n'.join(lstCanonicalHeaders)
print(strCanonicalHeaders)
lstSignedHeaders = []
lstSignedHeaders.append('content-type')
lstSignedHeaders.append('date')
lstSignedHeaders.append('host')
#lstSignedHeaders.append('x-amz-acl')
lstSignedHeaders.append('x-amz-content-sha256')
strSignedHeaders = ';'.join(lstSignedHeaders)
print(strSignedHeaders)

lstCanonicalRequest = [];
lstCanonicalRequest.append('PUT')
lstCanonicalRequest.append('/' + content_title)
lstCanonicalRequest.append('')
lstCanonicalRequest.append(strCanonicalHeaders)
lstCanonicalRequest.append('')
lstCanonicalRequest.append(strSignedHeaders)
lstCanonicalRequest.append(payload_hash)

strCanonicalRequest = '\n'.join(lstCanonicalRequest)
print(strCanonicalRequest)
hashed_canonical_request = hashlib.sha256(strCanonicalRequest.encode('utf-8')).hexdigest()

scope = []
scope.append(date_stamp)
scope.append(region)
scope.append(service)
scope.append('aws4_request')

string_to_sign = []
string_to_sign.append('AWS4-HMAC-SHA256')
string_to_sign.append(amz_date)
string_to_sign.append('/'.join(scope))
string_to_sign.append(hashed_canonical_request)
strStringToSign = '\n'.join(string_to_sign)
print(strStringToSign)

signing_key = getSignatureKey(secret_key, date_stamp, region, service)
signature = hmac.new(signing_key, (strStringToSign).encode('utf-8'), hashlib.sha256).hexdigest()

authorization_header = 'AWS4-HMAC-SHA256' + ' ' + 'Credential=' + access_key + '/' + '/'.join(scope) + ', ' +  'SignedHeaders=' + strSignedHeaders + ', ' + 'Signature=' + signature
print(authorization_header)
headers = {'Authorization':authorization_header,
           'Content-Type':content_type,
           'date':amz_date,
           'host':host,
           #'x-amz-acl':content_acl,
           'x-amz-content-sha256': payload_hash
           }
r = requests.put('https://' + host + '/' + content_title, data=content, headers=headers)
print('Response code: %d\n' % r.status_code)
print(r.text)