区块链中的:哈希算法

2023-11-04

什么是哈希算法。

哈希算法,又称散列算法,它是一个单向函数,可以把任意长度的输入数据转化为固定长度的输出:

h\=H(x)h=H(x)h\=H(x)

例如,对 morning 和 bitcoin 两个输入进行某种哈希运算,得到的结果是固定长度的数字:

H("morning") = c7c3169c21f1d92e9577871831d067c8
H("bitcoin") = cd5b1e4947e304476c788cd474fb579a

我们通常用十六进制表示哈希输出。

因为哈希算法是一个单向函数,要设计一个安全的哈希算法,就必须满足:通过输入可以很容易地计算输出,但是,反过来,通过输出无法反推输入,只能暴力穷举。

H("???????") = c7c3169c21f1d92e9577871831d067c8
H("???????") = cd5b1e4947e304476c788cd474fb579a

想要根据上述结果反推输入,只能由计算机暴力穷举。

哈希碰撞

一个安全的哈希算法还需要满足另一个条件:碰撞率低。

碰撞是指,如果两个输入数据不同,却恰好计算出了相同的哈希值,那么我们说发生了碰撞:

H("data-123456") = a76b1fb579a02a476c789d9115d4b201
H("data-ABCDEF") = a76b1fb579a02a476c789d9115d4b201

因为输入数据长度是不固定的,所以输入数据是一个无限大的集合,而输出数据长度是固定的,所以,输出数据是一个有限的集合。把一个无限的集合中的每个元素映射到一个有限的集合,就必然存在某些不同的输入得到了相同的输出。

哈希碰撞的本质是把无限的集合映射到有限的集合时必然会产生碰撞。我们需要计算的是碰撞的概率。很显然,碰撞的概率和输出的集合大小相关。输出位数越多,输出集合就越大,碰撞率就越低。

安全哈希算法还需要满足一个条件,就是输出无规律。输入数据任意一个bit(某个字节的某一个二进制位)的改动,会导致输出完全不同,从而让攻击者无法逐步猜测输入,只能依赖暴力穷举来破解:

H("hello-1") = 970db54ab8a93b7173cb48f55e67fd2c
H("hello-2") = 8284353b768977f05ac600baad8d3d17

哈希算法有什么作用?

假设我们相信一个安全的哈希算法那么我们认为,如果两个输入的哈希相同,我们认为两个输入是相同的。

如果输入的内容就是文件内容,而两个文件的哈希相同,说明文件没有被修改过。当我们从网站上下载一个非常大的文件时,我们如何确定下载到本地的文件和官方网站发布的原始文件是完全相同,没有经过修改的呢?哈希算法就体现出了作用:我们只需要计算下载到本地的文件哈希,再和官方网站给出的哈希对比,如果一致,说明下载文件是正确的,没有经过篡改,如果不一致,则说明下载的文件肯定被篡改过。

大多数软件的官方下载页面会同时给出该文件的哈希值,以便让用户下载后验证文件是否被篡改:

和文件类似,如果两份数据的哈希相同,则可以100%肯定,两份数据是相同的。比特币使用哈希算法来保证所有交易不可修改,就是计算并记录交易的哈希,如果交易被篡改,那么哈希验证将无法通过,说明这个区块是无效的。

常用哈希算法

常用的哈希算法以及它们的输出长度如下:

哈希算法 输出长度(bit) 输出长度(字节)
MD5 128 bit 16 bytes
RipeMD160 160 bits 20 bytes
SHA-1 160 bits 20 bytes
SHA-256 256 bits 32 bytes
SHA-512 512 bits 64 bytes

比特币使用的哈希算法有两种:SHA-256  和   RipeMD160

SHA-256的理论碰撞概率是:尝试2的130次方的随机输入,有99.8%的概率碰撞。注意2130是一个非常大的数字,大约是1361万亿亿亿亿。以现有的计算机的计算能力,是不可能在短期内破解的。

比特币使用两种哈希算法,一种是对数据进行两次SHA-256计算,这种算法在比特币协议中通常被称为hash256或者dhash。

另一种算法是先计算SHA-256,再计算RipeMD160,这种算法在比特币协议中通常被称为hash160。

const
    bitcoin = require('bitcoinjs-lib'),
    createHash = require('create-hash');

