Python Show-Me-the-Code 第 0021题 密码加密

第 0021 题: 通常,登陆某个网站或者 APP,需要使用用户名和密码。密码是如何加密后存储起来的呢?请使用 Python 对密码加密。


思路:

加密技术是对信息进行编码和解码的技术,编码是把原来可读信息(又称明文)译成代码形式(又称密文),其逆过程就是解码(解密)。加密技术的要点是加密算法,加密算法可以分为对称加密、不对称加密和不可逆加密三类算法。

按照安全性由低到高,有这样几种选择:

密码明文直接存储在系统中

这种方法下密码的安全性比系统本身还低,管理员能查看所有用户的密码明文。除非是做恶意网站故意套取用户密码,否则不要用这种方式

密码明文经过转换后再存储

与直接存储明文的方式没有本质区别,任何知道或破解出转换方法的人都可以逆转换得到密码明文

密码经过对称加密后再存储

密码明文的安全性等同于加密密钥本身的安全性。对称加密的密钥可同时用于加密与解密。一般它会直接出现在加密代码中,破解的可能性相当大。而且系统管理员很可能知道密钥,进而算出密码原文

密码经过非对称加密后再存储

密码的安全性等同于私钥的安全性。密码明文经过公钥加密。要还原密码明文,必须要相应的私钥才行。因此只要保证私钥的安全,密码明文就安全。私钥可以由某个受信任的人或机构来掌管,身份验证只需要用公钥就可以了

实际上,这也是 HTTPS/SSL 的理论基础。这里的关键是 私钥的安全 ,如果私钥泄露,那密码明文就危险了。

以上 4 种方法的共同特点是可以从存储的密码形式还原到密码明文。

所以密码最好是以不可还原明文的方式来保存。通常利用哈希算法的单向性来保证明文以 不可还原的有损方式 进行存储。

这类方法的各个具体操作方式按安全性由低到高依次为:

使用自己独创的哈希算法对密码进行哈希,存储哈希过的值

哈希算法复杂,独创对理论要求很高。一般独创的哈希算法肯定没有公开经过时间检验的算法质量高,天才另算

使用 MD5 或 SHA-1 哈希算法

MD5 和 SHA-1 已破解。虽不能还原明文,但很容易找到能生成相同哈希值的替代明文。而且这两个算法速度较快,暴力破解相对省时,建议不要使用它们。

使用更安全的 SHA-256 等成熟算法

更加复杂的算法增加了暴力破解的难度。但如果遇到简单密码,用彩虹字典的暴力破解法,很快就能得到密码原文

加入随机 salt 的哈希算法

密码原文(或经过 hash 后的值)和随机生成的 salt 字符串混淆,然后再进行 hash,最后把 hash 值和 salt 值一起存储。验证密码的时候只要用 salt 再与密码原文做一次相同步骤的运算,比较结果与存储的 hash 值就可以了。这样一来哪怕是简单的密码,在进过 salt 混淆后产生的也是很不常见的字符串,根本不会出现在彩虹字典中。salt 越长暴力破解的难度越大

所以加入随机salt的哈希算法是一个安全性比较好的加密算法,能够废掉彩虹表,加入随机salt,每一个用户哪怕密码一样密文值也不一样。下面使用python实现这种加密方法。


代码:

0021.密码加密.py

#coding: utf-8
import random
from hashlib import sha256
from hmac import HMAC

def set_password(raw_password, salt=None):
    if salt is None:
        salt = sha256(str(random.random())).hexdigest()[-8:]
    if isinstance(raw_password, unicode):
        raw_password = raw_password.encode(‘utf-8‘)
    # password = sha256(‘%s%s‘ % (salt, raw_password)).hexdigest()
    password = HMAC(salt, raw_password, sha256).hexdigest()
    return (‘%s$%s‘ % (salt, password))

def check_password(raw_password, enc_password):
    salt = enc_password.split(‘$‘)[0]
    return enc_password == set_password(raw_password, salt)

if __name__ == ‘__main__‘:
    raw_password1 = ‘hehe‘
    raw_password2 = ‘test‘
    salt = ‘12345678‘
    enc_password1 = set_password(raw_password1)
    enc_password2 = set_password(raw_password2, salt)
    print ‘enc_password1:%s‘ % enc_password1
    print ‘enc_password2:%s‘ % enc_password2
    print check_password(raw_password1, enc_password1)
    print check_password(raw_password2, enc_password1)



