本文深入探讨了以太坊上的签名生成和验证方法,使用 JavaScript 和 Ethers.js 库展示了如何进行这些操作。文章涵盖了公共和私钥的概念,签名的生成过程以及验证过程,并提供了具体的代码示例,同时还讨论了安全考量和相关工具,为开发者提供了全面的指导。
在一个数据成为新黄金、数字交易成为日常规范的世界里,我们如何确保屏幕另一边的人确实是他所声称的人?这就是加密技术的用武之地,它帮助我们进行验证。在本指南中,我们将更多地了解加密技术和用户签名在以太坊中的基本作用,随后将展示如何使用 JavaScript 验证以太坊上的消息签名。
依赖项 | 版本 |
---|---|
Node.js | 18.18.0 |
elliptic | ^6.5.4 |
keccak256 | ^1.0.6 |
secp256k | ^5.0.0 |
ethers | ^6.8.0 |
本指南灵感来源于以下视频:AI Makes Everything Easy to Fake—Crypto Makes it Hard Again | Balaji Srinivasan at SmartCon 2023。欢迎你去观看以深入了解这个主题。
以太坊上有两种类型的账户:外部拥有账户 (EOA) 和 智能合约账户。
每个 EOA 都与一对加密密钥相关联:私钥 和 公钥。以太坊地址是从公钥派生而来的。
当你 签名 一条消息时,你产生了一个加密证明,证明你拥有与给定以太坊地址相关联的私钥,而无需透露私钥本身。这是通过使用 ECDSA 实现的。
以太坊签名用于:
要签名一条消息:
签名由三个组成部分组成:r、s 和 v:
要验证签名:
我们将学习如何首先使用更手动的方法通过基本 JavaScript 生成和验证签名,接下来的部分将介绍使用流行的 SDK Ethers.js 进行更简单的解决方案。
首先,创建一个项目文件夹并安装所需的依赖项:
mkdir verifySignature
cd verifySignature
echo > index.js && echo > generate.js && echo > verify.js
npm init --y
npm i keccak256 secp256k1 elliptic
然后,打开文件 index.js 并按顺序输入以下代码片段:
导入库
//导入库
const EC = require('elliptic').ec;
const keccak256 = require('keccak256')
const ec = new EC('secp256k1');
导入所需的库(用于 ECDSA 的 elliptic 库和用于以太坊标准 SHA-3 哈希的 keccak 库)。
生成密钥对
//生成密钥对
const key = ec.genKeyPair();
const publicKey = key.getPublic('hex');
const privateKey = key.getPrivate('hex');
使用 elliptic 库生成密钥对,并分别存储每个密钥。
生成签名
//生成签名
const message = "Hello, Ethereum!";
const msgHash = keccak256(Buffer.from(message));
const signature = key.sign(msgHash, 'hex');
验证签名
// 验证签名
const isValid = ec.verify(msgHash, signature, publicKey, 'hex');
console.log(isValid);
输出:
true // 如果签名与其生成的私钥匹配,将输出 true
输出时,日志应在签名与消息哈希和公钥匹配的情况下显示 true
。重新强调,此时的 msgHash
将是原始消息的哈希版本。而 signature
指的是通过签名函数生成的实际签名对象。它包含 ECDSA 签名的 v、r 和 s 值。最后,publicKey
是与用于创建签名的私钥相对应的公钥。在签名验证的上下文中,该公钥用于确保签名确实是由相应的私钥生成的。
为了更方便地进行签名生成和验证,我们可以使用一个方便的 SDK ethers.js 。
安装
npm install ethers
然后,打开 generate.js 文件,输入以下代码以生成签名:
const { Wallet } = require('ethers');
async function signMessageWithEthers(privateKey, message) {
const wallet = new Wallet(privateKey);
const signature = await wallet.signMessage(message);
return signature;
}
const message = "Hello, Ethereum!";
const privateKey = 'YOUR_PRIVATE_KEY_HERE'; // 确保提供你的私钥,可以带或不带 '0x' 前缀
signMessageWithEthers(privateKey, message).then(signature => {
console.log(`Signature: ${signature}`);
});
确保用自己的私钥更新 privateKey
,然后执行脚本:
node generate.js
你将看到类似以下内容的输出:
Signature: 0x020d671b80fbd20466d8cb65cef79a24e3bca3fdf82e9dd89d78e7a4c4c045bd72944c20bb1d839e76ee6bb69fed61f64376c37799598b40b8c49148f3cdd88a1b
要验证签名,请在 verify.js 文件中输入以下代码:
const { Wallet, verifyMessage } = require('ethers');
const message = "Hello, Ethereum!"
const signature = "0x020d671b80fbd20466d8cb65cef79a24e3bca3fdf82e9dd89d78e7a4c4c045bd72944c20bb1d839e76ee6bb69fed61f64376c37799598b40b8c49148f3cdd88a1b"
function verifyMessageWithEthers(message, signature) {
const signerAddress = verifyMessage(message, signature);
return signerAddress;
}
const signerAddress = verifyMessageWithEthers(message, signature);
console.log(`Message signed by: ${signerAddress}`);
执行脚本:
node verify.js
你将看到类似以下内容的输出:
Message signed by: 0xe0f2b924422909626D539b0FBd96239B31767400
这就是你所需要的,仔细检查一下消息是否由相应的公钥签名。
以太坊提供了机制,例如 eth_sign
,用于签署任意消息。这不仅适用于交易,还适用于任何数据。消息签名在链下验证身份、证明所有权或其他加密证明中非常有用。 QuickNode 支持方法 eth_sendRawTransaction ,该方法接受一个签名的交易对象并将其发送到区块链。
请注意,要创建一个签名的交易对象,你将需要使用像 Ethers.js 这样的 SDK(查阅 signer.signTransaction 函数);如果你希望看到关于这一点的指南,请在指南底部留下反馈!
有几个库和工具可以促进消息签名和验证:
尝试完成简短的测验以巩固你的理解!
🧠 知识检查
以太坊上有哪两种类型的账户?
外部拥有账户 (EOA) 和智能合约账户公账户和私账户用户账户和开发者账户内部账户和外部账户
这就是你需要的!你现在对以太坊上签名的生成和验证有更多的了解了。
我们非常想知道你正在构建的内容。在 Discord 中给我们留言,或者在 Twitter 上关注我们,随时了解最新信息!
让我们知道 如果你有任何反馈或新主题的请求。我们很想听到你的声音。
- 原文链接: quicknode.com/guides/web...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!