如何使用ColdFusion和openSSL检查Amazon Alexa请求的签名



亚马逊关于如何验证的文档在此处发布:https://developer.amazon.com/docs/custom-skills/custom-skills/host-a-custom-custom-skill-as-skill-as-as-a-a-a-web-service.html#检查 - 签名

我坚持尝试使它起作用:

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

base64将签名标头值限制为获得加密签名的请求。

使用从签名证书提取的公共密钥解密加密的签名以产生主张的哈希值。

从完整的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:inetpubalexacertecho.pem"
                        output="#cfhttp.FileContent#">

                <!---check date is valid---->
                <cfexecute name="C:OpenSSL-Win32binopenssl.exe" 
                       arguments="x509 -noout -dates -in C:inetpubalexacertecho.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-Win32binopenssl.exe" 
                       arguments="x509 -noout -subject -in C:inetpubalexacertecho.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-Win32binopenssl.exe" 
                       arguments="x509 -noout -issuer -in C:inetpubalexacertecho.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-Win32binopenssl.exe" 
                           arguments="x509 -noout -pubkey -in C:inetpubalexacertecho.pem"    
                           variable="local.cert.OpenSSL_Pubkey"
                           timeout="120" >
                </cfexecute>

                  <cffile action="write"
                        file="C:inetpubalexakeys#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:inetpubalexakeys#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>

在base64 decode

之前尝试charsetDecode到UTF-8

在base64 decode

之前使用它
<CFSET local.request.headers.Signature = charsetDecode( local.request.headers.Signature, "utf-8" )>

最新更新