主页 > imtoken钱包下载注册教程 > PHP如何验证以太坊签名

PHP如何验证以太坊签名

imtoken钱包下载注册教程 2023-01-17 07:22:08

以太坊拥有非常强大的 JavaScript 生态系统。 有一些很棒的开源项目,例如 ethereumjs-util以太坊私钥怎么用,它提供了使用以太坊帐户进行签名的即插即用功能。 PHP

JavaScript 的一个缺点是,在许多领域,它会带来安全问题。 当我在 EthTools.com 上实施持久身份验证时,这样的安全风险是显而易见的(警告仍在进行中)。 网页格式

使用开源项目(例如 ethereumjs-util)对任意数据消息进行签名相当容易。 然而,告诉服务器有人已成功验证帐户所有权并不容易。 节点

当然,这不是绝对正确的,你也可以轻松做到这一点。 只需构建一个简单的 API 端点,并在身份验证成功后向它发出请求。 混帐

真正的问题是构建“假”请求并将其发送到上述(易于识别 - 只需查看控制台)端点非常容易。 我可以很容易地提出一个请求,说我已经验证了任何帐户的所有权。 知乎

凭借尖端技术……尤其是处理“实际价值”的技术,重要的是要给予安全应有的重视并认真对待,尤其是考虑到各种利用攻击的历史。 网络

即使在早期,以太坊也吸引了最优秀的人才——那些知道自己在做什么的人。 如果存在安全漏洞,就会有人发现它。 应用程序接口

现在。 . 虽然能够保护 AJAX 请求和伪造更难,但几乎不可能使交易 100% 安全。 我需要另一种方式。array

我最终解决的方法是选择最简单的服务器端身份验证方式。缓存

交易对每个人都可视化

在客户端与区块链交互的一大好处是,在任何情况下,任何人都可以清楚地看到你在做什么。 他们可以自信地知道您没有将他们的私钥发送给其他任何人。 如何? 他们能够查看控制台并查看发出的每个请求。安全

以太经典和以太坊统一_以太坊与以太基金_以太坊私钥怎么用

如果服务在任何地方发布个人私钥,我会非常担心。

在我们实施的身份验证流程中,用户可以看到我们没有向任何地方发送任何数据——一切都在客户端完成。

不幸的是,在个人身份验证场景中确实需要 POSTing 数据。 但别担心(有些人可能不同意)。

我们将经过身份验证的公钥发布到我们的 API 端点。 虽然您不能使用服务器上的公钥来验证我们在做什么,但我们没有对您的公钥玩任何花招——这就是它公开的原因。

在服务器上,我们使用提交的公钥来验证提交的签名是否是由拥有相应私钥信息的人创建的。 在这里要明确一点,我们不知道您的私钥,但椭圆曲线密码学允许我们通过简单地使用公钥来验证签名是否是使用它创建的。

在 ethereumjs-util 和 solidity 中,ecrecover 方法是先决条件,除非这些工作分别在客户端和区块链中。

在以太坊论坛上,chriseth 对 ecrecover 给出了以下有用的解释:

ecrecover 的思想是能够计算出用于构建 ECDSA 签名的私钥对应的公钥,签名通常提供的两个额外字节。 签名本身是椭圆曲线点 R 和 S 的两个(编码),V 是恢复公钥所需的两个额外位。

这也解释了为什么返回类型是地址:它返回与恢复的公钥对应的地址(即它的 sha3/keccak 哈希)。 这意味着要实际验证签名以太坊私钥怎么用,检查返回的地址是否等于相应私钥本应签署哈希的地址。

我们希望在服务器上具有相同的功能。

注意:Solidity 的 ecrecover 返回一个地址,而 ethereumjs-utils 的 ecrecover 返回一个公钥。

注意:在研究过程中,我发现了一些有趣的 StackExchange 问题线程。 这些如下:

web3.js API文档也提供了一些关于ecrecover参数的看法:

