hashlib 各种加密的使用

1. os 生成salt ---> (盐) --->(字节)

import os

print(os.urandom(16))
# 输出字节: b'\xc0Y\xc3`\x8aK\x0c\x18\x9ay\x1f\xe0\xe06\xc6\xb6'

2. secrets生成salt ---> (盐) --->(字节)

import secrets

token_hex = secrets.token_hex(16)
print(token_hex)
# 输出字符串 需要转为字节: 71cd0749b21cd3af7cc73fe965c00c30

print(token_hex.encode('utf-8'))
# 转为字节: b'221a4a7e7fbe6a024cf037dbd4214039'


token_urlsafe = secrets.token_urlsafe()
print(token_urlsafe)
# 输出字符串 需要转为字节: 0LXrsyB7xQsoBkc3D8NrQrj5Jyc4B8eYkM0ueULYFP8

print(token_urlsafe.encode('utf-8'))
# 转为字节: b'0a8ijqWZgpiEglrFzihPlO53spDPevwgeqH4oMIQLao'


token_bytes = secrets.token_bytes()
print(token_bytes)
# 输出字节: b'J\x10\xdeE4 W/\xef\x0b\x895\xf7\x9a\xd7Uc\x83\xb9\xf0\x83"\x01\x91\x064L>\x84\x96\xe9T'

3. 查看所有hash方法


import hashlib

print(hashlib.__all__)

'''
(
'md5', 
'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 
'blake2b', 'blake2s', 
'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 
'shake_128', 'shake_256', 
'new', 
'algorithms_guaranteed', 'algorithms_available', 
'pbkdf2_hmac'
)
'''

4. 以MD5为例 (除特殊方法) 其余方法直接套用

4.1 


import hashlib


pwd = b'123456'
hash_md51 = hashlib.md5(pwd)
hash_value = hash_md51.hexdigest()
print(hash_value)  # e10adc3949ba59abbe56e057f20f883e

4.2  


import hashlib


hash_md51 = hashlib.md5(b'123456')
hash_value = hash_md51.hexdigest()
print(hash_value)  # e10adc3949ba59abbe56e057f20f883e

4.3 


import hashlib


hash_md5 = hashlib.new('md5', b'')
hash_md5.update(b'123456')
v = hash_md5.hexdigest()
print(v)  # e10adc3949ba59abbe56e057f20f883e

4.3.1 加盐 (salt)

import hashlib



hash_md5 = hashlib.new('md5', b'123123')
hash_md5.update(b'123456')
v = hash_md5.hexdigest()
print(v)  # 207fa18ec8125a9bfeb825012e5ea911

4.4  


import hashlib


def MD5(s1, s2):
    obj = hashlib.md5(str(s1).encode('utf-8'))
    obj.update(str(s2).encode('utf-8'))
    return obj.hexdigest()


print(MD5('', '123456'))  # e10adc3949ba59abbe56e057f20f883e

4.4.1 加盐 (salt)

​

import hashlib


def MD5(salt, s2):
    obj = hashlib.md5(str(salt).encode('utf-8'))
    obj.update(str(s2).encode('utf-8'))
    return obj.hexdigest()


print(MD5('123123', '123456'))  # 207fa18ec8125a9bfeb825012e5ea911



​

5. new

作用:通用的哈希对象创建函数,可以指定算法名称。


import hashlib


# s = b'hello'
# hash_obj = hashlib.new('sha256', s)
# hash_obj.update(b'123123')
# print(hash_obj.hexdigest())  # 输出: '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'



s = b'hello'
hash_obj = hashlib.new('md5', s)
hash_obj.update(b'123123')
print(hash_obj.hexdigest())  # 输出: '1e350c24c64c6c64d2fcad12ba3e3572'

hashlib.new() 可以指定的算法取决于 Python 环境中可用的哈希算法。可以通过 hashlib.algorithms_guaranteedhashlib.algorithms_available 查看支持的算法。

