在ColdFusion中验证DotNetNuke用户

时间:2012-09-21 05:43:59

标签: coldfusion dotnetnuke single-sign-on

有没有办法使用DNN登录来验证来自其他网络应用的用户?

我们有一个使用DNN的主站点,用户登录存储在asp net Membership表中。从我读过的内容来看,密码是使用机器密钥加密然后加盐的。我看到这些信息的位置,但似乎无法使用此方法正确加密密码。

我正在尝试在我们的DNN网站所在的同一台服务器上使用Coldfusion Web应用程序,但它不想工作。您认为使用ColdFusion加密功能会向前推进:

    Encrypt(passwordstring, key [, algorithm, encoding, IVorSalt, iterations])

无论我尝试什么,我都没有得到匹配的价值。

非常感谢任何帮助,见解或指向正确的方向!

3 个答案:

答案 0 :(得分:3)

(编辑:原始答案在所有情况下都不起作用。经过大幅修改......)

根据我的阅读,DNN使用" SHA1"哈希默认情况下。发布的帖子@barnyr显示它只是哈希连接的盐和密码,但有一些曲折。

鉴于CF9的Hash函数不接受二进制文件(CF11支持),我认为不可能仅使用本机CF函数复制结果。相反,我建议将字符串解码为二进制,然后直接使用java:

<强>代码:

<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("theBase64Hash= "& theBase64Hash &"<br/>");
</cfscript>


差异演示:

<cfscript>
    theEncoding = "UTF-16LE";
    thePassword = "DT!@12";
    base64Salt = "+muo6gAmjvvyy5doTdjyaA==";

    // extract the bytes SEPARATELY
    saltBytes = binaryDecode(base64Salt, "base64");
    passBytes = charsetDecode(thePassword, theEncoding );
    ArrayUtils = createObject("java", "org.apache.commons.lang.ArrayUtils");
    separateBytes = ArrayUtils.addAll( saltBytes, passBytes );

    // concatenate first, THEN extract the bytes 
    theSalt = charsetEncode( binaryDecode(base64Salt, "base64"), theEncoding );
    concatenatedBytes = charsetDecode( theSalt & thePassword, theEncoding );

    // these are the raw bytes BEFORE hashing
    WriteOutput("separateBytes= "& arrayToList(separateBytes, "|") &"<br>");        
    WriteOutput("concatenatedBytes"& arrayToList(concatenatedBytes, "|") );
</cfscript>


<强>结果:

separateBytes     = -6|107|-88|-22|0|38|-114|-5|-14|-53|-105|104|77|-40|-14|104|68|0|84|0|33|0|64|0|49|0|50|0
concatenatedBytes = -6|107|-88|-22|0|38|-114|-5|-14|-53|-105|104|-3|-1|68|0|84|0|33|0|64|0|49|0|50|0 


答案 1 :(得分:2)

密码很可能没有加密,而是经过哈希处理。哈希与加密不同,因为它不可逆。

你不会使用ColdFusion的encrypt()函数,你可以使用它的hash()函数。

因此,您需要回答的问题是如何在CF中散列密码以便能够对DNN用户进行身份验证:

  1. DNN使用什么算法来散列密码?
  2. 在散列之前,如何将盐与密码一起使用?
  3. DNN是否在哈希X次上迭代以提高安全性?
  4. 必须回答所有这些问题,以确定CF必须如何结合salt和用户提交的密码使用hash()函数。

    我会做一些假设来提供答案。

    如果我们假设正在进行小手术并且在使用SHA1散列密码之前将盐简单地附加到密码,那么您将能够像这样重现散列摘要:

    <cfset hashDigest = hash(FORM.usersubmittedPassword & saltFromDB, "SHA1") />
    

答案 2 :(得分:1)

(发布新的回复以使“加密”过程与“哈希”分开)

对于“加密”密钥,DNN端使用标准算法,即DES,3DES或AES - 具体取决于您的machineKey设置。但是您需要在CF代码中找到一些差异。如果不知道您的实际设置,我会假设您现在使用的是默认3DES

要加密的数据

加密值是salt和password的组合。但与散列一样,DNN使用UTF-16LE。不幸的是,ColdFusion的Encrypt()函数总是采用UTF-8,这会产生非常不同的结果。因此,您需要使用EncryptBinary函数。

    // sample valus
    plainPassword = "password12345";
    base64Salt    = "x7le6CBSEvsFeqklvLbMUw==";
    hexDecryptKey = "303132333435363738393031323334353637383930313233";

    // first extract the bytes of the salt and password
    saltBytes = binaryDecode(base64Salt, "base64");
    passBytes = charsetDecode(plainPassword, "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 );


加密算法

使用分组密码,ColdFusion默认为ECB mode。 (参见Strong Encryption in ColdFusion).NET默认为CBC模式,这需要额外的IV值。因此,您必须调整您的CF代码以匹配。

    // convert DNN hex key to base64 for ColdFusion
    base64Key  = binaryEncode(binaryDecode( hexDecryptKey, "hex"),  "base64");

    // create an IV and intialize it with all zeroes
    // block size:  16 => AES, 8=> DES or TripleDES 
    blockSize = 8; 
    iv = javacast("byte[]", listToArray(repeatString("0,", blocksize)));

    // encrypt using CBC mode 
    bytes = encryptBinary(dataBytes, base64Key, "DESede/CBC/PKCS5Padding", iv);

    // result: WBAnoV+7cLVI95LwVQhtysHb5/pjqVG35nP5Zdu7T/Cn94Sd8v1Vk9zpjQSFGSkv 
    WriteOutput("encrypted password="& binaryEncode( bytes, "base64" ));
相关问题