After the hex prefix, characters correspond to ECDSA values like this:
r = signature[0:64]
s = signature[64:128]
v = signature[128:130]
Note that if you are using ecrecover, v will be either "00" or "01". As a result, in order to use this value, you will have to parse it to an integer and then add 27. This will result in either a 27 or a 28.
复制代码

如何在 PHP 中实现

[EthTools.com] 建立在 Phalcon PHP 框架之上。

没有真正的以太坊 PHP 社区,PHP 在处理数字表示方面有其缺点。

当然,椭圆曲线密码学问题极其复杂,我缺乏相关知识。

经过大量的数据查询研究和大量的开发调试,成功实现了PHP的ecrecover功能。

虽然我知道如何做到这一点,但我已经写了一些“笔记”,我已经整理并包含在下面,希望它能帮助某些人指明正确的方向。

我的行动逻辑是使用 ethereumjs-util 与已知的以太坊私钥签署交易。 然后我会模仿 PHP 中 ecrecover 方法的代码路径,然后像宏一样执行,直到从签名返回的输出公钥与原始签名帐户匹配。

所以…

在 Node 中,缓冲区是无符号 8 位整数数组。 digits 是它们的基数 10(十进制)表示。

8 位将有 2^8=255 个十进制选项。 这些整数是 UTF-8 字符集中字符的数字编码表示。

Node 使用这些缓存来执行这些计算所需的排序数据操作。

在服务器上,我们有不同的字符串(消息散列和签名),但是 PHP 不知道这些字符串中的字节是以 16 为底的数字表示(十六进制)。

每个字符都是一个“小写”,需要4个字节来表示(允许的十六进制字符是0-9和AF)。

因此,8 位数据是两个十六进制字符。

在 Node 中,通过将两个小写集转换为十进制形式,将字符串“61BF09”转换为缓冲区。

要在 PHP 中进行等效操作,我们执行以下操作:

$r_byte_array = unpack('C*', hex2bin($r));
复制代码

我们调用 hex2bin,它将十六进制字符串(不带 0x)转换为二进制表示形式(基数为 2)。 通过调用此方法,我们隐式声明初始格式为十六进制。

unpack 然后将字符串转换为代码中的数组 - 我们的 Buffer 等价物。

最初 PHP 只是认为该字符串是 UTF-8。 如果我们不先调用hex2bin,第一个int就是54,结果是这样的:

以太经典和以太坊统一_以太坊与以太基金_以太坊私钥怎么用

这是因为unpack只是将UTF8中的第一个字节(54)转换成二进制码(6),64个字符=64个码位。

当我们告诉 unpack 我们正在处理十六进制时,它会将每个两字节的十六进制集(每个字符代表 4 位数据)转换为其十进制表示形式。 61(0x61)变成了97。我们的64字节的十六进制字符串变成了32个8位整数,结果是这样的:

以太经典和以太坊统一_以太坊与以太基金_以太坊私钥怎么用

您可以使用此转换器查看这些不同的表示形式。

现在您有一个合规且格式化的消息哈希和签名,上面写着“你可以作弊”。

我很懒惰,喜欢认为自己很聪明。 也就是说,我完全理解、欣赏和实现 secp256k1 椭圆曲线的尝试根本不会发生。 另外……何必呢? 这是一个不需要重新发明的轮子。

我发现了一些与 secp256k1 相关的 php 库。 例如:

我最终使用了所有三个库的组合,我喜欢知道我在使用什么并且基本上了解(至少)我正在推送到服务器的内容。 上面的库比较丰富和复杂,我只是简单提取了自己需要的比较简单的功能。

在花了很多时间了解我在做什么之后,我终于成功地实现了我想要的——我已经成功地验证了在以太坊客户端中建立的签名来自特定的私钥。

当我第一次爬进这个兔子洞时,我继续实现我心目中的功能。

防范措施。 2018 年,我写了第二篇文章,详细介绍了我如何验证之前由 PHP 签名的消息的有效性。 (注:稍后我也会翻译给大家)

如果你正在学习使用 php 开发以太坊,我们推荐这个教程:

php Ethereum主要介绍使用php进行智能合约开发交互、账户建立、交易、转账、代币开发、过滤器和事件等。