一个简单的方式搞定密码的加盐哈希与验证

简介: 过去一段时间来, 众多的网站遭遇用户密码数据库泄露事件。层出不穷的类似事件对用户会造成巨大的影响,因为人们往往习惯在不同网站使用相同的密码,一家 “暴库”,全部遭殃。

过去一段时间来, 众多的网站遭遇用户密码数据库泄露事件。层出不穷的类似事件对用户会造成巨大的影响,因为人们往往习惯在不同网站使用相同的密码,一家 “暴库”,全部遭殃。

单向加密

一个简单的方案是将明文密码做单向哈希后存储。

单向哈希算法有一个特性,无法通过哈希后的摘要(digest) 恢复原始数据,这也是 “单向” 二字的来源,这一点和所有的加密算法都不同。常用的单向哈希算法包括 SHA-256, SHA-1, MD5 等。例如,对密码“passwordhunter” 进行 SHA-256 哈希后的摘要 (digest) 如下:

“bbed833d2c7805c4bf039b140bec7e7452125a04efa9e0b296395a9b95c2d44c”

可能是 “单向” 二字有误导性,也可能是上面那串数字唬人,不少人误以为这种方式很可靠, 其实不然。

单向哈希有两个特性:

1)从同一个密码进行单向哈希,得到的总是唯一确定的摘要

2)计算速度快。随着技术进步,尤其是显卡在高性能计算中的普及,一秒钟能够完成数十亿次单向哈希计算

结合上面两个特点,考虑到多数人所使用的密码为常见的组合,攻击者可以将所有密码的常见组合进行单向哈希,得到一个摘要组合, 然后与数据库中的摘要进行比对即可获得对应的密码。这个摘要组合也被称为 rainbow table(彩虹表)。

更糟糕的是,一个攻击者只要建立上述的rainbow table,可以匹配所有的密码数据库。仍然等同于一家 “暴库”,全部遭殃。

加盐哈希

将明文密码混入 “随机因素 “,然后进行单向哈希后存储,也就是所谓的”Salted Hash(加盐哈希)”。

这个方式相比上面的方案,最大的好处是针对每一个数据库中的密码,都需要建立一个完整的 rainbow table 进行匹配。 因为两个同样使用 “passwordhunter”作为密码的账户,在数据库中存储的摘要完全不同。

在 C# 中实现加盐哈希

早在2016年,MD5 作为哈希算法已经不可靠,可以人为制造碰撞,于是本文采用了 SHA256 作为哈希算法。同时在哈希前生成了一个 Guid 作为盐和哈希值拼接在一起:

    using System;
    using System.Security.Cryptography;
    using System.Text;

    public class PasswordHasher
    {
        public string HashPassword(string password)
        {
            var rnd = Guid.NewGuid().ToString("N").Substring(10);
            return BuildHash(rnd, password);
        }

        public bool CheckPassword(string password, string hash)
        {
            if (string.IsNullOrWhiteSpace(hash))
            {
                return false;
            }

            var items = hash.Split('|');
            if (items.Length != 2)
            {
                return false;
            }

            var rnd = items[0];
            return hash == BuildHash(rnd, password);
        }

        private string BuildHash(string rnd, string password)
        {
            var key = rnd + "|" + password.Trim();
            var hash = Hash(key);
            return rnd + "|" + hash;
        }

        private string Hash(string input)
        {
            using (var sha = new SHA256CryptoServiceProvider())
            {
                var bytes = Encoding.UTF8.GetBytes(input);
                bytes = sha.ComputeHash(bytes);
                return Convert.ToBase64String(bytes);
            }
        }
    }

生成加盐哈希值:

    //生成加盐哈希
    var hasher = new PasswordHasher();
    var pwd = hasher.HashPassword("123456");
    Console.WriteLine("加盐哈希值为:{0}",pwd);

校验密码是否匹配:

    //校验密码是否匹配
    var hasher = new PasswordHasher();
    var hash = "89455bb276f037799fea1d|1rcfw+tSKhpG7zuW7Sm6SuMgjafAwsMg76OlyFkXLm8=";
    var pwd = "123456";
    if (hasher.CheckPassword(pwd, hash))
    {
        Console.WriteLine("密码正确");
    }
    else
    {
        Console.WriteLine("密码不匹配");
    }