Run

运行上述代码,观察对一个字符串进行SHA-256、RipeMD160、hash256和hash160的结果。

区块链不可篡改特性

  • 有了哈希算法的预备知识,我们来看比特币的区块链如何使用哈希算法来防止交易记录被篡改。
  • 区块本身记录的主要数据就是一系列交易,所以,区块链首先要保证任何交易数据都不可修改。

Merkle Hash

在区块的头部,有一个Merkle Hash字段,它记录了本区块所有交易的Merkle Hash:

Merkle Hash是把一系列数据的哈希根据一个简单算法变成一个汇总的哈希。

假设一个区块有4个交易,我们对每个交易数据做dhash,得到4个哈希值a1a2a3a4

a1 = dhash(tx1)
a2 = dhash(tx2)
a3 = dhash(tx3)
a4 = dhash(tx4)

注意到哈希值也可以看做数据,所以可以把a1a2拼起来,a3a4拼起来,再计算出两个哈希值b1b2

       ┌───────────────┐               ┌───────────────┐
       │b1=dhash(a1+a2)│               │b2=dhash(a3+a4)│
       └───────────────┘               └───────────────┘
               ▲                               ▲
       ┌───────┴───────┐               ┌───────┴───────┐
       │               │               │               │
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│a1=dhash(tx1)│ │a2=dhash(tx2)│ │a3=dhash(tx3)│ │a4=dhash(tx4)│
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘

最后,把b1b2这两个哈希值拼起来,计算出最终的哈希值,这个哈希就是Merkle Hash:

                     ┌───────────────────┐
                     │merkle=dhash(b1+b2)│
                     └───────────────────┘
                               ▲
               ┌───────────────┴───────────────┐
               │                               │
       ┌───────────────┐               ┌───────────────┐
       │b1=dhash(a1+a2)│               │b2=dhash(a3+a4)│
       └───────────────┘               └───────────────┘
               ▲                               ▲
       ┌───────┴───────┐               ┌───────┴───────┐
       │               │               │               │
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│a1=dhash(tx1)│ │a2=dhash(tx2)│ │a3=dhash(tx3)│ │a4=dhash(tx4)│
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘

如果交易的数量不恰好是4个怎么办?

        例如,只有3个交易时,第一个和第二个交易的哈希a1a2可以拼起来算出b1,第三个交易只能算出一个哈希a3这个时候,就把a3直接复制一份,算出b2这样,我们也能最终计算出Merkle Hash:

                     ┌───────────────────┐
                     │merkle=dhash(b1+b2)│
                     └───────────────────┘
                               ▲
               ┌───────────────┴───────────────┐
               │                               │
       ┌───────────────┐               ┌───────────────┐
       │b1=dhash(a1+a2)│               │b2=dhash(a3+a3)│
       └───────────────┘               └───────────────┘
               ▲                               ▲
       ┌───────┴───────┐               ┌───────┴───────┐
       │               │               │               │
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌ ─ ─ ─ ─ ─ ─ ┐
│a1=dhash(tx1)│ │a2=dhash(tx2)│ │a3=dhash(tx3)│
└─────────────┘ └─────────────┘ └─────────────┘ └ ─ ─ ─ ─ ─ ─ ┘

        如果有5个交易,我们可以看到,a5被复制了一份,以便计算出b3,随后b3也被复制了一份,以便计算出c2总之,在每一层计算中,如果有单数,就把最后一份数据复制,最后一定能计算出Merkle Hash:

                  ┌─────────┐
                  │ merkle  │
                  └─────────┘
                       ▲
           ┌───────────┴───────────┐
           │                       │
         ┌───┐                   ┌───┐
         │c1 │                   │c2 │
         └───┘                   └───┘
           ▲                       ▲
     ┌─────┴─────┐           ┌─────┴─────┐
     │           │           │           │
   ┌───┐       ┌───┐       ┌───┐       ┌ ─ ┐
   │b1 │       │b2 │       │b3 │        b3
   └───┘       └───┘       └───┘       └ ─ ┘
     ▲           ▲           ▲
  ┌──┴──┐     ┌──┴──┐     ┌──┴──┐
  │     │     │     │     │     │
┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌ ─ ┐
│a1 │ │a2 │ │a3 │ │a4 │ │a5 │  a5
└───┘ └───┘ └───┘ └───┘ └───┘ └ ─ ┘

从Merkle Hash的计算方法可以得出结论:修改任意一个交易哪怕一个字节,或者交换两个交易的顺序,都会导致Merkle Hash验证失败,也就会导致这个区块本身是无效的,所以,Merkle Hash记录在区块头部,它的作用就是保证交易记录永远无法修改。

Block Hash

区块本身用Block Hash——也就是区块哈希来标识。但是,一个区块自己的区块哈希并没有记录在区块头部,而是通过计算区块头部的哈希得到的:

区块头部的Prev Hash记录了上一个区块的Block Hash,这样,可以通过Prev Hash追踪到上一个区块。

由于下一个区块的Prev Hash又会指向当前区块,这样,每个区块的Prev Hash都指向自己的上一个区块,这些区块串起来就形成了区块链。

区块链的第一个区块(又称创世区块)并没有上一个区块,因此,它的Prev Hash被设置为00000000...000

如果一个恶意的攻击者修改了一个区块中的某个交易,那么Merkle Hash验证就不会通过。所以,他只能重新计算Merkle Hash,然后把区块头的Merkle Hash也修改了。这时,我们就会发现,这个区块本身的Block Hash就变了,所以,下一个区块指向它的链接就断掉了。

由于比特币区块的哈希必须满足一个难度值,因此,攻击者必须先重新计算这个区块的Block Hash,然后,再把后续所有区块全部重新计算并且伪造出来,才能够修改整个区块链。

在后面的挖矿中,我们会看到,修改一个区块的成本就已经非常非常高了,要修改后续所有区块,这个攻击者必须掌握全网51%以上的算力才行,所以,修改区块链的难度是非常非常大的,并且,由于正常的区块链在不断增长,同样一个区块,修改它的难度会随着时间的推移而不断增加。

小结

区块链依靠安全的哈希算法保证所有区块数据不可更改;

交易数据依靠Merkle Hash确保无法修改,整个区块依靠Block Hash确保区块无法修改;

工作量证明机制(挖矿)保证修改区块链的难度非常巨大从而无法实现。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

区块链中的:哈希算法 的相关文章

