Hash 是密码学安全性的基石,它引入了单向函数(one-way function)和指纹(fingerprint)的概念。即:

对于任意输入,都可以产生相同的、唯一的输出值

输出值中不包含输入值的任何线索

一、保密性(confidentiality)与完整性(integrity)

简单来说,信息的保密性确保除授权人员以外的任何人都无法读取该消息,信息的完整性则确保除授权人员以外的任何人都无法修改该消息。

很多时候一段加密的消息无法被他人读取和理解(保密性),并不意味着该密文不会在传播过程中被截取和恶意修改(完整性)。

信息摘要(message digest)或指纹(fingerprint)技术即用于验证信息的完整性。

信息摘要需满足的基本条件为:

相同的文档永远会生成相同的摘要(能够作为身份线索)

生成的摘要“感觉”是随机的,即摘要中不包含原始文档的任何信息(无法被破解)

信息摘要也被称作指纹,即可以代表某份文档“身份”的一小段数据,类似于人类的指纹。

每个人都可以通过指纹验证其身份,但该指纹并不包含其身体的所有信息。文档的指纹也是如此,可以很方便快速的通过文档内容计算得出一小段唯一的指纹数据作为其身份证明,但是只有指纹数据就几乎不可能得出原始文档的内容。

对于两份文档,只需要比对其信息摘要(指纹)是否一致,就可以确保其内容是否相同,在传播过程中是否被人恶意修改。同时该指纹信息也不会造成原始文档本内容的泄露。

二、MD5

MD5 是一种比较古老的哈希算法,其名字中的 MD 即代表 message digest。它可以从任意大小的文档计算出一个唯一的 16 字节长度的摘要数据。

PS:鉴于 MD5 较悠久的历史和不够长的摘要长度,不推荐在安全性很敏感的场景中使用该算法。

>>> from hashlib import md5

>>> md5(b'alice').hexdigest()

'6384e2b2184bcbf58eccf10ca7a6563c'

>>> md5(b'bob').hexdigest()

'9f9d51bc70ef21ca5c14f307980a29d8'

>>> md5(b'balice').hexdigest()

'6760742ebf884c998752b4e082b78224'

>>> md5(b'cob').hexdigest()

'386685f06beecb9f35db2e22da429ec9'

>>> md5(b'a').hexdigest()

'0cc175b9c0f1b6a831c399e269772661'

>>> md5(b'aa').hexdigest()

'4124bc0a9335c27f086f24ba207a4912'

>>> md5(b'aa' * 100000).hexdigest()

'561b1994f6baacd6e5eaf4baaa12849f'

>>> md5(b'alice').hexdigest()

'6384e2b2184bcbf58eccf10ca7a6563c'

从输出中可以看出,针对不同的输入内容(即便相似度很高,比如 bob 和 cob),摘要算法生成的输出是发散的,彼此之间没有相似性,像是随机生成的结果。

但是对于任意相同的输入,生成的摘要数据则都是确定的、唯一的。

三、哈希算法的规则

一般我们提到哈希算法,都会关联到密码学、安全性等场景中,实际上我们很早就接触了一种完全“非密码学”的哈希场景。比如小时候跟老师学习判断一个数是奇数还是偶数。。。

从本质上看,哈希函数的目的是将巨大(甚至无穷大)数量的事物映射到一个相对较小的数据集中。比如 MD5,不管输入的文档有多大,最终都会生成一个固定长度(16 字节)的十六进制数字作为指纹。

这就意味着 MD5 的输入集合,实际上是大于其输出集合的。即只要输入文档的集合足够大(很大很大),就有可能出现重复的指纹信息。

这和判断数字奇偶是相通的。不管某个数字有多大多奇特,我们永远可以将它“压缩”成奇数或偶数,用 1 bit 的 1 或 0 表示就可以。但是只说明某个未知数字是奇数(或偶数),我们就无法猜出该数字的准确值。

上面的逻辑验证了哈希函数共有的 3 个特性:

consistency(一致性):相同的输入只会生成相同的输出信息

compression(压缩):可以将体量很大的输入压缩成一个固定大小的输出

lossiness(有损的):只通过检查输出无法反向计算出输入值