通常,hashlib.new() 可以指定以下算法:

  • MD5: 'md5'

  • SHA-1: 'sha1'

  • SHA-224: 'sha224'

  • SHA-256: 'sha256'

  • SHA-384: 'sha384'

  • SHA-512: 'sha512'

  • BLAKE2s: 'blake2s'

  • BLAKE2b: 'blake2b'

  • SHA3-224: 'sha3_224'

  • SHA3-256: 'sha3_256'

  • SHA3-384: 'sha3_384'

  • SHA3-512: 'sha3_512'

  • SHAKE-128: 'shake_128'

  • SHAKE-256: 'shake_256'

6.  如果你安装了第三方库或在特定平台上运行,hashlib.new() 可能还支持其他算法。可以通过以下代码检查当前 Python 环境中可用的算法:

import hashlib

print(hashlib.algorithms_guaranteed)  # 查看保证可用的算法
print(hashlib.algorithms_available)   # 查看所有可用的算法



"""
{'shake_256', 'sha3_512', 'sha3_224', 'sha3_256', 'blake2b', 'sha256', 'sha224', 'shake_128', 'sha1', 'blake2s', 'sha384', 'sha512', 'sha3_384', 'md5'}
{'shake_256', 'sha3_512', 'sha3_256', 'sha224', 'blake2s', 'sha512', 'sha1', 'sm3', 'ripemd160', 'md5-sha1', 'sha384', 'blake2b', 'sha3_384', 'md5', 'sha512_224', 'sha3_224', 'sha512_256', 'sha256', 'shake_128'}

"""

7. pbkdf2_hmac

  • 作用:使用 PBKDF2(基于 HMAC 的密钥派生函数)从密码生成密钥。
  • 用法key = hashlib.pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None)
import hashlib 


password = b'password' 

salt = b'salt' 

key = hashlib.pbkdf2_hmac('sha256', password, salt, 100000) 

print(key.hex()) # 输出: 密钥的十六进制字符串

hashlib.pbkdf2_hmac:这是 Python 标准库提供的 PBKDF2 实现。

  • 'sha256':指定使用的哈希函数,可以换成 'sha512' 等其他函数。

  • password.encode('utf-8'):将密码转换为字节格式。

  • salt:使用生成的随机盐值。

  • iterations:迭代次数,越高越安全,默认推荐至少 100,000 次。

  • dklen:派生密钥的长度,这里为 32 字节(256 位)。

hashlib.pbkdf2_hmac 函数支持多种哈希算法,但不是所有你列出的算法都能用于 pbkdf2_hmac。下面我将详细解释哪些算法可以用于 hashlib.pbkdf2_hmac,以及其他列出的属性的用途。

7.1 支持的哈希算法

hashlib.pbkdf2_hmac 中,支持的哈希算法主要包括以下几种:

  1. md5:消息摘要算法 5,产生 128 位(16 字节)哈希值,不推荐用于密码哈希,因为它安全性较低。
  2. sha1:安全哈希算法 1,产生 160 位(20 字节)哈希值,也不再推荐用于安全应用。
  3. sha224:SHA-2 家族中的一个成员,产生 224 位(28 字节)哈希值。
  4. sha256:SHA-2 家族中的一个成员,产生 256 位(32 字节)哈希值,推荐用于大多数安全需求。
  5. sha384:SHA-2 家族中的一个成员,产生 384 位(48 字节)哈希值。
  6. sha512:SHA-2 家族中的一个成员,产生 512 位(64 字节)哈希值,推荐用于更高安全需求。

此外,hashlib 支持其他算法,但不适用于 pbkdf2_hmac

7.2 不适用于 pbkdf2_hmac 的算法

  1. blake2bblake2s

    • 这是高效的哈希函数,通常用于替代 MD5 和 SHA-1,但不能用于 pbkdf2_hmac
  2. sha3_224sha3_256sha3_384sha3_512

    • 这是 SHA-3 系列哈希算法,不直接支持 pbkdf2_hmac
  3. shake_128shake_256

    • 这是可变长度的 SHA-3 系列算法,同样不支持在 pbkdf2_hmac 中使用。

