如何为 AWS 签名版本 4(在 ColdFusion 中)派生登录密钥? [英] How to derive a sign-in key for AWS Signature Version 4 (in ColdFusion)?

查看:20
本文介绍了如何为 AWS 签名版本 4(在 ColdFusion 中)派生登录密钥?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 ColdFusion 使用他们当前称为签名版本 4 的身份验证方法访问 Amazon Web Services (AWS).我查阅了他们的文档,其中包含 几种编程语言,以及 其他语言.他们提供了一些测试输入值以传递给我的脚本的签名函数,以及一些预期的结果.

I am trying to use ColdFusion to access Amazon Web Services (AWS) using their current authentication method known as Signature Version 4. I have consulted their documentation which has code examples for several programming languages, as well as pseudo-code for other languages. They provided some test input values to pass in to my script's signature function, and also some expected results.

这里是测试输入:

key = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
dateStamp = '20120215'
regionName = 'us-east-1'
serviceName = 'iam'

以下是预期结果:

kSecret  = '41575334774a616c725855746e46454d492f4b374d44454e472b62507852666943594558414d504c454b4559'
kDate    = '969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d'
kRegion  = '69daa0209cd9c5ff5c8ced464a696fd4252e981430b10e3d3fd8e2f197d7a70c'
kService = 'f72cfd46f26bc4643f06a11eabb6c0ba18780c19a8da0c31ace671265e3c87fa'
kSigning = 'f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d'

kSigning"的正确值应该是这样的:

The correct value for "kSigning" should be this:

f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d

但是,对于kSigning",我的代码会生成:

However, for "kSigning" my code generates this:

31A84DCE0538A8B15ED68CCFBD803F17947E41BF625EFFD1AD6A67FC821F9BE2

我正在使用 Railo 4.2.有人可以帮我解决这个问题,以便预期值与转储值匹配吗?这是我的 ColdFusion 标记:

I am using Railo 4.2. Can someone please help me solve this, so that the anticipated value matches the dumped value? Here's my ColdFusion markup:

<cfsilent>

<!--- HMACSHA256 --->
<cffunction name="sign" returntype="binary" access="private" output="false" hint="Sign with NSA SHA-256 Algorithm">
   <cfargument name="signMessage" type="string" required="true" />
   <cfargument name="signKey" type="string" required="true" />

   <cfset var jMsg = JavaCast("string",arguments.signMessage).getBytes("utf-8") />
   <cfset var jKey = JavaCast("string",arguments.signKey).getBytes("utf-8") />
   <cfset var key = createObject("java","javax.crypto.spec.SecretKeySpec") />
   <cfset var mac = createObject("java","javax.crypto.Mac") />

   <cfset key = key.init(jKey,"HmacSHA256") />
   <cfset mac = mac.getInstance(key.getAlgorithm()) />
   <cfset mac.init(key) />

   <cfreturn mac.doFinal(jMsg) />
</cffunction>

<!--- Get Signature Key --->
<cffunction name="getSignatureKey" returntype="binary" access="private" output="false" hint="Derive the sign-in key">
    <cfargument name="key" type="string" required="true" />
    <cfargument name="dateStamp" type="string" required="true" />
    <cfargument name="regionName" type="string" required="true" />
    <cfargument name="serviceName" type="string" required="true" />

    <cfset var kSecret = "AWS4" & arguments.key />
    <cfset var kDate = sign( arguments.dateStamp, kSecret ) />
    <cfset var kRegion = sign( arguments.regionName, kDate ) />
    <cfset var kService = sign( arguments.serviceName, kRegion ) />
    <cfset var kSigning = sign( arguments.serviceName, kService ) />

    <cfreturn kSigning />
</cffunction>

</cfsilent><!doctype html>

<html lang="en">
<head>
    <meta charset="utf-8">
    <title>AWS Test</title>
</head>
<body>

<cfset kSecret = getSignatureKey( 
    'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY', 
    '20120215', 
    'us-east-1', 
    'iam' 
) />
<cfdump var="#BinaryEncode(kSecret, 'hex')#" label="kSecret" />

</body>
</html>

推荐答案

<cfset var kRegion = sign(arguments.regionName, kDate)/>

我对代码运行没有错误感到惊讶,因为 sign() 函数需要两个字符串,但代码实际上是为第二个参数传入一个字节数组.(在 CF11 下它会引发错误).也许正在进行某种隐式转换?无论如何,在稍微重构函数之后,该示例运行良好,但有一个例外.该示例的最后一行使用文字字符串aws4_request"而不是arguments.serviceName".请参见下面的示例.

I am little surprised the code runs without error, as the sign() function expects two strings, but the code is actually passing in a byte array for the second parameter. (Under CF11 it throws an error). Perhaps there is some sort of implicit conversion going on? Anyway, after refactoring the functions slightly, the example worked fine with one exception. The very last line of the example uses the literal string "aws4_request" rather than "arguments.serviceName". See example below.

话虽如此,Railo 不是有一个 HMAC 函数可以使用而不是自己滚动吗?我猜是这样,因为 HMAC() 包含在 CF10+ 中.更新: 作为 vrtjason 在评论中注明,Railo 在 4.0.0.011.但是,为了向后兼容,下面的 java 版本应该适用于大多数任何版本.

Having said that, does not Railo have an HMAC function you can use rather than rolling your own? I am guessing so, as HMAC() is included in CF10+. Update: As vrtjason noted in the comments, Railo added the HMAC() function in 4.0.0.011. However, for backward compatibility the java version below should work with most any version.

示例:

result = getSignatureKey(key, dateStamp, regionName, serviceName);
writeDump( binaryEncode(result, "hex") );

结果:

F4780E2D9F65FA895F9C67B32CE1BAF0B0D8A43505A000A1A9E090D414DB404D 

功能:

<cffunction name="getSignatureKey" returntype="binary" access="private" output="false" hint="Derive the sign-in key">
    <cfargument name="key" type="string" required="true" />
    <cfargument name="dateStamp" type="string" required="true" />
    <cfargument name="regionName" type="string" required="true" />
    <cfargument name="serviceName" type="string" required="true" />

    <cfset Local.kSecret = charsetDecode("AWS4" & arguments.key, "UTF-8") />
    <cfset Local.kDate = sign( arguments.dateStamp, Local.kSecret ) />
    <cfset Local.kRegion = sign( arguments.regionName, Local.kDate ) />
    <cfset Local.kService = sign( arguments.serviceName, Local.kRegion ) />
    <cfset Local.kSigning = sign( "aws4_request", Local.kService ) />

    <cfreturn Local.kSigning />
</cffunction>




<cffunction name="sign" returntype="binary" access="private" output="false" hint="Sign with NSA SHA-256 Algorithm">
   <cfargument name="message" type="string" required="true" />
   <cfargument name="key" type="binary" required="true" />
   <cfargument name="algorithm" type="string" default="HmacSHA256" />
   <cfargument name="encoding" type="string" default="UTF-8" />

   <cfset Local.keySpec = createObject("java","javax.crypto.spec.SecretKeySpec") />
   <cfset Local.keySpec = Local.keySpec.init( arguments.key, arguments.algorithm ) />
   <cfset Local.mac = createObject("java","javax.crypto.Mac").getInstance( arguments.algorithm ) />
   <cfset Local.mac.init( Local.keySpec ) />

   <cfreturn Local.mac.doFinal( charsetDecode(arguments.message, arguments.encoding ) ) />
</cffunction>

这篇关于如何为 AWS 签名版本 4(在 ColdFusion 中)派生登录密钥?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