Question
· Feb 12

How to Authenticating AWS Signature Version 4) for POST API it's show msg ""The request signature we calculated does not match the signature you provided"

I want to request authentication to AWS using AWS Signature in the authentication request.

I have attempted to follow the documentation at this link: AWS Signature Version 4 Signing Process

 

 

However, when I send a POST API request to AWS, I receive the following response:

Status Code: 403 {"message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details."}

 

Below is the code I wrote to hash with SHA256 and convert to HEX according to the steps provided.

 

Class Custom.API.AWSTool Extends %RegisteredObject
{

Parameter lambdaprivatedns = "lambda.xxxxx.amazonaws.com";
Parameter funcname = "/functions/sync-function/invocations";
Parameter AWSAccessKeyId = "XXXxxxxxxxxxxxXXX";
Parameter AWSSecretAccessKey = "XXXxxxxxxxxxxxXXX";
Parameter Region = "ap-southeast-1";
Parameter ServiceName = "lambda";
Parameter SSLConfig = "AWS";
ClassMethod TestAWSPOST()
{
    //------------------------------------------------------------------
    set lstPerson=[]
    set objPerson=##class(%Library.DynamicObject).%New()
    set objPerson."RowId"="001"
    set objPerson."Fullname"="8CRjdd9K3i9CyhokbubuCN7OhQ=="
    set objPerson."isDelete"="FALSE"
    do lstPerson.%Push(objPerson)
    set bodyRAW={
            "Result": {
                "Code": "S",
                "Message": "Active",
                "RequestCode": ""
                },
            "Person": (lstPerson)
    }
    s json=bodyRAW.%ToJSON()
    //------------------------------------------------------------------
    set tPort="443"
    set tContentType="application/json"
    set tSSLConfig="AWS"
    set tUseHTTPS=1
    ;---Payload-------
    set tContentStream=##class(%Stream.TmpCharacter).%New()
    do tContentStream.Write(json)
    do tContentStream.Rewind()
    set tHashedPayload=..BytesToHex($System.Encryption.SHAHashStream(256,tContentStream,.tSC)) 
    //
    ;set payloadHash = ##class(%SYSTEM.Encryption).SHAHash(256, json)
    ;set tpaylaod=..hexDigest(payloadHash)
    ;w "tpaylaod : "_tpaylaod,!
    w "tHashedPayload : "_tHashedPayload,!
    //---------AWSDate--------
    set tHorolog=$h
    set tTmpTime=$ZDT(tHorolog,2,7)
    set tHeaderDate=$ZD(tHorolog,11)_", "_$E(tTmpTime,1,11)_" "_$E(tTmpTime,13,*-1)_" GMT"
    set tAmzDate=$TR($zdt(tHorolog,8,7),":","")
    //------------------1.Canonical Request--------------------------
    ;---HTTP Verb-------
    Set method = "POST"_$c(10)  
    ;---Canonical URI-------
    Set canonicalUri = ..#funcname
    set canonicalUri=$zconvert(canonicalUri,"O","URL")
    Set canonicalUri =canonicalUri_$c(10)
    ;--- Canonical Query String-------
    set canonicalQueryString=""
    set canonicalQueryString=$zconvert(canonicalQueryString,"O","URL")
    Set canonicalQueryString =canonicalQueryString_$c(10)
    ;--- Canonical Headers-------
    Set canonicalHeaders ="content-length:"_tContentStream.Size_$c(10)
        _"content-type:"_tContentType_$c(10)
        _"host:"_..#lambdaprivatedns_$c(10)
        _"x-amz-content-sha256:"_tHashedPayload_$c(10)
        _"x-amz-date:"_tAmzDate_$c(10)    
    set canonicalHeaders=$zconvert(canonicalHeaders,"L")
    set canonicalHeaders=canonicalHeaders_$c(10)
    ;---Signed Headers-------
    Set signedHeadersori = "content-length;content-type;host;x-amz-content-sha256;x-amz-date"
    Set signedHeaders = "content-length;content-type;host;x-amz-content-sha256;x-amz-date"
    set signedHeaders=$zconvert(signedHeaders,"L") 
    set signedHeaders=signedHeaders_$c(10)
    ;---Canonical Request-------
    /*set tCanonicalRequest=method _$C(10) _ canonicalUri _$C(10) _ canonicalQueryString _$C(10)
    _ canonicalHeaders _$C(10)_ signedHeaders _$C(10)_ tHashedPayload*/
    set tCanonicalRequest=method_canonicalUri_canonicalQueryString_canonicalHeaders
    _signedHeaders_tHashedPayload
    w !,!,"1.Canonical Request-------------------------- : "_tCanonicalRequest,!,!
    //------------------2.StringToSign--------------------------
    set tStringToSign="AWS4-HMAC-SHA256"_$c(10)
        _$TR($zdt(tHorolog,8,7),":","")_$c(10)
        _$zd(tHorolog,8)_"/"_..#Region_"/"_..#ServiceName_"/aws4_request"_$c(10)
        _..hex($System.Encryption.SHAHash(256,tCanonicalRequest))
    w !,!,"2.StringToSign-------------------------- : "_tStringToSign,!,!
    //------------------3.Signature--------------------------
    set dateStamp = $PIECE(tAmzDate, "T", 1)
    set DateKey = ..sign("AWS4"_..#AWSSecretAccessKey, dateStamp)
    set DateRegionKey = ..sign(DateKey, ..#Region)
    set DateRegionServiceKey = ..sign(DateRegionKey, ..#ServiceName)
    set SigningKey = ..sign(DateRegionServiceKey, "aws4_request") //HMACSHA256
    Set signature = ##class(%SYSTEM.Encryption).HMACSHA(256, tStringToSign,SigningKey)
    set signature=..hex(signature)
    w !,!,"3.Signature-------------------------- : "_signature,!,!
    set tAuthHeader="AWS4-HMAC-SHA256 Credential="_..#AWSAccessKeyId_"/"_$zd(tHorolog,8)_"/"_..#Region_"/"_..#ServiceName_"/aws4_request, SignedHeaders="_signedHeadersori_", Signature="_signature
    //-----------------------------------------------------------------------------------------------    
    set tHReq=##class(%Net.HttpRequest).%New()
    set tHReq.Server=tHost
    set tHReq.Port=443
    set tHReq.SSLConfiguration=..#SSLConfig
    set tHReq.Https=1
    do tHReq.SetHeader("Authorization",tAuthHeader)
    do tHReq.SetHeader("Host",tHost)
    do tHReq.SetHeader("Content-Type","application/json")
    do tHReq.SetHeader("Content-Length",tContentStream.Size)
    do tHReq.SetHeader("X-Amz-Content-Sha256",tHashedPayload)
    do tHReq.SetHeader("X-Amz-Date",tAmzDate)
    do tHReq.EntityBody.Write(json)
    do tHReq.OutputHeaders()

    set tSC = tHReq.Post(..#funcname,0,1)
    do $System.OBJ.DisplayError(tSC)
    
    write "Status Code:",tHReq.HttpResponse.StatusCode,!
    w tHReq.HttpResponse.Data.Read(),!
    ;set obj = {}.%FromJSON(tHReq.HttpResponse.Data)
    ;w "obj : "_obj,!
    if $isobject(tHReq.HttpResponse.Data) {
        s ^zresp=tHReq.HttpResponse.Data.Read(1000000)
    } else {
        s ^zresp=tHReq.HttpResponse.Data
    }
}

ClassMethod BytesList(pBytes As %String) As %String
{
    s l=$LISTFROMSTRING(pBytes," ")
    f i=1:1:$LL(l)  s st=$G(st)_$CHAR($ZHEX($LISTGET(l,i)))
    return st
}

ClassMethod BytesToHex(pBytes As %String) As %String
{
    set tHex=""
    for i=1:1:$L(pBytes) {
        set tHexByte=$ZHEX($ASCII($E(pBytes,i)))
        if $L(tHexByte)=1 s tHexByte="0"_tHexByte
        set tHex=tHex_tHexByte
    }
    
    return $ZCONVERT(tHex,"L")
}

ClassMethod hex(str As %String)
{
    set hexstring = ""
    for i=1:1:$L(str) 
    {
        set hexcode = $zh($a($e(str,i))) 
        set:($l(hexcode)=1) hexcode = "0"_hexcode
        set hexstring = hexstring _ hexcode
    }
    quit $ZCVT(hexstring,"L")
}

ClassMethod hex2(pRaw As %String) As %String [ Internal ]
{
    set out="", l=$l(pRaw)
    for i = 1:1:l {
        set out=out_$zhex($ascii(pRaw,i))
    }
    quit $$$LOWER(out)
}

ClassMethod getPayloadHash(pRequest As Custom.THVJ.Report.API.AWS.AWS4Auth.BaseRequest) As %String [ Private ]
{
        Set payloadHash = ##class(%SYSTEM.Encryption).SHAHash(256, "")
        
        if pRequest.#Method '= "GET"
        {
            set payload = pRequest.Payload.%ToJSON()
            set payloadHash = ##class(%SYSTEM.Encryption).SHAHash(256, payload)
        }
        
        return ##class(AWS.Utils).hexDigest(payloadHash)
}

ClassMethod sign(key As %String, msg As %String)
{
        //set msg = $ZCONVERT(msg,"O","UTF8")
        //$system.Encryption.HMACSHA(bitlength,text,key)
        return ##class(%SYSTEM.Encryption).HMACSHA(256, msg, key)
}

ClassMethod hexDigest(hash As %String)
{
        set digest = ""
        for i=1:1:$L(hash) 
        {
            set hHex = $ZHex($Ascii($Extract(hash,i))) 
            
            //This accounts for leading zeros getting left out of converted hexidecimal string
            if $LENGTH(hHex) = 1
            {
                set hHex = "0"_hHex
            }
            
            set digest = digest _ hHex
        }
        
        Quit $ZConvert(digest,"L")
}

// END Class
}
Product version: IRIS 2020.1
$ZV: IRIS for UNIX (Red Hat Enterprise Linux for x86-64) 2020.1 (Build 215_0_21670U)
Discussion (0)1
Log in or sign up to continue