加密盐

1 背景

涉及身份验证的系统都需要存储用户的认证信息,常用的用户认证方式主要为用户名和密码的方式,为了安全起见,用户输入的密码需要保存为密文形式,可采用已公开的不可逆的hash加密算法,比如SHA256, SHA512, SHA3等,对于同一密码,同一加密算法会产生相同的hash值,这样,当用户进行身份验证时,也可对用户输入的明文密码应用相同的hash加密算法,得出一个hash值,然后使用该hash值和之前存储好的密文值进行对照,如果两个值相同,则密码认证成功,否则密码认证失败。

由于密码是由用户设定的,在实际应用中,用户设置的密码复杂度可能不够高,同时不同的用户极有可能会使用相同的密码,那么这些用户对应的密文也会相同,这样,当存储用户密码的数据库泄露后,攻击者会很容易便能找到相同密码的用户,从而也降低了破解密码的难度,因此,在对用户密码进行加密时,需要考虑对密码进行掩饰,即使是相同的密码,也应该要保存为不同的密文,即使用户输入的是弱密码,也需要考虑进行增强,从而增加密码被攻破的难度,而使用带盐的加密hash值便能满足该需求。

2 加密盐的实现方法

2.1 加密存储

输入: 密码字符串passWord

输出:盐值 salt 、密码密文passWordHash

函数:加密hash函数

其中:“盐值 salt”是在加密过程中生成的随机字符串;

可以将salt放到passWord前面作为前缀或放到passWord后面作为后缀得到新的字符串PS,即,PS = password和salt的组合串;

密码密文passWordHash = Hash加密函数(PS );

将用户名、密码密文passWordHash和盐值salt一起保存到数据库中。

2.2 密码校验

输入: 密码字符串passWordCur

输出:密码校验是否成功

处理: 1)、取出当前用户密码加密时使用的盐值salt

2)、得到本次输入的密码passWordCur和盐值salt的组合字符串PS

3)、得出本次输入密码的密文passWordHashCur= Hash加密函数(PS );

4)、比较passWordHashCur和用户最初设置的密码密文passWordHash是否一致,如果一致,则校验成功,否则校验失败。

3 常用的密码攻击方式

常用的密码攻击方式有字典攻击、暴力破解、查表法、反向查表法、彩虹表等。

对字典攻击和暴力破解,攻击者均采用逐密码尝试的方式,目前没有很好的手段来阻止字典攻击和暴力破解攻击,只能是想办法让这两种攻击方式变得相对低效一些,而相同的密码产生不同的hash值便能让攻击者针对每一个hash值都需要从头进行尝试,从而使攻击变得更加低效。

对查表法、反向查表法和彩虹表攻击方式,攻击者需要提前准备好包含密码和密码hash值的密码表,然后根据该表和用户密码数据库进行批量匹配,从而达到攻破密码的目的;而如果我们在加密时,给每个密码附加了不同的随机值,这样每个密码对应的hash值也会不同,这样攻击者在准备密码表时,就必须要将最基本的密码和用户密码数据库中的盐值进行笛卡尔积后再计算hash值,盐值越多,用户需要准备的表量越大,这样对于攻击而言,就变得有些得不偿失了。

4 加盐的注意事项

加盐的目的是为了增加攻击者破解的难度,那么在加盐的时候要注意以下几点,否则加盐的意义也不会太大。

1)、盐值不能太短;如果盐值只有少数两三位甚至一两位的话,攻击者完全可以穷举所有可能的盐值;关于盐值长度的一个经验值是长度至少要和hash加密函数的返回值长度保持一致。

2)、盐值不能固定;如果系统使用了固定的盐值,那么和不加盐相当于是一回事了,攻击者完全可以使用该固定的盐值提前准备密码表;另外,相同密码对应的hash值仍然是一样的,仍然无法对密码相同这一事实进行掩饰。

3)、不要使用能提前预知的值作为盐值;如果盐值能提前得知或提前推断出,攻击者也完全可以根据提前预知的盐值准备密码表,从而对破解的难度也增加不了多少。

4)、每一次修改密码重新计算hash值时,要重新生成新的盐值,不要使用上次密码对应的盐值;因为如果用户密码泄露之后,盐值相应的也就泄露了,用户修改密码时,如果还沿用原来的盐值,攻击者也仍然可以根据上次的盐值提前准备密码表,从而使攻破可能性变得更高了。

