不同哈希加密算法安全分析及python实现

本文探讨了哈希算法在密码保护中的应用,指出MD5和SHA1因易遭暴力破解而不推荐用于加密。推荐使用PBKDF2、Argon2和Scrypt等加强型哈希算法,它们通过多次哈希提高安全性。比特币使用SHA256算法。加盐能提升安全性,避免彩虹表攻击。文中还提供了MD5、SHA256、SHA512及PBKDF2的Python实现示例。
摘要由CSDN通过智能技术生成

前言

哈希算法有时也被称作摘要算法,目的是将数据不可逆得转成一串固定长度的字符串。常用作密码保护等场景,如果我们只能拿到哈希计算之后的字符串,我们无法简单得推出他的原文。

目前来说,常用哈希算法有MD5、SHA1、SHA256、SHA512、SHA3等。

安全性

目单纯的md5和sha1已经不推荐用于加密场合了,因为使用的实在太频繁了。所以通过暴力破解(如彩虹表都可以破解出很大一部分密码了)

比特币目前用的是sha256算法

建议使用 PBKDF2, Argon2, Scrypt, Bcrypt 等方法 ,这些算法由于执行了多次的哈希,提高了暴力破解的难度,增加了安全性。

md5<<PBKDF2<Bcrypt<Scrypt

实用性

对于校验场合,md5一般都够用了,但是对于密码之类的敏感场合,请勿用md5,如果需要前后端都做哈希的话建议用PBKDF2+sha256,如果只做后端哈希的话可以考虑用Bcrypt。剩下的scrypt和argon2因为用的人太少不推荐。

加盐

一般的加盐实质就是在要加密的字符串前面或者后面加入一串随机字符串(hmac加盐不同)。这样就能把你的密码拉长增加安全性。而且推荐的做法是不同用户用不同的随机盐,这样就能防止诸如彩虹表的方法一次查表碰撞多个用户的密码。

md5 sha256 PBKDF2 Bcrypt实现示例


# -*- coding: utf-8 -*-
# @Time    : 2021/4/13 2:11 下午
# @Author  : meng_zhihao
# @Email   : 312141830@qq.com
# @File    : main.py


# 不同加密方式
import hashlib
import binascii
import bcrypt, time
import random


def md5(password):
    # 1 即使加盐,也有被彩虹表破解的可能
    # 2 有用被同一个md5的不同密码撞库的风险 (通过算法快速找到MD5(M1) = MD5(M2))
    md = hashlib.md5(password)  # 加盐减少彩虹表暴力破解风险(每个用户需要不同,这样就不能复用彩虹表)  加盐相当于在前面拼一截上去增加复杂度
    # md.update(b'5y3w4h')  # 加盐相当于拼到后面
    password_encrypt = md.hexdigest()
    return password_encrypt


def sha256(password):  # 比特币目前采用这种 但是这里的加盐也是就拼接一下的,所以盐的长度一定要够长
    s = hashlib.sha256()  # Get the hash algorithm.
    s.update(b's')
    s.update(password)  # Hash the data.
    b = s.hexdigest()  # Get he hash value.
    return b


def sha512(password):  # 更长,更安全
    s = hashlib.sha512()  # Get the hash algorithm.
    s.update(password)  # Hash the data.
    b = s.hexdigest()  # Get he hash value.
    return b


def gen_salt(len):
    rs = ''
    strs = 'abcdefghijklmnopqrstuvwxyz0123456789'
    for i in range(len):
        rs += random.choice(strs)
    return rs


# PBKDF2
def pbkdf2(password):  # 这个算法是把每次的结果当初盐值和原来的password继续算,然后把多次的结果取异或 前端做10000次需要0.5s,然而后端只需要0.0043s,差了100倍
    # 主要通过的是迭代来增加时长
    start = time.time()

    x = hashlib.pbkdf2_hmac("sha256", password, b"mysalt", 10000, dklen=32)  # 相同盐值,不同迭代次数 digestLength
    # 这算法能生成很多长度的结果,所以要约定最后结果字节数
    # 密钥被提取为最终哈希的前dkLen byte,这就是为什么存在大小限制的原因。
    print("x_3 = " + binascii.hexlify(x).decode())
    # 要防止暴力破解还是得每个用户一个盐值,并且配上合适的迭代次数(迭代次数建议和用户相关。。。)
    end = time.time()
    t = end - start
    print(t)


def Bcrypt(password):  # 比较适合密码,但是这校验不太对。。居然要密码原文
    salt = bcrypt.gensalt()
    print(salt)
    hash = bcrypt.hashpw(password, salt)  # 数据库存这个

    hash1 = bcrypt.hashpw(password, hash)  # 新密码
    print(hash, hash1)  # 生成的密码中,$是分割符,无意义;2a是bcrypt加密版本号;10是cost的值(默认值);而后的前22位是salt值;再然后的字符串就是密码的密文了
    # 特点是每次结果里带了盐值 好处是可以逐步增大work factor,而且不会影响已有用户的登陆

    # 速度调整 No argument (Default) - 0.192 ms:
    start = time.time()
    hashed = bcrypt.hashpw(password, bcrypt.gensalt())
    end = time.time()

    t = end - start
    print(t)

    # Work factor of 14 - 0.755 ms:
    start = time.time()
    hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=14))  # 成本稀疏就是2的多少次方
    end = time.time()
    t = end - start
    print(t)


def Scrypt():
    # 这个主要是对抗矿机的,需要内存和cpu更长
    pass


def print_hex(bytes):
    l = [hex(int(i)) for i in bytes]
    print(" ".join(l))


# 建议的盐值都很长很长
if __name__ == '__main__':
    password = b'aaaaaa'
    # print_hex(password)
    result = pbkdf2(password)
    # result = Bcrypt(password)  
    print(result)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值