但是对于一个满足密码学安全的哈希函数而言,除以上三点以外还需要具有如下属性:

Preimage resistance

Second-preimage resistance

Collision resistance

Preimage Resistance

哈希函数的 preimage 是指能够生成同一个特定指纹的所有输入的合集。即对于某个哈希函数 H 与摘要 k,所有能够生成 k 的输入值 x (满足 H(x) = k)共同组成了 H 与 k 的 preimage。

preimage resistance 的意义即为,在仅仅只是知晓某个摘要的前提下,通过有限的计算无法获取其 preimage 中的任何一个元素。即只通过结果无法知晓输入。

摘要中不包含原始文档的任何信息(lossiness),无法通过逆向运算的方式由摘要反推出原始输入。只能随机地尝试任意输入,以期碰巧得到同样的摘要信息(暴力破解)。

因此前面提到的奇偶函数就不能作为一个安全的哈希函数使用。假设使用奇偶作为哈希函数(奇数输出 1,偶数输出 0),则对于摘要 1,总可以很轻易的在 preimage(此处是全体奇数)中找到任意多个摘要同为 1 的元素。这意味着原始输入可以轻易被修改而不影响指纹数据,则该指纹作为信息完整性的验证条件就失去了意义。

但是对于较安全的哈希算法如 MD5,由 MD5(x) = ca8a0fb205782051bd49f02eae17c9ee就无法在有限的计算内找到确定的 x 的值。

MD5 生成 16 字节(16 * 8 = 128bit)长度的摘要,其中可以包含 2^128 种不同的数字组合。因此使用暴力破解的话,最多需要尝试 2^128 = 340282366920938463463374607431768211456次!

假设每秒钟可以尝试一百万条输入,仍需要 10^26 年完成所有验证操作!

Second-Preimage Resistance 与 Collision Resistance

second-primage resistance 是指即便知晓某个原始文档以及由该文档生成的摘要数据,仍很难计算可以出生成同样摘要的另一个不同的文档。

即在已知 MD5(alice) = 384e2b2184bcbf58eccf10ca7a6563c 的情况下,仍无法找出除 alice 以外的另一个输入生成同样的摘要。为了寻求可以替换掉 alice 的另一个值,同时不影响摘要认证,达到混淆的目的,最终仍需使用暴力破解的方式。

collision resistance 是指很难找出任意两个生成相同摘要(相同而非特定)的输入值。

可以参考“生日问题”,即在一个班级中,存在两个生日为同一天的学生的概率远比存在一个生日为特定日期的学生的概率大得多。

collision resistance 的意义在于,无法故意找出两套符合同一指纹的输入以达到混淆的目的。比如 MD5 算法:

>>> from hashlib import md5

>>> md5('bob').hexdigest()

'9f9d51bc70ef21ca5c14f307980a29d8'

>>> md5('cob').hexdigest()

'386685f06beecb9f35db2e22da429ec9'

对于很相似的输入 bob 和 cob,其指纹信息的差异却非常大,没有任何可供预测的规律。这得益于一种称为 avalanche property 的特性:输入的微小变化总可以在输出中产生巨大的无法预测的差异。

由前面提到的生日问题可知,找出两个生成相同指纹的元素远比找出某个可以生成特定指纹的元素要容易的多。以 MD5 算法的暴力破解为例,后者往往需要做 2^128 次尝试,而前者只需要 2^64 次尝试。

现实中 MD5 的 collision resistance 远非想象中那么优异,甚至存在一种非暴力破解的方式 能够在一小时以内攻破 MD5 的 collision resistance。

所以尽量不要使用 MD5 这个已经不再维护超过 10 年、安全漏洞存在 20 年的古老算法。

参考资料

以上就是python密码学示例——理解哈希(Hash)算法的详细内容,更多关于python 哈希(Hash)算法的资料请关注脚本之家其它相关文章!

