【问题标题】:Authenticating DotNetNuke Users in ColdFusion在 ColdFusion 中对 DotNetNuke 用户进行身份验证
【发布时间】:2012-09-21 05:43:59
【问题描述】:

是否有任何方法可以使用 DNN 登录验证来自其他 Web 应用程序的用户?

我们有一个使用 DNN 的主站点,用户登录信息存储在 asp 网络成员表中。根据我一直在阅读的内容,密码是使用机器密钥加密的,然后加盐。我看到此信息在哪里,但似乎无法使用此方法正确加密密码。

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

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

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

任何帮助、见解或指出我正确的方向将不胜感激!

【问题讨论】:

标签: coldfusion dotnetnuke single-sign-on


【解决方案1】:

(编辑:原始答案并非在所有情况下都有效。大幅修改......)

根据我的阅读,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 


【讨论】:

  • 我刚刚发现我们的设置使用的是加密密码格式,而不是散列。虽然,我确实发现了一件事是 SHA-256 产生了正确的加密长度,但仍然不是它应该的最终结果。
  • 你的意思是HMAC256?但是什么种类加密,AES,3DES,...?支持的类型似乎是vary by version 你的&lt;machineKey&gt; 设置是什么? (显然要清理任何加密密钥。)
  • 机器密钥设置为 SHA1 和 3DES
【解决方案2】:

密码很可能没有加密,它是散列的。散列不同于加密,因为它是不可逆的。

您不会为此使用 ColdFusion 的 encrypt() 函数,而是使用它的 hash() 函数。

因此,要弄清楚如何在 CF 中对密码进行哈希处理以便能够针对 DNN 用户进行身份验证,您需要回答的问题是:

  1. DNN 使用什么算法对密码进行哈希处理?
  2. 在散列之前如何将盐与密码一起使用?
  3. DNN 是否对哈希进行 X 次迭代以提高安全性?

必须回答所有这些问题才能确定 CF 如何将 hash() 函数与盐和用户提交的密码结合使用。

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

如果我们假设正在进行迭代,并且在使用 SHA1 对密码进行哈希处理之前将盐简单地附加到密码中,那么您将能够像这样重现哈希摘要:

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

【讨论】:

    【解决方案3】:

    (发布新的响应以将“加密”过程与“散列”分开)

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

    要加密的数据

    加密值是盐和密码的组合。但与散列一样,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" ));
    

    【讨论】:

    • 注意,如果您的版本不支持ArrayUtils.addAll,只需手动合并数组,如this post底部所示
    • 嗯,哇!谢谢你,利!您发布的代码非常完美!这是一个救生员!谢谢谢谢谢谢!
    • 不客气。这是一个有趣的问题:)(我喜欢互操作问题)
    • 哈!我终于能够为 NodeJS 重新创建它。非常感谢您的代码! :)
    • @SimonGermain - 很高兴它有帮助:)
    猜你喜欢
    • 2013-03-11
    • 2021-06-11
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    相关资源
    最近更新 更多