2011-04-10 85 views
1

我想弄清楚如何生成SQL Server和ColdFusion之间匹配的MD 5哈希值。根本原因似乎是SQL Server字段是nvarchar数据类型,这似乎意味着我需要对字符串的编码做些什么,我会在ColdFusion或Java中进行散列以使其匹配,但我无法想象它出。为了清楚这是否是SQL Server varchar字段,一切正常。如何生成匹配MD5哈希:SQL Server nvarchar字段与ColdFusion

这里是我想要的代码:

<cfset stringToHash = "Hello world!"> 

<cfquery name="sqlserver" datasource="#mySqlServerDSN#"> 
    SELECT RIGHT( 
    master.dbo.fn_varbintohexstr( 
     HashBytes( 
      'MD5', 
      CAST(<cfqueryparam value="#stringToHash#" cfsqltype="cf_sql_varchar"> AS nvarchar(max))  
     ) 
    ) 
    , 32) AS HASHED 
</cfquery> 

<cfoutput> 
<pre> 
CF UFT-8: #hash(stringToHash, 'MD5', 'UTF-8')# 
CF UFT-16: #hash(stringToHash, 'MD5', 'UTF-16')# 
SQL Server: #sqlserver.hashed# 
</pre> 
</cfoutput> 

主要生产

CF UTF-8: 86FB269D190D2C85F6E0468CECA42A20 
CF UTF-16: 0C89A9720D83539E3723BB99C07D069F 
SQL Server: f9a6119c6ec37ce652960382f8b59f2c 

所以我猜我需要改变我传递给hash()最后一个参数是不同的编码,但我无法弄清楚。我也将这个问题也标记为Java,因为我很乐意以该语言来回答问题。

+1

其他人似乎有与.net http://stackoverflow.com/questions/5341556/calculating-sha1-hash-of-a-nvarchar-string-using-t-sql这个问题我不没有办法测试出来,但也许默认情况下CF UTF-16编码是Big Endian? – patrickmcgraw 2011-04-10 15:55:02

+0

如果要将纯字符串值与SQL hased列进行比较,请将纯字符串传递给使用SQL的SQL&hash。然后与该栏进行比较。你有什么具体的要求来检查在CF代码? – 2011-04-10 17:46:07

回答

2

默认情况下,SQL Server在little-endian字节顺序字符集中为nvarchar字段使用UTF-16。 在ColdFusion中,您必须使用'UTF-16LE'字符集。

<cfscript> 
    helloWorld = "Hello, World!"; 
    utf8HashCF = lcase(hash(helloWorld, 'MD5', 'UTF-16LE')); 
</cfscript> 
<cfoutput> 
    #utf8HashCF# <br /> 
</cfoutput> 
+0

这是正确的。以为我试过这个编码与散列函数,但显然不是。会很好奇看到一些关于nvarchar的endianess的文档。 – orangepips 2011-04-12 21:44:51

+0

我以为我也试过这个,我想不是,很好的工作! – 2011-04-13 13:40:43

+0

奇怪的是,当我尝试使用@StefanoDiFabio java版本使用UTF-16LE时,它不起作用。 ColdFusion正在做一个或两个额外的步骤,以使其发挥作用。 – 2011-04-13 14:28:52

1

我很好奇为什么你的sql服务器列是nvarchar;它不是必需的哈希值。 nvarchar用于存储扩展字符集,您不应该从哈希函数返回。

无论如何,我尝试了所有CF9中可用的散列算法,它们都不会生成您要查找的散列。

除非您需要将列设置为nvarchar出于某种原因,您尚未解释,为什么不将其更改为varchar?

+1

亚当发布 - 我检查了SQL Server 2008,但将查询更改为CAST('Hello world!'AS varchar(32))并获得了您的CF UTF-8哈希值。 – Lucas 2011-04-11 15:26:33

0

我不认为这是CF散列,因为如果您将CF与Java比较,它们会创建相同的散列。我的盒子上的CF & Java输出为“65a8e27d8879283831b664bd8b7f0ad4”,当我将转换转换为varchar(32)时,它与SQL哈希匹配。

在过去,当我需要做任何形式的散列创建和比较时,我创建了一个返回字符串的服务,因此您不必担心跨平台算法问题。你也可以让sql为你做所有事情,但是你的业务逻辑在错误的层次上,但是每个层次都有自己的逻辑。

<cfscript> 
    helloWorld = "Hello, World!"; 

    javaString = CreateObject("java", "java.lang.String").Init(helloWorld); 
    javaHash = CreateObject("java", "java.security.MessageDigest").getInstance("MD5"); 

    javaHash.reset(); 
    javaHash.update(javaString.getBytes("UTF-8"),0,javaString.length()); 

    javaBigInt = CreateObject("java", "java.math.BigInteger").Init(1,javaHash.digest()); 

    utf8HashCF = lcase(hash(helloWorld, 'MD5', 'UTF-8')); 
    utf8HashJava = variables.javaBigInt.toString(16); 
</cfscript> 
<cfoutput> 
    #utf8HashCF# <br /> 
    #utf8HashJava# 
</cfoutput>