python 密码学计算_python 密码学示例——理解哈希(Hash)算法相关推荐

  1. python星期计算_Python简单计算给定某一年的某一天是星期几示例

    本文实例讲述了Python简单计算给定某一年的某一天是星期几.分享给大家供大家参考,具体如下: # -*- coding:utf-8 -*- #计算某特定天使星期几 #蔡勒公式:w=y+[y/4]+[ ...

  2. python公式计算_Python Numpy计算各类距离的方法

    详细: 1.闵可夫斯基距离(Minkowski Distance) 2.欧氏距离(Euclidean Distance) 3.曼哈顿距离(Manhattan Distance) 4.切比雪夫距离(Ch ...

  3. python 金额计算_Python | 根据销售金额计算折扣

    python 金额计算 Input same amount and calculate discount based on the amount and given discount rate in ...

  4. python密码编程_Python密码学编程

    Python密码学编程 1 制作纸质加密工具 1.1 密码学是什么 1.2 代码与加密法 1.3 制作纸质加密轮盘 1.4 虚拟加密轮盘 1.5 如何使用加密轮盘加密 1.6 如何使用加密轮盘解密 1 ...

  5. python卷积计算_Python使用scipy模块实现一维卷积运算示例

    本文实例讲述了python使用scipy模块实现一维卷积运算.分享给大家供大家参考,具体如下: 一 介绍 signal模块包含大量滤波函数.b样条插值算法等等.下面的代码演示了一维信号的卷积运算. 二 ...

  6. python复利计算_python复利代码

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 比如在<零基础学编程012:画出复利曲线图>提到的numpy和mat ...

  7. python 异常处理 实例_Python 异常处理(示例代码)

    一.异常概念 Python在执行代码之前,会进行语法检查,如果语法出错了,会抛出语法错误(SyntaxError). Python程序运行期间检测到的错误被称为异常. 内置异常: BaseExcept ...

  8. python线性回归实例_python 线性回归示例

    说明:此文的第一部分参考了这里 用python进行线性回归分析非常方便,有现成的库可以使用比如:numpy.linalog.lstsq例子.scipy.stats.linregress例子.panda ...

  9. python的计算_python 计算方位角实例(根据两点的坐标计算)

    知道两点坐标,怎么计算两点方向的方位角? 答:首先计算坐标增量dx,dy(两个对应坐标分量相减,终点的减始点的). 若dx,dy中有一个为零时,根据另一个的正负决定方位角(0,90,180,270这四 ...

最新文章

  1. 百度指数常见php框架,怎么导出数据到excel表格-如何将百度指数数据导出到Excel表格...
  2. 理解I/O Completion Port(完成端口)
  3. html之引入独立js方便维护jq代码
  4. struct lnode是什么结构类型_【自考】数据结构第三章,队列,期末不挂科指南,第4篇
  5. cv2.cornerHarris()详解 python+OpenCV 中的 Harris 角点检测
  6. centos7 如何重启web服务_CentOS7重启网络服务失败。
  7. 架构学习----消息队列
  8. 大数据分析中常见的分析模型
  9. 34.MySQL的高级安装和升级
  10. linux强制获得锁,Linux中的两种文件锁——协同锁与强制锁
  11. Android中实现Activity的透明背景效果
  12. Pandas loc/iloc用法详解
  13. 2020中国区块链产业政策年度报告|链塔智库
  14. 【JavaWeb】网络留言板 可登录、注册、留言、修改留言、删除留言 附源码
  15. 手机微信html整人代码大全,2018年微信整人代码有哪些?2018年微信整人代码大全!...
  16. win10右键删除多余菜单
  17. 小武匠师PPT 基础篇(一)-武文杰-专题视频课程
  18. DLink无线路由器做交换机配置
  19. 华硕笔记本快捷键失效(例如fn+f5失效)
  20. java如何生成api文档_api文档自动生成工具

热门文章

  1. 分析方法的基础 — 3. 业务与管理的特性,分析与设计的抓手
  2. 信息与数据科学国际会议征文通知
  3. 【操作系统】部分概念解释题
  4. 如何在SQL Server数据库中加密数据
  5. 《Ansible权威指南 》一第2章 Ansible基础元素介绍
  6. linux设备驱动模块引用和依赖
  7. 中国软件开发project师之痛
  8. 2013/12/25
  9. 【cocos2d-x】游戏构成要素③----游戏关卡的实现
  10. 企业即时通讯设计理念及实现代码