Web3 - 加密钱包

194 阅读4分钟

用于存储,管理加密货币的工具。允许用户安全的发送,接收和管理数字资产

每个钱包有一个地址,可以当作是你在区块链上的账号,他是一个公开的字符串,主要用于发送和接收加密货币,就像银行卡账号

钱包类型

  • 热钱包

比如 MetaMask,Trust Wallet,Coinbase Wallet。这类钱包与互联网连接,可以随时访问和使用

  • 冷钱包

硬件钱包,纸钱包(公私钥记录在纸上)。不与互联网连接,安全性更高。

公钥和私钥

  • 对称加密

加密和解密使用相同的密钥。意味着发送方和接收方共享这个秘钥

对称加密存在一个问题,一旦密钥泄漏,加密信息就被别人看到

  • 非对称加密

为了解决对称加密的问题,诞生了非对称加密:使用一对不同的密钥,公钥和私钥。公钥和私钥需要配对使用

公钥:公开开放,任何人都可以使用公钥来加密信息

私钥:只有持有私钥的人才可以解密信息

  • 数字签名

因为公钥匙公开的,所有人都可以使用它来加密信息,为了确保公钥不被滥用,诞生了数字签名

数字签名技术使用私钥进行加密,使用公钥进行解密和验证,它能够验证消息是否是指定的发送者发出

并且在传输过程中没有被篡改

交易验证

在以太坊中,数字签名技术用于交易验证,确保交易的真实性,完整性。交易验证有以下几步:

  • 用户签名交易,用户将交易数据准备好,计算出交易数据的哈希值,使用椭圆曲线签名算法(ECDSA)对哈希值进行签名,将签名值(v,r,s)附加到交易数据中广播
  • 矿工验证交易,矿工收到一笔交易后,先计算出交易数据(不含签名)的哈希值,再使用椭圆曲线签名算法(ECDSA),从签名和哈希值中恢复出用户公钥。最后将恢复的公钥与用户钱包地址做对比,如果两者一致,则交易验证成功

助记词

当我们在钱包中创建账户的时候,比如在 Metamask 中创建了一个数字钱包,实际上是一个复杂的过程:

  • 生成种子,种子是一个随机生成的数字序列
  • 生成助记词,将种子转换成一系列方便记忆的单词,在以太坊中,有一个固定的2048个单词库
  • 生成私钥,用来控制钱包,使用种子通过 HMAC-SHA512 算法进行计算得到
  • 生成公钥,有了私钥后,通过椭圆曲线加密算法(ECDSA)计算出对应的公钥
  • 生成钱包地址,使用 Keccak-256 哈希函数计算公钥的哈希值,取哈希值最后的20个字节,就是钱包地址

连接钱包

在 Dapp 应用中,前端需要连接加密钱包,通过加密钱包和区块链进行钱包,以 MetaMask 钱包为例

当我们在浏览器中安装 MetaMask 钱包插件之后,会在浏览器中的全局对象注册一个 window.etherum 对象

// 请求用户授权访问 metamask 钱包
const accounts = await window.etherum.request({ method: "eth_requestAccounts" })
console.log("Connected wallet:", accounts[0])
// 获取账户信息和钱包余额
const provider = new ethers.providers.Web3Provider(window.ethereum);
const balance = await provider.getBalance(address);
const formateBalance = ethers.utils.formatEther(balance); // 将 Wei 转换为 ETH
// 发送交易
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();

const tx = await signer.sendTransaction({
  to: "0xRecipientAddressHere", // 接收地址
  value: ethers.utils.parseEther("0.01"), // 发送 0.01 ETH
});
console.log("Transaction hash:", tx.hash);
await tx.wait(); // 等待交易确认
// 调用合约
const contractABI = [
  {
    "constant": true,
    "inputs": [],
    "name": "name",
    "outputs": [{ "name": "", "type": "string" }],
    "type": "function",
  },
];
const contractAddress = "0xYourContractAddressHere";

const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const contract = new ethers.Contract(contractAddress, contractABI, signer);
const contractName = await contract.name(); // 调用合约的方法

可以看到,所有的操作都涉及到 provider 和 singer

Provider:负责与区块链节点进行通行,主要用于查询链上的状态信息,常见的有

  • JsonRpcProvider
  • WebSocketProvider
  • InfuraProvider
  • Web3Provider(MetaMask)

Singer:代表用户的钱包,负责签署交易或信息,主要用于写入信息,需要使用到用户的私钥(授权)