惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
Recent Announcements
Recent Announcements
H
Help Net Security
Y
Y Combinator Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
有赞技术团队
有赞技术团队
小众软件
小众软件
Last Week in AI
Last Week in AI
U
Unit 42
Google DeepMind News
Google DeepMind News
博客园 - 司徒正美
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
Microsoft Security Blog
Microsoft Security Blog
G
Google Developers Blog
N
Netflix TechBlog - Medium
Blog — PlanetScale
Blog — PlanetScale
云风的 BLOG
云风的 BLOG
V
V2EX
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
博客园 - 三生石上(FineUI控件)
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿

博客园 - 老三

“内部开源” 视野,自学,和其他 反编译yield未解决问题记录 编译,调试mono运行时 确实,是有学习曲线的 mono 的Sgen mono 执行顺序 UTF8编码 *nix mono 找不到 MySql.Data Could not be loaded *nix,mono运行reflector 【翻译】正确的精神 11期Beta技术沙龙总结体会 记一次Cookie调试 Hubble.net Maillist 【译文】版本一很糟,但也坚持发布 《重构》读书体会以及近期相关工作 NHibernate no session or session was closed问题以及NH最佳实践 推荐the productive programmer Vim 还是 Emacs
MD5加密引出的一段代码
老三 · 2010-04-12 · via 博客园 - 老三

.NET平台的MD5加密做起来很容易,System.Security.Cryptography.MD5进行操作,很容易获得加密之后的字节数组。之所以经常会涉及一些和asp兼容的问题,主要来自于

  1. System.Security.Cryptography.MD5操作时候,其返回类型是byte[]
  2. 很多web项目直接使用 System.Web.Security.FormsAuthentication 的 HashPasswordForStoringInConfigFile 方法,这个方法直接返回String类型,大写,所以不兼容。

这引起了我看看ASP.NET到底是怎么实现这个HashPasswordForStoringInConfigFile方法的。看了一下,它的实现,也是先调用了MD5类,然后调用下面的方法,部分源码如下:

 static unsafe internal String ByteArrayToHexString(byte[] buf, int iLen)
        {
            char[] acharval = s_acharval; 
            if (acharval == null)
            { 
                acharval = new char[16]; 
                for (int i = acharval.Length; --i >= 0; )
                { 
                    if (i < 10)
                    {
                        acharval[i] = (char)('0' + i);
                    } 
                    else
                    { 
                        acharval[i] = (char)('A' + (i - 10)); 
                    }
                } 

                s_acharval = acharval;
            }
 
            if (buf == null)
                return null; 
 
            if (iLen == 0)
                iLen = buf.Length; 

            char[] chars = new char[iLen * 2];
            fixed (char* fc = chars, fcharval = acharval)
            { 
                fixed (byte* fb = buf)
                { 
                    char* pc; 
                    byte* pb;
                    pc = fc; 
                    pb = fb;
                    while (--iLen >= 0)
                    {
                        *pc++ = fcharval[(*pb & 0xf0) >> 4]; 
                        *pc++ = fcharval[*pb & 0x0f];
                        pb++; 
                    } 
                }
            } 

            return new String(chars);
        }

代码很漂亮,比可以搜索到的一些结果要好很多,这里完整的模拟了2进制转换16进制的方法,每四位变成一位,于是最初代码中创建了一个长度16位的 acharval  字节数组,代表了16进制中的16个表现形式。

由于byte是8为,两个与操作分别取高低8位,进行换算,很好看。

但是这里有了指针不是很理解,未免有点追求华丽的嫌疑,因为我用CodeTimer(thanks to @jeffz_cn) 的测试结果表明,不用指针,仅仅是foreach循环,算法一样的话,两种实现方式性能相差无几。

测试代码:

  private static void ToStringWithoutPointer(byte[] buf)
        {
            int iLen = buf.Length;
            char[] chars = new char[iLen * 2];
            int index = 0;

            foreach (var item in buf)
            {
                chars[index++] = acharval[(item & 0xf0) >> 4];
                chars[index++] = acharval[item & 0x0f];
            }

            //Console.WriteLine(new String(chars));
        }