时间: 2024-08-06 03:41:17

Python Show-Me-the-Code 第 0021题 密码加密的相关文章

Python + Selenium + Firefox 使用代理 auth 的用户名密码授权

米扑代理,全球领导的代理品牌,专注代理行业近十年,提供开放.私密.独享代理,并可免费试用 米扑代理官网:https://proxy.mimvp.com 本文示例,是结合米扑代理的私密.独享.开放代理,专门研发的示例, 支持 http.https的无密码.白名单ip.密码授权三种类型 本博客转自米扑博客:Python + Selenium + Firefox 使用代理 auth 的用户名密码授权 示例中,用的插件 xpi 请到米扑代理官网,或米扑官方 github 下载 本文,直接给出完整的代码,

如何在python脚本开发做code review

在软件项目开发中,我们经常提到一个词"code review".code review中文翻译过来就是代码评审或复查,简而言之就是编码完成后由其他人通过阅读代码来检查代码的质量(可编译.可运行.可读.可维护.可复用),这些性质都比较抽象,但是一般都可以通过以下的检查点来实现: 检查代码的命名方式是否符合规范,代码的可读和可维护必须要求所有参与编码的同事使用的命名有统一的规范(注意每个人有自己的代码风格,但是要符合可读性的代码规范): 检查代码的注释,注释一般包括:1.类要有类用途和使用

面试Python工程师,这几道编码题有必要背背,Python面试题No8

第1题:列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25],并使用列表推导式提取出大于10的数,最终输出[16,25]. map是python高阶用法,字面意义是映射,它的作用就是把一个数据结构映射成另外一种数据结构. map用法比较绕,最好是对基础数据结构很熟悉了再使用,比如列表,字典,序列化这些. map的基本语法如下: map(函数, 序列1, 序列2, ...) Python 2.x 返回列表. Python 3.x 返回迭代器. list = [1,2,3,

python核心编程第4章课后题答案(第二版75页)

4-1Python objects All Python objects have three attributes:type,ID,and value. All are readonly with a possible expection of the value(which can be changed only if the object is mutable). 4-5str()and repr() repr() is a built-in function while str() wa

[Python unittest] 3-Organizing test code

组织测试代码 前面已经了解到测试的原理和步骤,但只是默认类string的测试,如果是我们自己写的类改怎么测试呢? 如下 class Widget(object): def __init__(self,name,width=50,height=50): self.name = name self.width = width self.height = height def __repr__(self): return "Widget({0})".format(self.name) # 返

python 核心编程第六章课后题自己做的答案

6–6. 字符串.创建一个 string.strip()的替代函数:接受一个字符串,去掉它前面和后面的 空格(如果使用 string.*strip()函数那本练习就没有意义了) 1 'Take a string and remove all leading and trailing whitespace' 2 3 def newStrip(str): 4 'delete blanks around a string' 5 _end = len(str) 6 _start = 0 7 8 # de

python运行错误------Non-UTF-8 code

1.安装-----见:https://www.cnblogs.com/weven/p/7252917.html 本文转载于:http://blog.csdn.net/youyuyixiu/article/details/52886692 当python中的代码有中文时,有时会出现下图错误. 解决方法就是在程序的第一行加上 #coding=gbk 1 这样程序就正确啦,如下图. 原文地址:https://www.cnblogs.com/curo0119/p/8428807.html

python核心编程第2章课后题答案(第二版36页)

2-5 Loops and Numbers a) i = 0    while i <11:     print i    i += 1 b) for i in range(0,11): print i 2-6 Conditionals n =int( raw_input('enter a number:')) if n < 0: print 'negative' elif n > 0: print 'positive' else: print 'zero' 2-7 Loops and

python核心编程第5章课后题答案

5-8Geometry import math def sqcube(): s = float(raw_input('enter length of one side: ')) print 'the area is:', s ** 2., '(units squared)' print 'the volume is:', s ** 3., '(cubic units)'def cirsph(): r = float(raw_input('enter length of radius: ')) p