7.3 小结

hashlib.pbkdf2_hmac 中,你只能使用以下哈希算法:

  • 'md5'
  • 'sha1'
  • 'sha224'
  • 'sha256'
  • 'sha384'
  • 'sha512'

其他列出的算法和属性要么不适用于 pbkdf2_hmac,要么与密码哈希无关。建议使用 sha256 或更强的算法用于实际密码哈希,避免使用 md5sha1,因为它们已被认为不再安全。

8.  scrypt 是一种强大的密码哈希函数,设计时专注于抵抗大规模硬件攻击(如 FPGA 和 ASIC 攻击)。它与 bcryptPBKDF2 类似,但提供了更好的安全性,因为它需要大量的内存来执行哈希计算,从而增加了攻击者的成本。

scrypt 的特点

  • 内存硬性要求scrypt 设计为对内存使用敏感,增加了大规模并行硬件破解的难度。
  • 可调参数:允许通过调整参数来控制计算的复杂度和内存需求。
  • 内置盐值:与 bcrypt 一样,scrypt 也自动生成并使用盐值,确保即使相同的密码每次生成的哈希也不同。

8.1 使用 scrypt 进行密码哈希和验证

以下是使用 Python 的 hashlib 库内置的 scrypt 函数来进行密码哈希和验证的基本步骤:

import os 
import hashlib 


def hash_password(password, salt=None, n=2**14, r=8, p=1): 
    if not salt: 
        salt = os.urandom(16) # 生成16字节的随机盐 
    key = hashlib.scrypt(password.encode('utf-8'), salt=salt, n=n, r=r, p=p, maxmem=0, dklen=64) 
    return salt + key # 返回盐和哈希值的组合 


hashed = hash_password('mypassword') 
print(hashed) # 输出二进制数据(盐 + 哈希)

def check_password(stored_password, provided_password, n=2**14, r=8, p=1): 
    salt = stored_password[:16] # 提取前16字节的盐 
    stored_key = stored_password[16:] # 提取哈希值 
    key = hashlib.scrypt(provided_password.encode('utf-8'), salt=salt, n=n, r=r, p=p, maxmem=0, dklen=64) 

    return key == stored_key # 比较生成的哈希值与存储的哈希值 # 验证密码 
   

result = check_password(hashed, 'mypassword') 
print(result) # 输出: True 或 False

8.2 示例代码

完整的密码哈希和验证示例:

import os
import hashlib

# 生成哈希
def hash_password(password, salt=None, n=2**14, r=8, p=1):
    if not salt:
        salt = os.urandom(16)  # 生成16字节的随机盐
    key = hashlib.scrypt(password.encode('utf-8'), salt=salt, n=n, r=r, p=p, maxmem=0, dklen=64)
    return salt + key  # 返回盐和哈希值的组合

# 验证密码
def check_password(stored_password, provided_password, n=2**14, r=8, p=1):
    salt = stored_password[:16]  # 提取前16字节的盐
    stored_key = stored_password[16:]  # 提取哈希值
    key = hashlib.scrypt(provided_password.encode('utf-8'), salt=salt, n=n, r=r, p=p, maxmem=0, dklen=64)
    return key == stored_key  # 比较生成的哈希值与存储的哈希值

# 使用示例
if __name__ == "__main__":
    # 用户注册时生成哈希
    password = "mypassword"
    hashed = hash_password(password)
    print(f"Hashed password: {hashed}")

    # 用户登录时验证密码
    result = check_password(hashed, "mypassword")
    print(f"Password is correct: {result}")  # 输出: True

8.3 调整参数

scrypt 的参数可以根据需要调整:

  • n:工作因子,必须是2的幂,值越大,计算成本越高,安全性越强。推荐值在 2**142**20 之间。
  • r:块大小,推荐值为 8
  • p:并行因子,推荐值为 1。增加此值会增加 CPU 成本。

