Created
January 18, 2017 19:47
-
-
Save Sparticuz/e5dcfb3bc3b21a6dc850f64e8fb27fac to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FUNCTION lf AS C (count AS N = 1) | |
dim return as c = "" | |
while count | |
*concat(return,chr(10)) | |
count = count - 1 | |
end while | |
lf = return | |
END FUNCTION | |
function hmacsha256 as b (message as c, key as b) | |
dim Encoding as p = new ::System::Text::Encoding::UTF8 | |
dim kha as ::System::Security::Cryptography::KeyedHashAlgorithm = new ::System::Security::Cryptography::KeyedHashAlgorithm::Create("HMACSHA256") | |
'Set the key | |
kha.Key = key | |
hmacsha256 = kha.ComputeHash(Encoding.GetBytes(message)) | |
end function | |
function getSignatureKey as b (key as c, dateStamp as c, regionName as c, serviceName as c) | |
dim test as l = .f. | |
if test then | |
key = "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY" | |
dateStamp = "20120215" | |
regionName = "us-east-1" | |
serviceName= "iam" | |
'*to_hex() | |
'kSecret = '41575334774a616c725855746e46454d492f4b374d44454e472b62507852666943594558414d504c454b4559' | |
'kDate = '969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d' | |
'kRegion = '69daa0209cd9c5ff5c8ced464a696fd4252e981430b10e3d3fd8e2f197d7a70c' | |
'kService = 'f72cfd46f26bc4643f06a11eabb6c0ba18780c19a8da0c31ace671265e3c87fa' | |
'kSigning = 'f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d' | |
end if | |
dim Encoding as p = new ::System::Text::Encoding::UTF8 | |
dim kSecret as b = Encoding.GetBytes("AWS4"+key) | |
dim kDate as b = hmacsha256(dateStamp,kSecret) | |
dim kRegion as b = hmacsha256(regionName,kDate) | |
dim kService as b = hmacsha256(serviceName,kRegion) | |
dim kSigning as b = hmacsha256("aws4_request",kService) | |
getSignatureKey = kSigning | |
end function | |
function sha256 as c (string as c) | |
dim Encoding as p = new ::System::Text::Encoding::UTF8 | |
dim sham as ::System::Security::Cryptography::SHA256Managed = new ::System::Security::Cryptography::SHA256Managed() | |
sha256 = *to_hex(sham.ComputeHash(Encoding.GetBytes(string))) | |
end function | |
function getAccessKey as c () | |
getAccessKey = "" | |
end function | |
function getSecretKey as c () | |
getSecretKey = "" | |
end function | |
function getSignature as c (verb as c, method as c, query as p, payload as c = "", serviceName as c = "ses", regionName as c = "us-east-1") | |
'# ************* TASK 1: CREATE A CANONICAL REQUEST ************* | |
'http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html | |
dim datetime as t = now(.t.) | |
dim amzdate as c = time("yyyyMMddT0h0m0sZ",datetime) | |
dim datestamp as c = time("yyyyMMdd",datetime) | |
dim access_key as c = getAccessKey() | |
dim secret_key as c = getSecretKey() | |
dim host as c = "email."+regionName+".amazonaws.com" | |
dim test as l = .f. | |
if test then | |
amzdate = "20150830T123600Z" | |
datestamp = "20150830" | |
access_key = "AKIDEXAMPLE" | |
secret_key = "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY" | |
host = "example.amazonaws.com" | |
serviceName = "service" | |
regionName = "us-east-1" | |
delete query | |
dim query as p | |
query.Param1 = "value1" | |
query.Param2 = "value2" | |
debug(1) | |
end if | |
'Step 1 is to define the verb (GET, POST, etc.)--already done by passing verb. | |
'Step 2: Create canonical URI--the part of the URI from domain to query | |
' string (use '/' if no path) | |
dim uri as c = method | |
'Step 3: Create the canonical query string. In this example (a GET request), | |
' request parameters are in the query string. Query string values must | |
' be URL-encoded (space=%20). The parameters must be sorted by name. | |
' For this example, the query string is pre-formatted in the request_parameters variable. | |
dim queryString as c = property_to_url(query,"S") | |
'Step 4: Create the canonical headers and signed headers. Header names | |
' and value must be trimmed and lowercase, and sorted in ASCII order. | |
' Note that there is a trailing \n. | |
dim headers as c = "host:"+host+lf()+"x-amz-date:"+amzdate+lf() | |
'Step 5: Create the list of signed headers. This lists the headers | |
' in the canonical_headers list, delimited with ";" and in alpha order. | |
' Note: The request can include any headers; canonical_headers and | |
' signed_headers lists those that you want to be included in the | |
' hash of the request. "Host" and "x-amz-date" are always required. | |
dim signedHeaders as c = "host;x-amz-date" | |
'Step 6: Create payload hash (hash of the request body content). For GET | |
' requests, the payload is an empty string (""). | |
if verb == "GET" then | |
dim payloadHash as c = sha256("") | |
else | |
dim payloadHash as c = sha256(payload) | |
end if | |
' Step 7: Combine elements to create create canonical request | |
dim canonical_request as c = alltrim(verb) + lf() + alltrim(uri) + lf() | |
if queryString <> "" then | |
*concat(canonical_request,alltrim(queryString) + lf()) | |
end if | |
*concat(canonical_request,alltrim(headers) + lf(2) + alltrim(signedHeaders) + lf() + alltrim(payloadHash)) | |
'# ************* TASK 2: CREATE THE STRING TO SIGN************* | |
'Match the algorithm to the hashing algorithm you use, either SHA-1 or | |
' SHA-256 (recommended) | |
dim algorithm as c = "AWS4-HMAC-SHA256" | |
dim credentialScope as c = datestamp + "/" + regionName + "/" + serviceName + "/aws4_request" | |
dim canonicalHash as c = sha256(canonical_request) | |
dim stringToSign as c = algorithm + lf() + amzdate + lf() + credentialScope + lf() + canonicalHash | |
'# ************* TASK 3: CALCULATE THE SIGNATURE ************* | |
' Create the signing key using the function defined above. | |
dim signingKey as b = getSignatureKey(secret_key, datestamp, regionName, serviceName) | |
' Sign the string_to_sign using the signing_key | |
dim signature as c = *to_hex(hmacsha256(stringToSign,signingKey)) | |
'# ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST ************* | |
'# The signing information can be either in a query string value or in | |
'# a header named Authorization. This code shows how to use a header. | |
'# Create authorization header and add to request headers | |
dim authorization_header as c = algorithm + " " + "Credential=" + access_key + "/" + credentialScope + ", SignedHeaders=" + signedHeaders + ", Signature=" + signature | |
'# The request can include any headers, but MUST include "host", "x-amz-date", | |
'# and (for this scenario) "Authorization". "host" and "x-amz-date" must | |
'# be included in the canonical_headers and signed_headers, as noted | |
'# earlier. Order here is not significant. | |
'# Python note: The 'host' header is added automatically by the Python 'requests' library. | |
'headers = {'x-amz-date':amzdate, 'Authorization':authorization_header} | |
getSignature = "{'x-amz-date':'"+amzdate+"','Authorization':'"+authorization_header+"','Host':'"+host+"'}" | |
end function |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment