https-ssl-403-error

问题描述

由于用到小程序,需要配置ssl服务器;因为之前配置了好多次,以为这次这个事情也就10分钟的事情,谁知道花费了几个小时。按照正常流程申了ssl证书配置了域名和nginx ,当访问https://打开网站的的时候,莫名的打不开了。。。就以为是nginx配置问题。疯狂的找资料。因为服务器面板和云服务器443端口都开了,所以我就没往这里想。

问题解决

充分尝试之后,还是不行,之后,我一个一个的排查,先关闭防火墙;结果。。。。有反应了,https 出现了 403 ,巨大的进步。但是这一步怎么也解决不了。后来发现nginx文件没有配置默认的入口文件。

经验

遇到问题多方思考。最熟悉的地方👄容易忽略。
分享一个nginx配置文件生成网址,还挺有用的,可以根据nginx版本 ,ssl版本和其他一些方面,动态生成nginx配置还挺有用。
https://ssl-config.mozilla.org/#server=nginx&version=1.20.2&config=intermediate&openssl=1.1.1k&hsts=false&ocsp=false&guideline=5.6

update-ganache-from-less-than-v6.x.x-to-v7.x.x

ganache不保存数据

每次重启,账户都被情况,数据,交易全部都没了,每次重启reset了db。不想要这个效果,从文档看传入-db参数可以解决这个问题。无奈,这个V6.x.x有bug ,需要v7.x.x才行。

升级

v7.x.x的版本变化比较大

1
The Ganache npm packages have been combined and renamed from ganache-cli and ganache-core to ganache. You may need to uninstall the old packages before installing the new ganache.

如果升级需要删除老版本

1
2
npm uninstall --global ganache-cli ganache-core
npm install --global ganache

命令行参数也改了

1
2
3
x@y-MacBook-Pro ~ % ganache
ganache v7.2.0 (@ganache/cli: 0.3.0, @ganache/core: 0.3.0)
Starting RPC server

参考:https://github.com/trufflesuite/ganache/blob/develop/UPGRADE-GUIDE.md

最好的解决方案

升级之后,还是有问题。可能是我配置有问题,ganache命令行应该就是为了内存设计。如果为了缓存数据,可以用ganache 的 UI 版本。
20220601024732
Remix 添加ganache的网络
20220601024705

ganache UI 版本有一个workspace概念,可以很好的隔离保存每次不同的数据区块

一文理清过度授权的是是非非

什么是过度授权

忘记在哪里看过一个脑静急转弯了。大致内容:如果你的区块链硬件钱包有10万元,玩dapp你最多能亏多少钱?答案显而易见:10万。当然,这个10万有很大可能不是dapp内部逻辑导致的亏损,而是因为它的钱包授权给了恶意DAPP,这个恶意dapp盗走了他的10万元。

这就是区块链世界的”黑暗森林“,大家都在猎杀金钱,活下去的的唯一途径就是别被第二者发现我们的低级错误。

过度授权的案例

案例1: 2021 年 2 月份 ,中心化金融协议 Primitive由于合约漏洞,攻击者利用过度授权机制盗走了一部分资金。 https://cryptopotato.com/defi-protocol-primitive-finance-self-hacks-to-prevent-exploit/
案例2:2021 年 2 月份, https://rekt.news/furucombo-rekt/
案例3:我身边的朋友,自己偶尔玩玩dapp,自己本身也是做技术的,还被过度授权盗走了1000多U
20220529004454
更多过度授权案例 百度搜索:过度授权 或者 infinite approval

过度授权剖析

平时区块链转账,我们也没有使用过授权这个概念。授权这个概念大概是随着defi的兴起而火起来的,defi summber随便一个年化都很高,热钱涌动,进来了很多人。而这些defi大部分都是dapp,你需要授权给这些app使用你的资金,然后去赚钱。本质上,无论日常地址之间直接转账还是说dapp授权交易都是一个区块链的交易。怎么去区分和理解呢,如下图大致画 了一下我们平时转账交易和dapp授权的区别
日常转账交易(大致画了一下)
20220529005545
dapp授权交易
20220529010907

