如何使用Coldfusion和OpenSSL检查Amazon Alexa的请求签名

时间:2017-12-14 20:49:37

标签: hash coldfusion openssl alexa alexa-skill

亚马逊有关如何验证的文档发布在此处:https://developer.amazon.com/docs/custom-skills/host-a-custom-skill-as-a-web-service.html#checking-the-signature-of-the-request

我一直试图让它发挥作用:

确定签名证书有效后,从中提取公钥。

Base64-解码请求上的Signature标头值以获取加密签名。

使用从签名证书中提取的公钥来解密加密签名,以生成声明的哈希值。

从完整HTTPS请求正文生成SHA-1哈希值,以生成派生哈希值

比较断言的哈希值和派生的哈希值,以确保它们匹配。

这是我到目前为止所拥有的。我已经完成了主题和有效的pem文件的验证,问题是我不知道如何'比较断言的哈希值和派生的哈希值以确保它们匹配。

<!---get the request sent from amazon---->
 <cfset local.request = deserializeJson(
    toString(getHttpRequestData().content)
  )>      

  <!---collect headers for authentication---->
  <cfif this.isTesting is False>
          <cftry>
            <cfset local.request.headers.SignatureCertChainUrl = getHttpRequestData().headers.SignatureCertChainUrl>
          <cfcatch type="any">
            <cfset local.request.request.type = "SessionEndedRequest"><!---end session if SignatureCertChainUrl not passed--->
          </cfcatch>
          </cftry>

          <cftry>
            <cfset local.request.headers.Signature = getHttpRequestData().headers.Signature>
            <cflog file="Alexa" text="URL Sig: #local.request.headers.Signature#" > 
          <cfcatch type="any">
            <cfset local.request.request.type = "SessionEndedRequest"><!---end session if Signature not passed--->
            <cflog file="Alexa" text="Signature is not defined" > 
          </cfcatch>
          </cftry>



  <cfif isDefined("local.request.headers.SignatureCertChainUrl") and 
            isDefined("local.request.headers.Signature")>

               <cfif find('https://s3.amazonaws.com/echo.api/',local.request.headers.SignatureCertChainUrl)
                        or find('https://s3.amazonaws.com:443/echo.api/',local.request.headers.SignatureCertChainUrl)><!---not ssl so kill it--->



                <cflog file="Alexa" text="URL Chain: #local.request.headers.SignatureCertChainUrl#" > 

                <cfset local.request.headers.SignatureCertChainUrlFormatted = replacenocase(local.request.headers.SignatureCertChainUrl,'echo.api/../echo.api','echo.api')>

            <cfhttp url="#local.request.headers.SignatureCertChainUrlFormatted#" method="get"></cfhttp>

                <cffile action="write"
                        file="C:\inetpub\alexa\cert\echo.pem"
                        output="#cfhttp.FileContent#">


                <!---check date is valid---->
                <cfexecute name="C:\OpenSSL-Win32\bin\openssl.exe" 
                       arguments="x509 -noout -dates -in C:\inetpub\alexa\cert\echo.pem"    
                       variable="local.cert.OpenSSL_dates"
                       timeout="10" >
                </cfexecute>

                <cfset local.cert.datesFormatted = replacenoCase(local.cert.OpenSSL_dates,'notbefore','')>
                <cfset local.cert.datesFormatted = replacenoCase(local.cert.datesFormatted,'notafter','')>
                <cfset local.cert.datesFormatted = replacenoCase(local.cert.datesFormatted,'=','')>
                <cfset local.cert.notBefore = trim(listgetat(local.cert.datesFormatted,1,'='))>
                <cfset local.cert.notAfter = trim(listgetat(local.cert.datesFormatted,2,'='))>

                <cfif datecompare(convertCertTime(local.cert.notBefore),now()) is '-1' and 
                        datecompare(convertCertTime(local.cert.notAfter),now()) is '1'>
                    <!---cert date is valid--->
                <cfelse>
                    <cfset local.request.request.type = "SessionEndedRequest">
                </cfif>

                <!---check 'echo-api.amazon.com' in subject---->
                <cfexecute name="C:\OpenSSL-Win32\bin\openssl.exe" 
                       arguments="x509 -noout -subject -in C:\inetpub\alexa\cert\echo.pem"    
                       variable="local.cert.OpenSSL_Subject"
                       timeout="10" >
                </cfexecute>

                <cfif NOT findNOcase('echo-api.amazon.com',local.cert.OpenSSL_Subject)>
                    <cfset local.request.request.type = "SessionEndedRequest">
                </cfif>

                <!---check 'CN=Symantec Class 3 Secure Server CA' in issuer---->
                <cfexecute name="C:\OpenSSL-Win32\bin\openssl.exe" 
                       arguments="x509 -noout -issuer -in C:\inetpub\alexa\cert\echo.pem"    
                       variable="local.cert.OpenSSL_issuer"
                       timeout="10" >
                </cfexecute>

                <cfif NOT findNOcase('Symantec Class 3 Secure Server CA',local.cert.OpenSSL_issuer)>
                    <cfset local.request.request.type = "SessionEndedRequest">
                </cfif>

                <cfexecute name="C:\OpenSSL-Win32\bin\openssl.exe" 
                           arguments="x509 -noout -pubkey -in C:\inetpub\alexa\cert\echo.pem"    
                           variable="local.cert.OpenSSL_Pubkey"
                           timeout="120" >
                </cfexecute>


                  <cffile action="write"
                        file="C:\inetpub\alexa\keys\#local.request.request.requestId#.key"
                        output="#local.cert.OpenSSL_Pubkey#">  

                        <!---decyrpt header signature---->

                        <!----Base64-decode the Signature header---->
                  <cfset local.cert.encryptedSig = toString(ToBinary(local.request.headers.Signature)) /> 

                   <cffile action="write"
                        file="C:\inetpub\alexa\keys\#local.request.request.requestId#.sig"
                        output="#local.cert.encryptedSig#">

               <cfelse>
                <cfset local.request.request.type = "SessionEndedRequest">
               </cfif>     


          <!----end of header decrypting----->     
      <cfelse>
            <!---if either of these are not defined kill the session---->
            <cfset local.request.request.type = "SessionEndedRequest">
      </cfif>


</cfif>

2 个答案:

答案 0 :(得分:-1)

在Base64解码之前尝试将charsetDecode转换为utf-8

答案 1 :(得分:-1)

在Base64解码之前使用它

<CFSET local.request.headers.Signature = charsetDecode( local.request.headers.Signature, "utf-8" )>