1

试图将 C# 代码转换为 CF 并且我坚持翻译以下行

StorageKey = 'abcd';
Convert.FromBase64String(StorageKey)

上面的行产生一个 105,183,29 的字节数组

该行取自 Azure 的创建授权标头;

System.Security.Cryptography.HMACSHA256 SHA256 = new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(StorageKey));

我在 msdn 库上查找了 FromBase64String 方法,但它在我头上。我希望有人能指出我正确的 Coldfusion 方向。

我试过 BinaryDecode(StorageKey,"BASE64"),对我来说这似乎是最合乎逻辑的翻译,但我得到了 105-7329,这不是我的预期结果。

请参阅下面 Leigh 对 CF10+ 的回答,如果您在使用 CF7-9 解决方案,这是我的尝试

var javaMsg = javacast("string", arguments.sigMsg).getBytes("UTF-8");
var javaKey    = JavaCast("string", arguments.sigKey);
var myKey     = createObject('java', 'javax.crypto.spec.SecretKeySpec' );
var mac     = createObject('java', "javax.crypto.Mac");
var myKeyB64  = CreateObject("java", "org.apache.commons.codec.binary.Base64").decodeBase64(javaKey.getBytes());
var secret  = myKey.Init(myKeyB64, 'HmacSHA256');
mac         = mac.getInstance("HmacSHA256");
mac.init(secret);
</cfscript>
<cfdump var="#mac.doFinal(javaMsg)#">
4

2 回答 2

1

C# 将结果视为无符号字节,而 ColdFusion 将它们视为有符号字节。

128 以下的值在 C# 和 ColdFusion 中相同,而在 C# 中超过 128 的值在 ColdFusion 中为负数(二进制补码)。

因此,要转换回来,请将 256 添加到任何负值。

编辑

对于从 BinaryDecode 返回的实际字节,这可能不是问题。在调试期间,ColdFusion 如何决定将这些字节打印到屏幕上可能只是一个问题。

比较从 C# 和 ColdFusion 获得的实际二进制值(例如,通过将值保存到二进制文件而不是打印到屏幕上)。

于 2012-11-14T03:29:36.520 回答
1

该行取自 Azure 的创建授权标头;

mbeckish 关于 C# 和 CF/java 之间的符号差异是正确的。但是,我认为内部表示不应该对您的最终结果产生任何影响,这通常是您所关心的。通常,您不需要匹配低级整数值,只需匹配 base64 或十六进制字节的字符串表示形式。只要您以通用格式(如 base64)比较最终的 HMAC 值,它们应该完全相同。

例如,如果您在此处获取示例签名字符串,则 CF10 和 C# 都返回相同的值。因此,您的问题似乎可能是其他问题。

<cfscript>
    savecontent variable="signatureString" {
        WriteOutput("GET#chr(10)##chr(10)##chr(10)##chr(10)#x-ms-date:Mon, 01 Dec 2008 05:17:57 GMT#chr(10)#/accountname/queuename/messages");
    };
    key = binaryDecode("abcd", "base64");
    resultInHex = hmac(signatureString, key,"HMACSHA256");
    // result: wxR7Bt6sWEKVJ9vEjCiuqA8OKCZOKYfbxaXj85whOkM=
    WriteDump(binaryEncode(binaryDecode(resultInHex, "hex"), "base64"));
</cfscript>



编辑:我知道有一堆 CF10 之前的 hmac 函数。但是他们中的许多人忘记了编码。这是一个接受算法(“hmacsha256”、“hmacsha1”、..)和编码(“utf-8”)的通用适配。它应该适用于 CF7-9。

<cfset result = hmacX( signatureString, "abcd", "HmacSHA256") />
<cfdump var="#result#" />

<cffunction name="hmacX" returntype="string" hint="">
    <cfargument name="message" type="string" required="true" />
    <cfargument name="keyInBase64" type="any" required="true" />
    <cfargument name="algorithm" type="string" default="HmacSHA256" />
    <cfargument name="encoding" type="string" default="UTF-8" />

    <cfset var dataBytes  = charsetDecode( arguments.message, arguments.encoding ) />
    <cfset var keyBytes  = binaryDecode( arguments.keyInBase64, "base64" ) />
    <cfset var keySpec = createObject("java", "javax.crypto.spec.SecretKeySpec") />
    <cfset var secret = keySpec.init( keyBytes, arguments.algorithm ) />
    <cfset var mac  = createObject("java", "javax.crypto.Mac").getInstance( arguments.algorithm ) />

    <cfset mac.init( secret ) />

    <cfreturn binaryEncode( mac.doFinal(dataBytes), "base64") />
</cffunction>
于 2012-11-14T17:54:29.193 回答