一言以蔽之,正常交易转账是自己直接转给地方地址。dapp授权是给第三方一个使用自己资金的权限,授权的时候可以指定币种和金额。
大家使用比较多的小狐狸授权页面如下,一旦遇到类似的页面,不熟悉的一定不要授权或者读取清楚每一个字。
20220529011159

ERC20标准

这个部分有一点偏技术,简单看一下,对于后边的内容会理解的更加深刻。ERC20标准大致是一个规定了以太坊区块链上的数字资产的生成,存储,转移等一系列操作的标准。有了这个标准之后,所有遵守ERC20协议的所有token之间既可以互操作了。

正常的erc20合约标准,大致有如下接口

https://eips.ethereum.org/EIPS/eip-20

1
2
3
4
5
6
7
8
9
10
11
12
// https://github.com/ethereum/EIPs/issues/20
contract ERC20 {
function totalSupply() constant returns (uint totalSupply);
function balanceOf(address _owner) constant returns (uint balance);
function transfer(address _to, uint _value) returns (bool success);
function transferFrom(address _from, address _to, uint _value) returns (bool success);
function approve(address _spender, uint _value) returns (bool success);
function allowance(address _owner, address _spender) constant returns (uint remaining);
event Transfer(address indexed _from, address indexed _to, uint _value);
event Approval(address indexed _owner, address indexed _spender, uint _value);
}

  • totalSupply token的总供应量
  • balanceOf 查询某一个地址的token余额
  • transfer 转移token从一个地址到另外一个地址
  • transferFrom 第三方从一个地址Token转移到一个地址
  • approve 给予其他地址授予token使用权限
  • allowance 查询既定的地址授予了哪些全新
  • Transfer 事件,token 发生转移就会有这个事件日志
  • Approval 授权事件

看到了吗?erc20标准就6个函数2个事件。让人失望的是,标准中没有我们期望看到的撤销授权的函数方法!!! 具体啥原因我暂时没有想清楚

从代码角度看,我的钱是怎么被恶意dapp盗走的

这里假设有两个用户A和B。用户A有100U 而且授权给了B使用这100U 。过程如下

  1. A调用 approve(address(B), 100),授予B使用A的100Usdt的权限
  2. B使用的时候需要检查A到底给自己了多少usdt的使用额度:allowance(address(A), address(B))
  3. B知道了自己的使用额度之后调用转账transferFrom(address(A), address(B), 100) 把100U 从A转到B

过程就是这么的简单!!!!!

虽然 transferFrom 函数被用来了盗用token,但是的设计目标是允许经过授权的地址使用我的token,在如下场景还是有不少用的

  • 让他人代付gas费用
  • dapp中允许dapp支配自己的资金去赚取收益
  • 订阅web3的一些服务,自动扣款等
  • 代币归集,如果100000 个地址需要归集,你需要给10000个地址打手续费,而且每个地址都有零星的不能用的小数点后边N位的以太坊,好恐怖!如果授权就不一样了

手续费是谁来付

1
2
3
4
5
假设:A账号有10000个token代币,B账号没有token代币,C账号也没有token代币!
那么:A账号 委托 B账号 转给C账号 100个token代币 怎么来实现呢?
首先:A账号 和 B账号建立一种委托关联,登录A账户执行approve(b,100)方法结果为:结果:_allowed[A][B] = 100token
然后:在执行登录B账户执行transferFrom(A,C,100),这里的B就是委托账号发送者,gas从B扣,必须确保token数量小于_allowed[A][B]
总结:其实就是A转入C,但是要经过B的账号来发送交易!

如何防范过度授权威胁

  • 不要使用来源不明或者自己不信任的dapp
  • 定期使用撤销授权工具清理授权
  • 养成良好的习惯,经常用来玩dapp的钱包别放太多资金。

如何手动撤销过度授权

  1. 一些钱包例如,tokenpocket ,imtoken ,mathwallet 内部都内置了过度授权清理工具。
  2. 一些第三方网站,例如https://approved.zone/ ,debank,cointool 也都提供了类似的工具(提示:别因为清理授权被钓鱼了)
  3. 清理授权的过程是需要花费一定的gas 的

过度授权一定能撤销干净吗

一种猜想

既然过度授权危害这么大。我有一些解决类似问题的想法。
建立一个权威的公用合约A。这个合约由一个dao组织运行,dapp项目方需要提供合约地址给合约A,一旦加入到合约A的白名单,就代表被加入的合约在一定程度上做了背书。加入白名单的项目方要么提供实名信息要么提供一些token质押,防止作恶。

在用户使用dapp的时候,不是直接授予权限给不受信任的dapp而是直接授权给dao运营的合约A。然后由合约A代理用户向目标合约做交互。

等于说在用户和目标dapp之间做了一个隔离,这个在一定程度上能解决授权过渡问题。

其他

其实,这个话题展开的话,能说很多。包括从代码角度可以写一个demo来演示都是没问题的。只有真正的让用户看到了过度授权的危害才能真正的警醒用户授权的时候留一个心眼。而屡屡有用户因为过度授权上当受骗,大概是因为狼来了的故事挺多了,反正这事也不会发生在我身上。

哎,这个话题又涉及到哲学高度了,涉及到了人类学了。也罢,到此为止。

react-native-environment

前置条件

由于react本质上是一套前端的开发流程,所以类似node ,npm等是必不可少的

1
2
brew install node
brew install watchman

其中 watchman是用来监测文件变化的。

安装

这里区分ios和安卓开发环境。最简单的,安卓安装android studio,ios就安装xcode ~ 如果在遇到其他问题,搜一下,一下子就出来了。

创建项目

1
npx react-native init AwesomeProject

运行项目

在项目根目录运行

1
npx react-native start

这个命令把项目用到的所有依赖和代码合并成一个js文件。

安卓平台

运行

1
npx react-native run-android

安卓平台还可以打开Android studio,然后导入代码目录下面的android文件夹编译,安装。

如果报错,在命令行输入命令

1
adb reverset tcp:8081 tcp:8081 

这句的意思是把电脑的8081端口的内容转发给手机端8081端口

ios平台

打开ios目录下的workspace,运行就很简单了,这里提一下签名。

  1. 必须使用苹果官方数据线。否则无法识别设备
  2. 需要一个mobileprovision文件,这是一个描述文件。他包含的信息说明使用什么证书打包、AppID是什么、打包的App包含了哪些功能、可以在哪些设备上安装,则是通过Provisioning Profile 描述文件。

Prisma入门

Prisma 是什么

Prisma是适用于Node.js和TypeScript的下一代开源ORM。ORM:对象关系映射(Object Relational Mapping)是一种程序设计技术。简单来说ORM可以将我们的底层数据库的各种操作进行一定的封装,我们就可以通过更加熟悉的开发语言来书写对应的数据库命令,ORM则可以将这些数据库操作命令转换为对应的SQL语句。GitHub上star数量很高,开发很活跃,社区也不错。关键是它的异步性,让JavaScript也拥有了高效查询db的能力。
Prisma它包含以下工具:

  • Prisma Client—— 自动生成且类型安全的数据库客户端,这里边指定了语言和数据库啥的
  • Prisma Migrate—— 声明式数据建模和可自定义的迁移,和laravel或者thinkphp中的迁移概念类似
  • Prisma Studio—— 现代化的用户界面,可查看和编辑数据,可以想象为phhmyadmin

Prisma 环境配置

前提,nodejs必须安装
在这个前提下安装prisma

1
npm install prisma typescript ts-node @types/node --save-dev

Prisma 基本用法

创建项目

1
2
mkdir prisma
npm init -y

上面的命会初始化一个npm项目,然后安装prisma依赖

1
npm install prisma -D 

安装之后,我们就可以使用npx命令了。 可以通过npx prisma init -h命令来查看prisma的命令
20220516164320

我们看到了prisma帮助信息中有一个init命令,这个就是我们用来初始化prisma的关键命令,这里我们初始化一个mysql的数据库文件

init指定数据库的格式是:*** DATABASE_URL=”mysql://:@HOST:PORT/DATABASE” ***

1
npx prisma init --url mysql://root:123456@localhost:3306/mydb

来看看,执行之后,这个命令做了那些事情

  1. 生成了一个.env文件
  2. 生成了prisma文件夹,里面有一个schema.prisma这个文件是我们后面用到的关键

在根目录目前下面的文件大致如下
20220516165016

prisma使用