随机推荐

  • python——类型转换和冗余数据删除

    1 类型转换 import pandas as pd import datetime 一般我们拿到日期型数据时 基本都是字符串表示的 该如何将其转换为日期型和日期时间型 法1 dt 2019 06 13 16 16 39 d 2017 04
  • Spring:IoC和DI完成打印机打印详细说明过程及代码

    Spring IoC和DI完成打印机 课后作业 使用Spring的IoC DI 装配一台打印机 纸张接口 实现 有 A4 A5 墨盒接口 实现 有 黑白 彩色 注解方式和非注解方式都要 说明 1 首先是注解方式 下面那些代码就是用注解方式做
  • 十九. Kubernetes NetworkPolicy 网络隔离策略

    目录 一 NetworkPolicy 基础解释 一 NetworkPolicy 基础解释 官方文档 NetworkPolicy 网络策略 网络隔离策略 k8s中资源是通过命名空间隔离的 但是为了保证k8s的网络互通性 是没有做隔离的 防止调
  • 高德地图API用户定位失败Geolocation permission denied

    问题描述 手机页面通过高德 js 进行用户定位失败 Geolocation permission denied mapObj new AMap Map iCenter mapObj plugin AMap Geolocation funct
  • 【Linux网络(C++)】——网络套接字(TCP/UDP编程模型)多进程,多线程,线程池服务器开发(画图解析)

    目录 一 套接字基本概念 IP地址 TCP和UDP协议 端口号 端口号vs 进程pid 网络字节序 本地字节序转换成网络字节序 网络字节序转换为本地字节序 二 套接字的基本操作 socket的创建 域 domain 类型 type 协议 P
  • 【线程(二)】——互斥量的详细解析

    作者 努力学习的少年 个人简介 双非大二 一个正在自学c 和linux操作系统 写博客是总结知识 方便复习 目标 进大厂 如果你觉得文章可以的话 麻烦你给我点个赞和关注 感谢你的关注 目录 进程线程间的互斥的相关概念 错误的抢票系统 lin
  • 物理渗透-Mifare Classic S50(IC)卡分析

    前言 我们不管是在小区里还是公司里 都可能会使用过门禁卡 比如乘坐电梯需要刷工牌才使用 而且只能去特定的楼层 生活中还有很多地方用到过IC卡 商铺的会员卡 交通的公交卡等等 关于IC ID卡的基础 本节不做详细叙述 只介绍M1的IC卡如何去
  • 【C++ Primer】重载运算与类型转换

    文章目录 一 基本概念 二 输入输出运算符 1 重载输出运算符 lt lt 2 重载输入运算符 gt gt 三 算数和关系运算符 1 相等运算符 2 关系运算符 四 赋值运算符 五 下标运算符 六 递增递减运算符 七 成员访问运算符 八 函
  • windows下网络编程UDP

    转载 C UDP客户端服务器Socket编程 UDPServer cpp include
  • IC项目中svn使用经验总结

    一 svn权限 二 svn分支 三 项目中遇到的问题总结 svn内容太大怎么解 svn的trunk经常不稳定怎么解 svn merge 冲突的处理方式 四 疑问 svn使用者未及时提交代码至trunk分支怎么办 提交代码至trunk后在tr
  • 每日一题:从前序与中序遍历序列(C++)

    题目描述 根据一棵树的前序遍历与中序遍历构造二叉树 注意 你可以假设树中没有重复的元素 例如 给出 前序遍历 preorder 3 9 20 15 7 中序遍历 inorder 9 3 15 20 7 返回如下的二叉树 3 9 20 15
  • html、vue、uni-app微信小程序的区别

    传统的h5只有1端 即浏览器 而uni app可跨多端 虽仍属前端 与传统h5有不同 网络模型的变化 以前网页大多是b s 服务端代码混合在页面里 现在是c s 前后端分离 通过js api 类似ajax的uni request 获取jso
  • opencv读取rtsp的一些优化

    用队列将同步转为异步 import cv2 import queue import time import threading q queue Queue def Receive print start Reveive cap cv2 Vi
  • 迅雷链同构多链框架解析

    本文转载自迅雷官方微信群 传统意义上的 甚至是消费者端熟知的迅雷 是那家唯一在美国上市的中国下载服务商 主营业务还是在线广告 游戏和会员 迅雷从2015年开始对分布式计算和区块链领域的布局 这几年 迅雷布局了CDN 推出了C端的赚钱宝和玩客
  • Notepad++ 支持markdown语法

    之前windows下想编写markdown只是通过有道云笔记来写 看的时候简单的就直接用notepad 看 有些语法得导入到有道云笔记中看很不方便 搜索windows下的markdown编辑工具 Typora sublime markdow
  • myBase7安全破解的方法

    转自https blog csdn net weixin 42414714 article details 89642305 首先 保证myBase7是关闭状态 然后执行以下步骤 1 找到myBase7的安装目录 右击mybase的启动图标
  • 用Python预测收入,来看看你的收入到底应该是多少?

    Python界的网红机器学习 这股浪潮已经逐渐成为热点 而Python是机器学习方向的头牌语言 用机器学习来玩一些好玩的项目一定很有意思 比如根据你的职业 婚姻 家庭 教育时间等等来预测你的收入 这么神奇 不信的话 一起跟我往下看 1 数据
  • 如何使用chatGPT进行论文润色(中英文均可)

    1 为什么ChatGPT可以进行论文润色 ChatGPT本质是一个基于GPT3 5 应用在对话场景的超大语言模型 在各种数据集上经过训练而来的 很好的掌握了语言的 本质 特征 自然可以进行语言相关的工作 论文润色只是小事情 2 如何使用ch
  • 搭建简单的神经网络——使用pytorch实现鸢尾花的分类

    最近写毕业论文 看到网上的pytorch入门nn方法乱七八糟 遂写了本篇方法 好让更多的人可以使用pytorch实现简单的神经网络方法 version python 3 7 9 pytorch 1 7 0 function 利用神经网络进行
  • 区块链中的:哈希算法

    什么是哈希算法 哈希算法 又称散列算法 它是一个单向函数 可以把任意长度的输入数据转化为固定长度的输出 h H x h H x h H x 例如 对 morning 和 bitcoin 两个输入进行某种哈希运算 得到的结果是固定长度的数字