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

推荐订阅源

H
Help Net Security
博客园 - Franky
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
Scott Helme
Scott Helme
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
C
CERT Recently Published Vulnerability Notes
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
L
LangChain Blog
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Hacker News: Front Page
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
AI
AI
T
Troy Hunt's Blog
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Security @ Cisco Blogs
Cloudbric
Cloudbric
E
Exploit-DB.com RSS Feed
Attack and Defense Labs
Attack and Defense Labs

博客园 - 找事的狐狸

“摸”电脑的时代(三):解析Surface内部结构 “摸”电脑的时代(二):多点触摸秀 写于Silverlight整装待发之际(八):也谈Silverlight人才招聘策略 WinHec扫盲贴 《WPF揭秘》勘误表 如何隐藏UpdatePanel 支付宝实名制实现思路 程序员的必备装备——为健康加油 [好书推荐] C#和.NET 2.0实战:平台、语言与框架 JavaScript的世界从来没有像现在这样精彩 CSS实现不同的打印和屏幕显示结果 [翻译] Vista中的音量II: Windows Vista音量种类 文件加密的简单实现(C语言) 如何检测是否安装了.NET 2.0和.NET 3.0 闲话WPF近期发展 浅析Family Show 2.0的子窗体实现 WPF实现Tag Cloud 浅析Family Show 2.0的数据结构及基本算法 如何实现一个不规则形状的WPF窗口
老调重弹——你存储的密码做Hash了吗?
数字游民托尼 · 2007-12-18 · via 博客园 - 找事的狐狸

看了标题,你马上会明白我这篇文章要讲什么——密码的Hash化,虽然这并不是什么新技术,也不是高端技术,但它确实很有意义。当然如果仅仅因为它有意义还不足以让我写这篇文章。有些人会觉得不就是密码Hash嘛,没有什么必要,还会影响网站的处理速度,如果你是这些人中的一员,请听我说两个真实的故事。

故事1
某黑客通过一些技术手段进入了一个刚刚起步的网站(至于用什么方法大家就不要多问了,再说与这篇文章关系不大),这个网站的安全问题很严重,严重到可以拿到所有用户的用户名、邮箱、网站密码。大家知道,很多人不喜欢记太多密码,他们在任何网站使用的永远是同一个密码。好了,问题出来了!这里面有大量的gmail、msn账户,也就是说知道邮箱,知道密码,我们不但能进入这个人的电子邮箱,还能进入googletalk或msn这样的及时聊天系统,从而获得更多的私人信息和关系网信息,甚至能冒用这个人的身份进行诈骗,还好这个黑客并没有恶意,并没有采取进一步的行动,否则后果不堪设想。

这个故事告诉我们在不同的网站、邮箱要使用不同的密码,当然要选择自己好记些的,但千万不要为了图方便而都用一样的密码,这是很危险的!特别是涉及金融、银行方面的网站更要使用高强度密码(有数字、大小写字母、下划线等组成),这样可以防止一些人用字典进行密码破解。从另一个角度看,这个故事还告诉我们,作为网站的开发者你必须时刻记住一点,在任何时候都不应该把机密数据用明文保存或传递,数据从进入系统那一刻开始网站就有义务保证数据的安全性,所以必须作相应的安全处理。对于密码,我们应该对密码做Hash,大家应该知道一个字符串无论何时做Hash,出来的结果是一样的,虽然从理论上讲会出现不同的字符串产生相同的Hash序列的情况,但是这种概率很低,基本上是中彩票的概率,这也是为什么要用Hash逆推出原文来几乎是不可能的,我们可以认为这种方法是安全的。

故事2
早上我在公交车上听到几句电话对话
甲:你密码忘记了?
....
甲:这个没关系,我帮你去问问IT部,他们知道密码是多少?
....

可能乍一看,这段对话很正常,没有什么特别的,但是我们可以分析一下其中的含义。密码忘了我们第一个想到的是什么——要回密码,但这能够实现吗?对于一个公司内部而言,这种密码获取还相对简单,毕竟大家可以方便地证明自己的身份,所以从业务上来讲似乎拿回密码一点问题都没有,但实际上,技术上不允许我们这么做。我们刚才说到过Hash是不可逆的,如果一个网管告诉你他可以帮你拿回原来的密码,这说明什么?说明密码很有可能是用明文存储的,这在很多情况下是很危险的,管理员可以利用自己的职权,获得一些人的密码,然后进入那些人的私人邮箱(非公司邮箱)盗取信息。即使有些密码是加密存储的,如果它是可逆的那也是不安全的,只要有加密后的字符串,且知道加密算法和密钥,也能轻易获得原密码,这同样是很危险的,当然相对而言这种方法要难许多、不是每个人都能做到的,但在第一个故事中我们看到如果某个黑客进入了这样的系统,仍然有办法获得原密码,毕竟黑客的技术水准要高出许多。从这一点我们应该意识到加密的密文必须不可逆,否则会带来进一步的信息泄漏。

好了,通过上面两个故事,我想大家应该对密码Hash的必要性比较认同了,希望以后在写code或者做架构设计的时候一定要把这个它考虑进去。从技术角度讲,我们只能为用户重置密码,但不能告诉用户原密码是什么,这一点live.com就做得很好,如果哪个网站可以拿回原密码,说明他不够安全,建议马上改密码!用一个和你的邮箱不一样的密码,特别是注册这个网站时使用的那个邮箱。

下面我顺便讲讲.NET下如何实现密码Hash化。有人说,Hash可以用

System.Security.Cryptography命名空间下面的加密类来实现,对,说得没错,我们的确可以这么做,但这似乎还是有些麻烦~~(我比较懒,呵呵)其实呢,.NET提供了一个专门用于做Password Hashing的方法,这在.NET 1.1中就有了,定义如下:

public static string HashPasswordForStoringInConfigFile (
    
string password,
    
string passwordFormat
)


第一个参数password就是密码,而第二个参数则是要使用的Hash算法,这个值只能是FormsAuthPasswordFormat枚举的成员(位于System.Web.Configuration下),不过不清楚为什么不直接传枚举类型。FormsAuthPasswordFormat有三个枚举成员,它们是Clear、MD5、SHA1,其中的Clear就是不加密,直接用明文的意思。

===========================更新2007.12.19====================================
感谢兄弟们提宝贵意见,加了一个基于Salt的密码Hash实现,代码如下:

    public class PasswordHelper
    
{
        
public static string CreateSalt(int size)
        
{
            
//Generate a cryptographic random number.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            
byte[] buff = new byte[size];
            rng.GetBytes(buff);

            
// Return a Base64 string representation of the random number.
            return Convert.ToBase64String(buff);
        }


        
public static string CreatePasswordHash(string pwd, string salt)
        
{
            
string saltAndPwd = String.Concat(pwd, salt);
            
string hashedPwd =
             FormsAuthentication.HashPasswordForStoringInConfigFile(
             saltAndPwd, 
"sha1");

            
return hashedPwd;
        }


        
public static bool PasswordMatch(string current,string salt,string savedPasswordHash)
        
{
            
string currentPasswordHash=CreatePasswordHash(current, salt);
            
return (currentPasswordHash == savedPasswordHash);
        }

    }