目录
相关文章
|
网络协议 网络架构
什么是BGP机房?3分钟全面了解BGP机房
购买服务器最常见的术语就是BGP机房,什么是BGP机房?BGP机房有什么特点?服务器百科网带你3分钟全面了解BGP机房: 什么是BGP机房? 在了解BGP机房之前服务器百科网带大家先了解下BGP,BGP是指边界网关协议(Border Gateway Protocol),BGP是运行于TCP上的一种自治系统(AS)的路由协议,是能够妥善处理不相关路由域间的多路连接的协议。
15136 2
|
边缘计算 缓存 安全
GitHub Release下载慢、老中断?断点续传多线路加速方案
GitHub未在中国大陆部署服务器与CDN,所有访问需经跨境出口,受国际链路拥塞、丢包等影响,导致时通时断、图片/头像/Release下载失败,严重影响开发效率。(239字)
756 0
|
6月前
|
Shell Python Windows
Python 3.14安装教程 Windows版:环境变量配置+IDLE启动+自定义路径指南
Python是成熟稳定的开源面向对象语言,简单易学、跨平台。本文详解Python 3.14安装:下载解压→管理员运行Setup→勾选添加PATH和“为所有用户安装”→自定义路径(如D:\Python314)→完成安装→通过IDLE验证成功。
|
缓存 开发工具 git
Git创建分支以及合并分支
在Git中,创建分支使用`git branch [branch_name]`,切换分支使用`git checkout [branch_name]`。修改文件后,通过`git add [file]`添加到暂存区,然后`git commit`提交到本地仓库。如果是新建分支的第一次推送,使用`git push origin [branch_name]`推送到远程仓库,之后可以简化为`git push`。合并分支时,使用`git merge [branch_name]`将指定分支的更改合并到当前分支。
810 2
Git创建分支以及合并分支
|
存储 安全 算法
深入探索iOS系统安全机制:保护用户隐私的前沿技术
本文旨在探讨苹果公司在其广受欢迎的iOS操作系统中实施的先进安全措施,这些措施如何共同作用以保护用户的隐私和数据安全。我们将深入了解iOS的安全架构,包括其硬件和软件层面的创新,以及苹果如何通过持续的软件更新来应对新兴的安全威胁。此外,我们还将讨论iOS系统中的一些关键安全功能,如Face ID、加密技术和沙箱环境,以及它们如何帮助防止未经授权的访问和数据泄露。
|
安全 网络协议 网络安全
BACnet初学者教程,第一章:BACnet/IP介绍
BACnet初学者教程,第一章:BACnet/IP介绍
1163 0
|
消息中间件 Java Kafka
如何在Kafka分布式环境中保证消息的顺序消费?深入剖析Kafka机制,带你一探究竟!
【8月更文挑战第24天】Apache Kafka是一款专为实时数据管道和流处理设计的分布式平台,以其高效的消息发布与订阅功能著称。在分布式环境中确保消息按序消费颇具挑战。本文首先介绍了Kafka通过Topic分区实现消息排序的基本机制,随后详细阐述了几种保证消息顺序性的策略,包括使用单分区Topic、消费者组搭配单分区消费、幂等性生产者以及事务支持等技术手段。最后,通过一个Java示例演示了如何利用Kafka消费者确保消息按序消费的具体实现过程。
1268 3
|
Linux Windows
IDEA如何查看每一行代码的提交记录(人员,时间)
【9月更文挑战第24天】在IntelliJ IDEA中,可通过安装GitToolBox插件并利用其功能来便捷地查看每行代码的提交记录,包括提交者、时间和提交信息。具体操作为:首先安装GitToolBox插件,然后在代码编辑区域将鼠标悬停于目标代码行以查看简要信息,或使用快捷键打开“Version Control”窗口查看详细提交历史。
9142 2
|
IDE Java 开发工具
python缩进错误(IndentationError)
【7月更文挑战第12天】
3401 10
|
JSON 自然语言处理 数据处理
数据标注工具 Label-Studio
数据标注工具 Label-Studio
8084 0