【Solidity】安全与校验
信息传输
发送方 A:
-
计算消息 message 的哈希值 H:
hash(message) = H
-
私钥 privateKey ➕ 哈希值 H 🟰 签名 signature:
signature = sign(H, privateKey)
-
将消息 message 和签名 signature 发送给 B
接收方 B:
-
计算消息 message 的哈希值 H1:
hash(message) = H1
-
公钥 publicKey ➕ 签名 signature 🟰 H2:
H2 = verify(signature, publicKey)
-
比较 H1 和 H2,如果相等 则说明消息未被篡改且确实来自 A
Keccak256 哈希函数
contract HashFunc {function hash(string memory _testString,uint _testUint) public pure returns (bytes32) {// 先对数据进行编码, 再用 keccak256 加密return keccak256(abi.encodePacked(_testString, _testUint));}
}
encodePacked 方法可以对多个参数进行编码,并压缩编码后的结果,节省 gas 费用。但某些情况下会导致哈希碰撞(哈希冲突)。
为了避免哈希碰撞,可以使用 encode 方法,它不会压缩编码结果,但会消耗更多 gas。
contract HashFunc {function hash(string memory _testString,uint _testUint) public pure returns (bytes32) {// 使用 encode 方法避免哈希碰撞return keccak256(abi.encode(_testString, _testUint));}
}
除了使用 encode 方法,我们还可以在 encodePacked 的入参之间再插入一个参数,这样也能避免哈希碰撞。
contract HashFunc {function hash(string memory _string1,uint _uint, // 用来避免哈希碰撞的参数string memory _string2) public pure returns (bytes32) {// 在 encodePacked 的入参之间再插入一个参数,避免哈希碰撞return keccak256(abi.encodePacked(_string1, _uint, _string2));}
}
签名与验证
contract VerifySig {// 将一个 65 字节长的签名拆分成 r、s 和 v 三个部分function split(bytes memory _signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {require(_signature.length == 65, "invalid signature length");assembly {// 从 _signature 的第 32 字节开始加载 32 字节的数据, 并将其赋值给 r// 这是因为前 32 字节是 _signature 的长度信息r := mload(add(_signature, 32))// 从 _signature 的第 64 字节开始加载 32 字节的数据, 并将其赋值给 ss := mload(add(_signature, 64))// 从 _signature 的第 96 字节开始加载 32 字节的数据, 并取其第一个字节给 vv := byte(0, mload(add(_signature, 96)))}}// 计算给定消息的哈希值function getMessageHash(string memory _message) public pure returns (bytes32) {return keccak256(abi.encodePacked(_message));}// 生成一个符合以太坊签名标准的消息哈希值function getEthSignedMessageHash(bytes32 _messageHash) public pure returns (bytes32) {returnkeccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",// 这是一个固定的前缀, 用于防止签名重用攻击// 这个前缀告诉以太坊客户端这是一个签名消息, 而不是交易或其他数据// \x19 表示消息的长度; 32 表示消息哈希的长度为 32 字节_messageHash));}// 从签名中恢复出签名者的地址function recover(bytes32 _ethSignedMessageHash,bytes memory _signature) public pure returns (address) {(bytes32 r, bytes32 s, uint8 v) = split(_signature);return ecrecover(_ethSignedMessageHash, v, r, s);}// 验证消息的有效性 (签名者是否正确、消息是否被篡改)function verify(address _signer,string memory _message,bytes memory _signature) public pure returns (bool) {bytes32 messageHash = getMessageHash(_message);bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);return recover(ethSignedMessageHash, _signature) == _signer;}
}
部署合约并测试:
模拟发送方 A:
-
将要发送的消息作为参数传入 getMessageHash 方法,得到消息的哈希值 H,这里以字符串 “hello” 为例
-
F12 打开控制台,执行
ethereum.enable()
;查看 Promise,若为 fulfilled 状态则说明 MetaMask 已连接,可查看 Promise 结果得到 MetaMask 的账号地址(需要先安装 MetaMask 插件并登录) -
执行
ethereum.request({ method: "personal_sign", params: [步骤 2 得到的 MetaMask 账号地址, 步骤 1 得到的哈希值 H] })
,会弹出签名框,点击 sign 进行签名;查看 Promise,若为 fulfilled 状态则说明签名成功,可查看 Promise 结果得到签名 signature -
假设 A 将步骤 3 得到的签名 signature 和消息 “hello” 发送给了 B
模拟接收方 B:
-
将收到的消息 “hello” 作为参数传入 getMessageHash 方法,得到消息的哈希值
-
将步骤 1 得到的哈希值作为参数传入 getEthSignedMessageHash 方法,得到符合以太坊签名标准的消息哈希值 H1
-
将步骤 2 得到的消息哈希值和收到的签名 signature 作为参数传入 recover 方法,得到签名者的地址;比对是否为 A 步骤 2 得到的 MetaMask 账号地址,如果不一致 则说明信息被篡改 / 消息不是来自 A
访问控制
contract AccessControl {// 定义两个角色bytes32 public constant ROLE_ADMIN =keccak256(abi.encodePacked("ROLE_ADMIN"));bytes32 public constant ROLE_USER =keccak256(abi.encodePacked("ROLE_USER"));// 定义一个双重映射, 用于管理 "角色 - 用户 - 权限"mapping(bytes32 => mapping(address => bool)) public roles;// 分配权限function _grantRole(bytes32 _role, address _account) internal {roles[_role][_account] = true;}// 撤销权限function _revokeRole(bytes32 _role, address _account) internal {roles[_role][_account] = false;}// 构造函数constructor() {_grantRole(ROLE_ADMIN, msg.sender);}// 函数装饰器, 限制只有管理员才能调用modifier onlyAdmin() {require(roles[ROLE_ADMIN][msg.sender],"AccessControl: sender must be an admin to perform this action");_;}// 分配权限 (外部使用, 只有管理员才能调用)function grantUserRole(address _account) public onlyAdmin {_grantRole(ROLE_USER, _account);}// 撤销权限 (外部使用, 只有管理员才能调用)function revokeUserRole(address _account) public onlyAdmin {_revokeRole(ROLE_USER, _account);}
}
-
部署合约,部署者将成为管理员
-
获取编辑器地址和 ROLE_ADMIN 的哈希值,填入 roles 中查看权限,此处应为 true
-
更新编辑器地址,获取新的编辑器地址和 ROLE_USER 的哈希值,填入 roles 中查看权限,此处应为 false
-
使用管理员地址调用 grantUserRole 方法,并传入新的编辑器地址作为参数,授权新的编辑器地址为 ROLE_USER
-
获取新的编辑器地址和 ROLE_USER 的哈希值,填入 roles 中查看权限,此处应为 true
-
使用管理员地址调用 revokeUserRole 方法,并传入新的编辑器地址作为参数,取消新的编辑器地址的 ROLE_USER 权限
-
获取新的编辑器地址和 ROLE_USER 的哈希值,填入 roles 中查看权限,此处应为 false
-
不使用管理员地址调用 grantUserRole 方法,会报错
相关文章:
【Solidity】安全与校验
信息传输 发送方 A: 计算消息 message 的哈希值 H:hash(message) H 私钥 privateKey ➕ 哈希值 H 🟰 签名 signature:signature sign(H, privateKey) 将消息 message 和签名 signature 发送给 B 接收方 B: 计算…...

黑神话悟空四十二项修改器 v1.0
软件简介 黑神话悟空四十二项修改器由风灵月影精心打磨,为《黑神话悟空》这款备受瞩目的游戏量身定制。这款修改器界面简洁、体积小巧、功能强大,它致力于为玩家提供便捷的游戏体验,让您能够根据个人喜好和需求,轻松调整游戏内的…...

RM电控RTOS
OS即(operating system)操作系统,比如我们常用的windows系统,mac系统,android系统,ios系统,linux系统等,都属于操作系统。操作系统的本质是一个特殊的软件,它直接管理硬件…...

Arduino开源四足蜘蛛机器人制作教程
视频教程:手把手叫你做四足蜘蛛机器人——1零件介绍_哔哩哔哩_bilibili 一、项目介绍 1.1 项目介绍 Arduino主控,图形化编程,趣味学习 Arduino nano开发板舵机扩展底板 4.8V可充电电池,支持Arduino C语言编程和米思齐图形化编程…...

【Axure高保真原型】中继器表格——标签使用情况案例
今天和大家分享中继器表格——标签使用情况案例的原型模板,效果包括: 模糊搜索——输入标签编号或者标签名称,可以快速查找对应的数据 排序——点击排序按钮,可以按升序或降序排列 分页——点击上拉列表,可以选择表格…...
ABAP字符串反转 and 寻找字符所在位置 and 根据数量汇总时把数量转为非数值类型
1.字符串反转 and 寻找字符所在位置 LOOP AT gt_wlmc ASSIGNING FIELD-SYMBOL(<fs_wlmc>). "遍历内表<fs_wlmc>-matnr <fs_wlmc>-matnr(8).DATA: l_output TYPE char50,v_off2 TYPE i,str TYPE i,str2 TYPE i.CALL FUNCTION STRING_REVERS…...
【机器学习第十二章——计算学习理论】
机器学习第十二章——计算学习理论 12.计算学习理论12.1 基础知识12.1 可能学习近似正确假设(PAC)12.3 有限假设空间12.4 VC维 12.计算学习理论 12.1 基础知识 从理论上刻画了若干类型的机器学习问题中的困难和若干类型的机器学习算法的能力 这个理论要…...
Docker私人学习笔记
俗话说“好记性不如烂笔头”,编程的海洋如此的浩大,养成做笔记的习惯是成功的一步! 此笔记主要是antlr4.13版本的笔记,并且笔记都是博主自己一字一字编写和记录,有错误的地方欢迎大家指正。 一、基础概念:…...
谷粒商城实战笔记-233~235-商城业务-认证服务-单点登录流程-原理
文章目录 一,场景二,单点登录流程 一,场景 包含以下三节的内容: 一,233-商城业务-认证服务-单点登录流程-1二,233-商城业务-认证服务-单点登录流程-2三,233-商城业务-认证服务-单点登录流程-3…...
机器学习在旅游业的革新之旅
机器学习在旅游业的革新之旅 随着科技的飞速发展,尤其是人工智能(AI)技术的广泛应用,各个行业都迎来了前所未有的变革。其中,旅游业作为全球经济的重要支柱之一,更是受益匪浅。机器学习(Machin…...

OpenCTI:开源网络威胁情报平台
OpenCTI 是一个开源平台,旨在帮助组织管理其网络威胁情报 (CTI) 数据和可观察数据。 该平台由 Filigran 开发,使用基于 STIX2 标准的知识模式构建数据。 它采用现代 Web 应用程序架构,配备 GraphQL API 和用户友好的前端。 OpenCTI 与 MIS…...
linux shell 脚本 let 数学计算
linux shell 脚本 let 数学计算 http://www.codebaoku.com/it-shell/ let命令中的算术表达式必须用双引号括起来,以避免解释器对特殊字符进行处理。 在变量的计算中,不需要使用$符号来表示变量, #!/bin/shweek_daydate %u echo $week_day…...

mp3和mp4的区别是什么?怎么把mp3转成mp4?(全)
在生活中我们或多或少会听到“mp3”和“mp4”,那么什么是mp3和mp4呢?mp3和mp4的区别是什么?mp3是一种音频压缩技术,旨在在不显著牺牲音质的前提下减小音频文件的体积,使其适用于音乐和其他音频内容的存储与传输。相比之…...
合并params和query参数
场景:三级分类只有query参数,搜索框使用params参数。为了解决这个问题,文中在typeNav的index.vue和Head/index.vue分别进行了判断和处理,确保在不同的路径下合并params和query参数能正确合并并传递。 如何当点击联动框时跳转到se…...

[数据集][目标检测]工程机械车辆检测数据集VOC+YOLO格式3189张10类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):3189 标注数量(xml文件个数):3189 标注数量(txt文件个数):3189 标注…...
构建域名服务器-BIND:Linux端的安装过程及配置文件详解
文章目录 构建域名服务器工具-BINDBIND的安装BIND配置文件详解1. /etc/named.conf:2. /etc/named.rfc1912.zones:3. /var/named/named.localhost:4./etc/logrotate.d/named5./etc/named.iscdlv.key6./etc/named.root.key7./etc/rndc.conf8./e…...
linux查询目录文件基础操作
基础命令 展示所有目录 ls 长格式列出(显示文件权限、所有者、大小和最后修改时间): ls -l 忽略大小写查询 ls | grep -i name 查找特定名称的文件: find /path/to/search -name "filename" 忽略大小写查找文件&#…...

搭建TestBench,收藏这几条基本框架就够了
Verilog功能模块HDL设计完成后,并不代表设计工作的结束,还需要对设计进行进一步的仿真验证。掌握验证的方法,即如何调试自己的程序非常重要。在RTL逻辑设计中,要学会根据硬件逻辑来写测试程序即写Testbench。Verilog测试平台是一个…...
怎么利用住宅代理提高数据抓取效率
在大数据时代,数据抓取已经是从互联网收集数据的关键手段,得到了广泛的应用。不论是网络营销、电商平台、或者是新闻网站,数据抓取都可以帮助企业或者是个人收集到大量的数据。但是随着反爬虫技术的不断发展,传统的爬虫方法已经不…...
c#中的ManuaResetEvent
在C#中,ManualResetEvent 是一个同步事件,用于线程间通信。它允许一个或多个等待的线程等待某个事件的发生。当事件被设置为已发生(或称为“信号”)状态时,所有等待的线程都会被释放,并且可以继续执行。 以…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...

iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...