5 加密盐代码实现举例(C#)

5.1 得到密码密文

/// <summary>
        /// 对用户输入的密码进行加密
        /// </summary>
        /// <param name="passWord">输入的明文密码</param>
        /// <param name="salt">加密过程中产生的盐值</param>
        /// <returns>加密后的密码值</returns>
        private static string GetHashSha256AndSalt(string passWord,out string salt)
        {
            //首先生成随机加密盐
            RandomNumberGenerator saltNumber = new RNGCryptoServiceProvider();
            byte[] s = new byte[256];
            saltNumber.GetBytes(s);
            salt = Convert.ToBase64String(s); //将盐值转化为字符串
            return GetHashSha256(passWord, salt);//针对盐值和密码一起应用hash加密函数,得到明文密码
        }
        /// <summary>
        /// 对用户输入的密码采用指定的盐值进行加密
        /// </summary>
        /// <param name="passWord">输入的明文密码</param>
        /// <param name="salt">指定的盐值</param>
        /// <returns>加密后的密码值</returns>
        private static string GetHashSha256(string passWord, string salt)
        {
            byte[] bytes = Encoding.Unicode.GetBytes(salt + passWord); //将盐值和密码进行组合
            SHA256Managed hashstring = new SHA256Managed();
            byte[] hash = hashstring.ComputeHash(bytes);//针对组合后的数据应用hash函数
            string hashString = string.Empty;
            foreach (byte x in hash)
            {
                hashString += String.Format("{0:x2}", x);
            }
            return hashString; //得到加密后的密文字符串
        }

应用效果:

Console.WriteLine("请输入新密码(若取消请按ESC键):");
                string passWord = string.Empty;
                bool isSucessed = GetUserInput(out passWord);//获取用户输入
                if (isSucessed == false)
                    break;
                string salt = string.Empty;
                string passWordHash = GetHashSha256AndSalt(passWord, out salt);//对密码进行加密
                Console.WriteLine("SHA256对应hash值为:{0}\n盐值为:{1}", passWordHash, salt);
对应输出:
请输入新密码(若取消请按ESC键):
******
SHA256对应hash值为:a5e5623028967e78ee79aa5aa8a6613d60252b9984af5db4e0c00e7de564d12f
盐值为:dPBQ6pbaCBaQjwlXv0B44gj4ErTRMo+1Dn5BQPgdxeMNvZu3qV+XlBlG+nict9bN0rQITbqzpzY1zXG5JxkBPQeVagsk05nUqDamP7Lhc4XEFrQrQn86oqKsCaG988Too2ad85ns4B7TmMswTWKsGzA3xWKQj2qjtMnaMB2NwHBpMD2jxnQLdGQEtIw8nF+m4xOA8U3wAeHPAnbIai+mt4k4DgI7OMitm42I80geO7vQexfGXcHR1c7j2hO++6aqb+jbpHwTmgtvi83gNghDj/iG67jk2a0FX8N0/knalhgHhmGom7rCuWmA86llfkk4H1cAfHImnA6cUiL2Viau2w==

5.2 密码校验

/// <summary>
        /// 密码校验
        /// </summary>
        /// <param name="passWordHash">密码的hash值</param>
        /// <param name="salt">盐值</param>
        private static bool ValidPSW(string passWordHash, string salt)
        {
            Console.WriteLine("请再次输入密码进行校验(若取消请按ESC键):");
            string passWord = string.Empty;
            bool isSucessed = GetUserInput(out passWord);
            if (isSucessed == false)
                return false;
            string passWordHashNew = GetHashSha256(passWord, salt); //将用户数据的密码采用已知的盐值进行加密
            bool isValid = SlowEquals(passWordHashNew, passWordHash);//校验密码hash值是否一致
            if (isValid)
            {
                Console.WriteLine("密码校验通过");
            }
            else
            {
                Console.WriteLine("两次输入密码不一致");
                return ValidPSW(passWordHash, salt);
            }
            Console.WriteLine();
            return true;
        }

应用效果:

输出:
请再次输入密码进行校验(若取消请按ESC键):
******
两次输入密码不一致
请再次输入密码进行校验(若取消请按ESC键):
******
密码校验通过

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • mysq配置参数详细说明

    mysql最大并发数|Linux修改Mysql最大并发连接数 第一步,先查看下当前MYSQL的最大连接数 [root@localhost ~]# /u...

    梦_之_旅
  • 用clipboard.js实现纯JS复制文本到剪切板

    ZeroClipboard是利用flash来实现的,ZeroClipboard兼容性很好,但是由于现在越来越多的浏览器不支持flash,导致一些没法正常使用了。

    梦_之_旅
  • axure如何创建弹出层

    右键转换为动态面板,双击选择动态面板,在动态面板中放入一个图片框并选择图片,将动态面板和图片作为一个组合,如图所示:

    梦_之_旅
  • md5和password_hash谁跟牛X

    加密方式更全面.使用起来也比md5+salt这种方式要简洁很多,最主要的是难破解,因为它每时每刻都在变动

    双面人
  • PassWord:一个简单的记录和管理多个账号密码的工具!

    我们有时候在很多网站都有账号,而且单个网站就有不少,这时候就很容易忘记了,而且有时候密码都喜欢搞一样,这样是很不安全的,这里就分享个很简单的工具,由吾爱的cc2...

    FreeRonin
  • Nightwatch中如何模拟键盘操作

    在自动化测试中有这样一个场景,在一个输入框中输入一串字符,然后执行敲回车键,验证搜索结果,以Google搜索为例,代码如下:

    Peter Shen
  • 基于Redis实现消息队列的6种方案之方案简述(中)

    在《基于Redis实现消息队列的6种方案之方案简述(上)》中我们讲到了基于List类型实现的消息队列,今天我们来讲下优先队列的实现。

    不太灵光的程序员
  • TCGA数据下载:R包TCGAbiolinks介绍

    昨天介绍了TCGA2STAT这个R包,今天来继续根据博文 TCGA数据下载方法简介中的顺序来介绍R包TCGAbiolinks包,其下载数据类型类似于TCGA2S...

    努力在北京混出人样
  • 腾讯云Web应用防火墙「网站管家」优惠-腾讯云优惠

    腾讯云 Web 应用防火墙(下文中也叫网站管家)( Web Application Firewall,WAF)帮助腾讯云内及云外用户应对 Web 攻击、入侵、漏...

    用户5899205
  • python 安装pip和Django

    py3study

扫码关注云+社区

领取腾讯云代金券