问题描述
我有一个纯文本用户表,并将其迁移到成员资格提供程序.
I have a user table that was in plain text and migrated it to Membership provider.
使用ColdFusion(当前系统),我设法哈希了一个用户的密码(测试用户),并且密码完美匹配.但是现在后续的用户不匹配.我在做什么错了.
Using ColdFusion (current system) I managed to HASH one user's password (test user) and it matched perfectly. But now the subsequent users do not match. What am I doing wrong.
<cfscript>
theEncoding = "UTF-16LE";
thePassword = "dtD3v310p3r!";
base64Salt = "JZjdzUXREM0A7DPI3FV3iQ==";
theSalt = charsetEncode( binaryDecode(base64Salt, "base64"), theEncoding );
theHash = hash(theSalt & thePassword, "SHA1", theEncoding);
// hash always returns hex. convert it to base64 so it matches DNN
theBase64Hash = binaryEncode(binaryDecode(theHash, "hex"), "base64");
WriteOutput("<br />theBase64Hash= "& theBase64Hash &"<br/>");
WriteOutput("DBPassword= 5khDDMmoFtW+j99r/whE/TjyIUo= <br />");
theEncoding = "UTF-16LE";
thePassword = "DT!@12";
base64Salt = "+muo6gAmjvvyy5doTdjyaA==";
theSalt = charsetEncode( binaryDecode(base64Salt, "base64"), theEncoding );
theHash = hash(theSalt & thePassword, "SHA1", theEncoding);
// hash always returns hex. convert it to base64 so it matches DNN
theBase64Hash = binaryEncode(binaryDecode(theHash, "hex"), "base64");
WriteOutput("<br />theBase64Hash= "& theBase64Hash &"<br/>");
WriteOutput("DBPassword= nfcqQBgeAm0Dp1oGZI0O70Y6DvA= <br />");
</cfscript>
第一个100%有效.但是第二个没有.第二个产生的哈希值86SrPKXW5xywDYoC8MVy0q259sQ=
The first one works 100%. But the second one doesn't.The second one produces a Hash value of 86SrPKXW5xywDYoC8MVy0q259sQ=
推荐答案
嗯.我认为将两个值串联在一起可能出问题了.散列实际上应该使用字节数组,类似于加密版本,但不幸的是CF9的 hash()函数不支持它-仅字符串. (尽管文献记载不充分,但CF11支持该文件).我不确定CF9是否有纯CF解决方案.但是,与此同时,您可以直接使用Java:
Hm.. I think something may be going wrong when the two values are concatenated. The hashing should really use a byte array, like with the encrypt version, but unfortunately CF9's hash() function does not support it - only strings. (Though poorly documented, it is supported in CF11). I am not sure if there is a pure CF work-around for CF9. However, in the mean time you could use java directly:
<cfscript>
thePassword = "DT!@12";
base64Salt = "+muo6gAmjvvyy5doTdjyaA==";
// extract bytes of the salt and password
saltBytes = binaryDecode(base64Salt, "base64");
passBytes = charsetDecode(thePassword, "UTF-16LE" );
// next combine the bytes. note, the returned arrays are immutable,
// so we cannot use the standard CF tricks to merge them
ArrayUtils = createObject("java", "org.apache.commons.lang.ArrayUtils");
dataBytes = ArrayUtils.addAll( saltBytes, passBytes );
// hash binary using java
MessageDigest = createObject("java", "java.security.MessageDigest").getInstance("SHA-1");
MessageDigest.update(dataBytes);
theBase64Hash = binaryEncode(MessageDigest.digest(), "base64");
WriteOutput("<br />theBase64Hash= "& theBase64Hash &"<br/>");
WriteOutput("DBPassword= nfcqQBgeAm0Dp1oGZI0O70Y6DvA= <br />");
</cfscript>
更新:
进一步环顾四周后,我认为没有纯粹的CF解决方案. UTF-16LE编码只是问题的一部分.另一个问题是DNN分别解码每个字符串 ,与将两个字符串都解码为单个字符串相比,这可能会产生不同的字节(请参见下面的比较).在您输入第二个密码的情况下也是如此,这就是为什么最终哈希值不同的原因.由于hash
将不接受字节数组,因此我认为这不是用于此工作的正确工具. MessageDigest
是必经之路.
After looking around further, I do not think there is pure CF solution. The UTF-16LE encoding is only part of the problem. The other issue is that DNN decodes each string separately, which may produce different bytes than when both are decoded as a single string (see comparison below). It does in the case of your second password, which is why the final hash is different. Since hash
will not accept byte arrays, I do not think it is the right tool for this job. MessageDigest
is the way to go.
字节数组比较
old| new |
1 | -6 | -6 |
2 | 107 | 107 |
3 | -88 | -88 |
4 | -22 | -22 |
5 | 0 | 0 |
6 | 38 | 38 |
7 | -114 | -114 |
8 | -5 | -5 |
9 | -14 | -14 |
10 | -53 | -53 |
11 | -105 | -105 |
12 | 104 | 104 |
13 | -3 | 77 | **
14 | -1 | -40 | **
15 | 68 | -14 | **
16 | 0 | 104 | **
17 | 84 | 68 | **
18 | 0 | 0 |
19 | 33 | 84 | **
20 | 0 | 0 |
21 | 64 | 33 | **
22 | 0 | 0 |
23 | 49 | 64 | **
24 | 0 | 0 |
25 | 50 | 49 | **
26 | 0 | 0 |
27 | | 50 | **
28 | | 0 | **
- old => charsetDecode(theSalt& thePassword,"UTF-16LE")
- new => ArrayUtils.addAll(saltBytes,passBytes);
- old => charsetDecode( theSalt & thePassword, "UTF-16LE")
- new => ArrayUtils.addAll( saltBytes, passBytes );
这篇关于成员SHA1哈希对于所有用户而言都不相同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!