8.4 安全性注意事项

  • scrypt 在默认参数下已经非常安全,可以抵抗大规模硬件攻击。通过增加 n 值可以进一步提高安全性,但会增加计算成本。
  • bcrypt 相比,scrypt 对内存的要求更高,适用于需要极高安全性的应用场景。

scrypt 是现代密码哈希的推荐选择之一,特别适合在需要高安全性、需要防止大规模硬件破解的场景中使用。

9. bcrypt 是一种密码哈希函数,专为密码存储而设计,具有以下特点:

  • 慢速计算:相比于 MD5 或 SHA 系列哈希算法,bcrypt 的计算速度更慢,这使得它在抵御暴力破解时更加有效。
  • 内置盐值bcrypt 在生成哈希时会自动生成并包含一个随机的盐值,无需手动管理。
  • 调整复杂度:可以通过调整计算成本(cost factor)来增加计算的复杂度,从而增加破解难度。

9. 1使用 bcrypt 进行密码哈希和验证

下面是使用 Python 的 bcrypt 库进行密码哈希和验证的基本步骤:

pip install bcrypt


# # 生成随机盐 salt
# bcrypt.gensalt()

# # 加密
# bcrypt.hashpw()

# # 密码比较
# bcrypt.checkpw()

# # 派生密钥
# bcrypt.kdf()




import bcrypt


# 原始密码
password = b"111"

# 生成随机盐值
salt = bcrypt.gensalt()
print(salt)

# 派生密钥
derived_key = bcrypt.kdf(
    password=password,
    salt=salt,
    desired_key_bytes=32,  # 期望生成的密钥长度
    rounds=12,  # 工作因子(迭代次数)
)

print(f"Derived key: {derived_key.hex()}")
  1. 生成密码哈希

import bcrypt

def hash_password(password):
    # 生成盐值并创建哈希
    salt = bcrypt.gensalt()
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)
    return hashed_password

hashed = hash_password('mypassword')
print(hashed)  # 输出: b'$2b$12$...'
  • bcrypt.gensalt():生成一个包含计算成本(默认值为 12)的盐值。
  • bcrypt.hashpw():生成密码的哈希值。返回的哈希值中包含盐值和成本因子。

  1. 验证密码

def check_password(provided_password, stored_hash):
    return bcrypt.checkpw(provided_password.encode('utf-8'), stored_hash)

# 验证密码
result = check_password('mypassword', hashed)
print(result)  # 输出: True 或 False

 bcrypt.checkpw():验证用户提供的密码与存储的哈希值是否匹配。 

9.2 示例代码

完整的密码哈希和验证示例:

import bcrypt

# 生成哈希
def hash_password(password):
    salt = bcrypt.gensalt()
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)
    return hashed_password

# 验证密码
def check_password(provided_password, stored_hash):
    return bcrypt.checkpw(provided_password.encode('utf-8'), stored_hash)

# 使用示例
if __name__ == "__main__":
    # 用户注册时生成哈希
    password = "mypassword"
    hashed = hash_password(password)
    print(f"Hashed password: {hashed}")

    # 用户登录时验证密码
    result = check_password("mypassword", hashed)
    print(f"Password is correct: {result}")  # 输出: True

9.3 调整成本因子

bcrypt 的成本因子(cost factor)控制了哈希计算的复杂度,默认为 12。你可以调整这个值来增加或减少计算时间:

salt = bcrypt.gensalt(rounds=14)  # 增加成本因子到 14,增加计算时间

9.4 安全性注意事项

  • 避免硬编码成本因子:成本因子越高,哈希计算越慢,但同时也更安全。可以根据服务器性能适当调整。
  • 不可逆:一旦密码被哈希化,就无法从哈希值中还原原始密码。

bcrypt 被广泛认为是安全的密码哈希算法,适合用于存储用户密码等需要高安全性的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值