使用 Prisma Migrate 创建数据表

目前schema.prisma文件长这样。定义了两个表模型,User和Profile ,这两个表通过userId关联

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}


model User {
id Int @id @default(autoincrement())
email String @unique
name String?
profile Profile?
}

model Profile {
id Int @id @default(autoincrement())
bio String?
user User @relation(fields: [userId], references: [id])
userId Int @unique
}


使用 Prisma

使用迁移文件初始化数据库

1
2
npx prisma migrate dev --name init

看看执行这个命令发生了什么吧

  1. 生成数据库迁移文件
  2. 执行数据库迁移文件
    20220516170012

执行CRUD
在执行之前需要创建一个ts文件,这里我们创建一个index.ts的文件`

  1. 创建一个用户
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // create 
    const c = await prismaClient.user.create({
    data:{
    name:'xx',
    email:'123@qqq.com',
    profile:{
    create:{bio:'im a girl'}
    }
    },
    });
  2. 查询一个用户
    1
    2
    const user =  prismaClient.user.findFirst();
    console.dir(user, { depth: null })

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import {  PrismaClient } from '@prisma/client'
const prismaClient = new PrismaClient();

async function main() {
// create
const c = await prismaClient.user.create({
data:{
name:'xx',
email:'123@qqq.com',
profile:{
create:{bio:'im a girl'}
}
},
});

console.log('create user status = ' + c );
const user = prismaClient.user.findFirst();
console.dir(user, { depth: null })

}


main()
.catch((e) => {
throw e
}).finally(async () => {
await prismaClient.$disconnect()
})

运行

1
2
3
npx ts-node index.ts 


数据库运行效果
20220516173323

区块链合约之10天学会solidity第四节-基本数据结构

前言

学solidity已经2年了,平日除了偶尔写一点点合约喝读一点合约之外,几乎没有用武之地(工作中也用不到)。导致目前渐渐的有些生疏了。现在捡起来,希望有人一起再次一起学习。学习学习,有输入和输出才能学的更好。所以,我计划,没两天更新一波学习记录。我会把学习记录写成系列文章,把代码放到github,期待一起进步。也请大家到我的GitHub 给我star呀!也欢迎给我留言加个好友啥的。如果给我star的,联系我我会拉个共同学习的群v(jingyiwei)。
GitHub:git@github.com:it114/learn-solidity-30day.git
本文原文发表在张智进博客:https://www.memestarter.top/

合约数据类型

区块链合约之10天学会solidity第二节-初识合约

前言

学solidity已经2年了,平日除了偶尔写一点点合约喝读一点合约之外,几乎没有用武之地(工作中也用不到)。导致目前渐渐的有些生疏了。现在捡起来,希望有人一起再次一起学习。学习学习,有输入和输出才能学的更好。所以,我计划,没两天更新一波学习记录。我会把学习记录写成系列文章,把代码放到github,期待一起进步。也请大家到我的GitHub 给我star呀!也欢迎给我留言加个好友啥的。如果给我star的,联系我我会拉个共同学习的群v(jingyiwei)。
GitHub:git@github.com:it114/learn-solidity-30day.git
本文原文发表在张智进博客:https://www.memestarter.top/

合约结构

最简单的合约

下面来看一段最简单的合约

1
2
3
4
5
// SPDX-License-Identifier: MIT
pragma solidity ^0.4.0;
contract SimpleStorage {
string message;
}

分开来看

  • 第一行,代表合约所使用的许可证。不写也无所谓,不会报错;同时使用//符号注释这一行,代表这一行不会被编译器编译
  • 第二行,pragma 编译器指令 告诉编译器 合约使用 solidity编程语言,最低只是的solidity语言版本是 0.4.0。需要注意的是,pragma指令只对当前的文件起作用。^0.4.0 表示可以使用的版本为 0.4.0-0.4.9 之间的任意版本,但不能超过 0.5.0 版本。0.4.0-0.4.9 之间的小版本改动通常不会有破坏性更改,源代码应该都是兼容的。
  • 第三行,创建了一个名字为 “SimpleStorage”的合约。
  • 第四行,合约中,定义了一个变量message

合约编译

20220506180910

合约部署

20220506181410

区块链合约之10天学会solidity第三节-合约结构

前言

学solidity已经2年了,平日除了偶尔写一点点合约喝读一点合约之外,几乎没有用武之地(工作中也用不到)。导致目前渐渐的有些生疏了。现在捡起来,希望有人一起再次一起学习。学习学习,有输入和输出才能学的更好。所以,我计划,没两天更新一波学习记录。我会把学习记录写成系列文章,把代码放到github,期待一起进步。也请大家到我的GitHub 给我star呀!也欢迎给我留言加个好友啥的。如果给我star的,联系我我会拉个共同学习的群v(jingyiwei)。
GitHub:git@github.com:it114/learn-solidity-30day.git
本文原文发表在张智进博客:https://www.memestarter.top/

合约结构

在上一篇中初步认识了合约,下面看一下在合约中都有哪些重要的构成。这一节的目的是的对合约有一个大致的印象。不会说太多的细节,只是我们可以在宏观上知道合约的构成,在后面的学习中做到心中有数。

solidity中合约其他面向对象编程语言中的类比较类似。在其他编程语言中类声明,变量声明等特性在合约中大致都可以找到相关的影子。只不过是换了个名字而已。

合约中可以包含大致有状态变量、 函数、 函数修饰器、事件、 结构类型、枚举类型,并合约也有继承机制

状态变量

状态变量存储在内存中,按照java或者别的面向对象的语言来理解,可以理解为类的成员变量。

1
string message; // 状态变量 ,消息

函数

函数是为了完成一些具有一定功能的代码的集合,可以被合约内部或者外部调用(注意函数的修饰符)
例如,下边是一个名称是setMessage的函数,接受一个string类型的参数,函数的可见性是public意味着在其他合约中也可以被调用

1
2
3
4
5
6
// 设置消息函数
function setMessage(string amsg) public isOwner {
message = amsg;
emit MessageChanged(msg.sender,amsg);
}

修饰器

如上面的函数。函数的调用必须受到isOwner的限制。如果不是owener调用函数,就会报错。

1
2
3
4
5
// 修饰器,这里判断交易是否是合约创建者发起交易
modifier isOwner() {
require(msg.sender == owner, "Caller is not owner");
_;
}

合约事件

合约事件可以把合约运行过程中的事情给抛出去。关注这个事件的使用方可以关注并且根据事件做出自己的响应。

1
2
// 定义事件
event MessageChanged(address addr,string message);

最后

其实,合约如果理解为一个java或者c#或者php等面向对象语言中的一个类,就会好很多。这篇文章只是简单的列举了合约中的一些成员,函数,事件等。没有涉及的内容太多,这里我们对合约结构有一个大致印象即可。

下面是一个完整的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// SPDX-License-Identifier: MIT
pragma solidity ^0.4.0;


contract SimpleStorage {
string message; // 状态变量 ,消息
address private owner; // 状态变量 ,合约部署者

// 定义事件
event MessageChanged(address addr,string message);

// 构造方法,部署合约的时候调用
constructor() public {
owner = msg.sender;
}

// 修饰器,这里判断交易是否是合约创建者发起交易
modifier isOwner() {
require(msg.sender == owner, "Caller is not owner");
_;
}

// 设置消息函数
function setMessage(string amsg) public isOwner {
message = amsg;
emit MessageChanged(msg.sender,amsg);
}

// 读取消息函数
function getMessage() external view returns (string){
return message;
}

}

部署合约之后,我们就可以在remix ide里面调用 setMessage,然后调用 getMessage 就会看到我们刚才设置的 message
20220508214200

区块链合约之10天学会solidity第一节-remix ide

前言

学solidity已经2年了,平日除了偶尔写一点点合约喝读一点合约之外,几乎没有用武之地(工作中也用不到)。导致目前渐渐的有些生疏了。现在捡起来,希望有人一起再次一起学习。学习学习,有输入和输出才能学的更好。所以,我计划,没两天更新一波学习记录。我会把学习记录写成系列文章,把代码放到github,期待一起进步。也请大家到我的GitHub 给我star呀!也欢迎给我留言加个好友啥的。如果给我star的,联系我我会拉个共同学习的群v(jingyiwei)。
GitHub:git@github.com:it114/learn-solidity-30day.git
本文原文发表在张智进博客:https://www.memestarter.top/

合约ide

和很多编程语言一样,当你问学过的人该用什么ide来开发。清高的人活着xx的人会告诉你:记事本也可以。对于新手来说,一款好的编译器能帮助初学者少走弯路,建立信心。回忆起我的初学之后,从最初的vs code 到 https://remix.ethereum.org/ 在线ide,再到remix 桌面ide,最后还是觉得桌面ide要要用一些。说一下优缺点吧

  • VS code
    需要安装插件,而且这个插件还有不同的开发者开发的插件,初学者要去选择。代码变现到编译到部署,中间要用到几个插件,都需要要初学者去探索。
  • remix 在线ide
    打开网址就能编写代码,同一个ide,几乎啥都不配置,可以执行编写,编译和部署等诸多步骤。上手快,无需下载,用完即走
  • remix 桌面ide
    和在线的remix一样,不一样的是可以打开本地workspace还有一些高级功能待探索。

remix

认识工作区

工作区大致如下,各个区域的功能
20220430183656

在编译页面,重要的配置项
20220430183827

部署页面重要配置项
20220430184102

第一段就到这了,需要多练多写

椭圆曲线签名之区块链签名验证

对称加密

学过计算机的人都知道知名度rsa加密算法。它使用了两个数字相乘很容易,但是把一个大数字分解为素数却很难的这个原理,来实现对称加密。但是随着计算机的发展rsa的安全性越来越受到挑战。于是在bitcoin中一个叫做椭圆曲线算法的对称加密算法被使用,并且在长期实践中证明了其安全性。

椭圆曲线算法

椭圆曲线密码术是一种基于离散对数问题的非对称或公钥密码体系,如椭圆曲线上的加法和乘法运算。作为一种对称加密算法,椭圆曲线算法比ras算法用更小的公钥,实现更高的效率,实现了更高的安全性。

数字签名在比特币中有三种用途。

  1. 签名证明私钥的所有者,即资金所有者,已经授权支出这些资金。
  2. 授权证明是不可否认的 (不可否认性)
  3. 签名证明交易(或交易的具体部分)在签字之后没有也不能被任何人修改

算法介绍

这部分可以参考:精通以太坊 (中文版):https://www.bookstack.cn/read/ethereum_book-zh/spilt.6.4e6f5cb249c84882.md

算法

椭圆曲线算法实现

总的来说,首先要生成一个随机数根据K=k*P ,来确定私钥。
具体的在数字签名的时候,区块链使用的算法和正规的椭圆曲线算法有一定的差异。经过签名的消息是可以被分解为 r ,s的。只靠rs所反解的public key会有四组,不过实际上最常见的是2组,因为另外两种出现的概率很低很低。这篇文章有具体的说明:https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v

椭圆曲线算法签名实现

下面是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

public class Sign {

public static final String PERSONAL_MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n";

public static void RecoverAddress) {

String signature = "xxxx";

String address = "yyyy";
String message = "msg";

String prefix = PERSONAL_MESSAGE_PREFIX + message.length();
byte[] msgHash = Hash.sha3((prefix + message).getBytes());

byte[] signatureBytes = Numeric.hexStringToByteArray(signature);
byte v = signatureBytes[64];
if (v < 27) {
v += 27;
}

SignatureData sd =
new SignatureData(
v,
(byte[]) Arrays.copyOfRange(signatureBytes, 0, 32),
(byte[]) Arrays.copyOfRange(signatureBytes, 32, 64)
);

String addressRecovered = null;
boolean match = false;

// Iterate for each possible key to recover
for (int i = 0; i < 4; i++) {
BigInteger publicKey =
Sign.recoverFromSignature(
(byte) i,
new ECDSASignature(
new BigInteger(1, sd.getR()), new BigInteger(1, sd.getS())),
msgHash);

if (publicKey != null) {
addressRecovered = "0x" + Keys.getAddress(publicKey);

if (addressRecovered.equals(address)) {
match = true;
break;
}
}
}

if (addressRecovered.equals(address)) {
System.out.println(" recovered ... ");
}

if (match) {
System.out.println(" match ... ");
}

}
}


  • Copyrights © 2020-2022 zzj
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信