V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
skyworker
V2EX  ›  PHP

PHP 是最好的语言! 那怎么兼容这个原来的.net 的历史遗留问题

  •  
  •   skyworker · 2015-06-02 16:37:47 +08:00 · 4057 次点击
    这是一个创建于 3467 天前的主题,其中的信息可能已经有所发展或是发生改变。

    手上有个系统,是.net写的。这个.net系统在加密用户密码时候,没有用salt,而是在MD5的基础上,进行了16进制转换和位偏移,并且用户的历史密码也是用这种方式来保存:

    public static string Encrypt(string pwd)
            {
                StringBuilder returnValue = new StringBuilder();
                var data = Encoding.Unicode.GetBytes(pwd);
                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
    
                var result = md5.ComputeHash(data);
    
                foreach (var t in result)
                {
                    returnValue.Append(t.ToString("X", CultureInfo.CurrentCulture).PadLeft(2, '0'));
                }
    
                return returnValue.ToString();
            }
    

    那么作为最好的语言,PHP怎么才能写一个类似的密码验证函数?嗯,主要是用在登录的时候,匹配用户密码是否正确。微软那一套东西很久就不看了,实在搞不通.net那帮家伙们,直接用salt不久解决了的问题,非要弄一段自以为了不起的“变种”MD5加密。

    嗯,问题来了,有木有熟悉PHP和.net的高手帮我用PHP实现一下?

    18 条回复    2015-06-06 13:45:45 +08:00
    Livid
        1
    Livid  
    MOD
       2015-06-02 16:39:17 +08:00
    MD5CryptoServiceProvider 的源代码你有吗?
    breestealth
        2
    breestealth  
       2015-06-02 16:40:11 +08:00
    难道PHP保存密码的标准姿势不应该是自带的password_hash和password_verify么?
    skyworker
        3
    skyworker  
    OP
       2015-06-02 16:42:28 +08:00
    @Livid MD5CryptoServiceProvider 应该是.net默认的

    @breestealth 这是为了兼容老系统。老系统是用这段代码加密用户password的,php系统只能针对老系统,做一个外围。所以php只能兼容老的.net系统的加密方式
    Septembers
        4
    Septembers  
       2015-06-02 16:44:25 +08:00   ❤️ 2
    $password = md5(mb_convert_encoding($pwd, 'UTF-16LE'));
    see https://stackoverflow.com/a/16538976
    skyworker
        5
    skyworker  
    OP
       2015-06-02 16:49:30 +08:00   ❤️ 1
    @Septembers 我靠,差不多解决了。PHP产生的password只是在大小写上不一样,应该能用参数解决。

    再说一遍,PHP是最好的语言
    Septembers
        6
    Septembers  
       2015-06-02 16:52:06 +08:00
    @skyworker 善用Google(我不是PHPer
    fangjinmin
        7
    fangjinmin  
       2015-06-02 17:43:51 +08:00
    你给的这个代码取的就是MD5码的,并没有位移什么的, 只不过, .net的这段代码不保证是小写。
    webflier
        8
    webflier  
       2015-06-02 17:55:08 +08:00
    MD5CryptoServiceProvider 的代码在Microsoft .NET Reference Source里有。请移步github。
    另外,也可参考mono的实现
    Athrob
        9
    Athrob  
       2015-06-02 18:26:28 +08:00
    其实找个会C#的一看就懂了, 被这标题吸引到了...
    jeriwu
        10
    jeriwu  
       2015-06-02 18:27:37 +08:00
    楼主是不是想要这个函数 ord ?
    klmun
        11
    klmun  
       2015-06-02 20:48:18 +08:00
    作为一枚.net狗告诉你,这个就是普通的md5。
    skyworker
        12
    skyworker  
    OP
       2015-06-02 21:30:44 +08:00
    @klmun 我觉得,var result = md5.ComputeHash(data); 应该才是是用.net内置的MD5 hash默认算法获取的哈希密码。

    然后后来的那一坨迭代,我觉得是这个函数的作者在自作聪明,对默认的哈希密码再做个小处理。 不知道我猜的对不对。
    caoyue
        13
    caoyue  
       2015-06-02 22:36:20 +08:00
    你们想多了,这就是 md5 的 C# 标准实现
    注意是 md5(unicode),楼主之前 md5 结果不对可能是没有做编码转换
    caoyue
        14
    caoyue  
       2015-06-02 23:20:17 +08:00
    @caoyue
    忘了说了,C# 所谓的 Encoding.Unicode 实际上是 UTF-16

    php 不会,上面的 Encrypt 函数等价于 Python 的
    hashlib.md5(u'123456'.encode('utf-16le')).hexdigest()
    hjc4869
        15
    hjc4869  
       2015-06-02 23:38:07 +08:00
    看了下标题。。。怎么我最近是在.NET里处理PHP里的历史遗留问题…难道楼主和我的时间线是反的……
    Hyperion
        16
    Hyperion  
       2015-06-03 00:17:34 +08:00
    这个其实不能叫历史遗留问题, 这个应该叫语言和库的差异问题..
    clowwindy
        17
    clowwindy  
       2015-06-03 17:35:01 +08:00
    问题不在 .Net 和 PHP,在于你并不理解字符串和编码 =。=
    caizixian
        18
    caizixian  
       2015-06-06 13:45:45 +08:00
    @clowwindy 对头
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1039 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:51 · PVG 04:51 · LAX 12:51 · JFK 15:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.