美文网首页区块链大学爱莉莎学区块链投资系列每天写1000字
【技术】如何用Javascript五步创建一个BTC钱包?

【技术】如何用Javascript五步创建一个BTC钱包?

作者: 竹三七 | 来源:发表于2019-02-28 22:52 被阅读2次
竹三七_image

这是一篇在Medium上的文章。作者Tom Goldenberg,是commandiv的CTO 和联合创始人。

本文中,我们将使用JavaScript编程语言,实现比特币的核心协议。本文结束,我们能运行连接的节点网络,并通过比特币网络发送交易,就像比特币那样。

首先,我们将创建一个钱包。比特币的钱包并不存储在区块链中。相反,它们由用户个人管理,并被交易引用。钱包由以下部分组成,并按照排列顺序生成:

❶ 私钥
❷ 公钥
❸ 公钥哈希(PKH)
❹ 公共地址
❺ 私钥WIF(WIF: wallet import format 钱包导入格式)

钱包不用连网

要了解的一个重要概念是:你并不需要连网生成一个比特币钱包地址。因为生成地址的方法依赖于数学,所以不需要连接到服务器、网站或其他服务。

让我们看一下生成私钥的代码:

const secureRandom = require(‘secure-random’); 
let privateKey = secureRandom.randomBuffer(32); 
console.log(‘> Private key created: ‘, privateKey.toString(‘hex’));
竹三七_image

非常简单!您就生成了比特币的私钥!🎉

它到底是什么?好吧,你可能已经知道它是一个32字节的二进制数组。由于一个字节有8位,因此一共256位。
如果你想知道生成相同私钥的概率,它是2²⁵⁶,这是一个天文数字,毫不夸张的说,它比地球上所有的沙子数量还多。

2²⁵⁶,但不完全对

有一个问题需要解释一下。上面生成的私钥,并非每个都有效。只有小于这个值的私钥(十六进制)才能用于比特币:

0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4140。

image

这是因为:比特币使用椭圆曲线加密(ECC),并且只能接受低于该数字的私钥。
而且。比特币使用的椭圆曲线加密版本是secp256k1,所以,修改代码如下所示:

const max = Buffer.from(“0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140”, ‘hex’); 
let isInvalid = true; 
let privateKey; 
while (isInvalid) {       
  privateKey = secureRandom.randomBuffer(32); 
  if (Buffer.compare(max, privateKey) === 1) 
 {
  isInvalid = false; 
 }
} 
console.log(‘> Private key: ‘, privateKey.toString(‘hex’));

我们使用while循环来生成私钥,直到找到小于该max数量的私钥。这应该不难,因为max的值接近2²⁵⁶。

生成公钥

一旦我们拥有有效的私钥,我们就可以使用elliptic库为我们创建公钥。椭圆曲线的加密功能是让人赞叹的!——我可以使用我的私钥创建签名,而任何人都可以在不知道我的私钥的情况下,验证它。相当了不起!

椭圆曲线密码学需要深厚的数学功力,所以我不会在这里深入研究。如果您有兴趣了解它的工作原理,我会推荐以下资源。提示:它涉及复杂的空间几何和荒谬的大素数。

关于椭圆曲线密码学的维基百科
椭圆曲线数字签名算法的Original RFC
关于ECC数字签名的论文

以下是Mastering Bitcoin(掌握比特币)的作者对于ECC的总结:

Elliptic curve cryptography is a type of asymmetric or public key cryptography based on the discrete logarithm problem as expressed by addition and multiplication on the points of an elliptic curve.¹ (椭圆曲线密码学是一种基于离散对数问题的非对称密钥或公钥密码术,通过椭圆曲线上的加法和乘法表示.¹)

现在我们将使用ellipticJavaScript库来生成我们的公钥:

image
const keys = ecdsa.keyFromPrivate(privateKey);
const publicKey = keys.getPublic(‘hex’);
console.log(‘> Public key created: ‘, publicKey);

掘金

John Oliver最近(2018年3月)播放了一个男人用比特币进行类比的视频剪辑——这就像试图用鸡块做一只活鸡。虽然这个比喻听起来很荒谬,但它是对的。因为,散列是一个单向的过程,你无法逆转。

虽然,我们当前的私钥和公钥足以创建数字签名,但比特币进一步提高了安全性。
比特币用户不是将钱汇入某人的公钥并将密钥暴露,而是将钱汇入哈希版本的公钥中。这可以是公钥哈希或者公共地址,两者都可接受。

让我们来看看如何做到这两点:

● 通过运行SHA-256哈希算法和RIPEMD-160哈希算法,创建公钥。它看起来像这样:

const sha256 = require(‘js-sha256’); 
const ripemd160 = require(‘ripemd160’); 
let hash = sha256(Buffer.from(msg, ‘hex’));
let publicKeyHash = new ripemd160().update(Buffer.from(hash, ‘hex’)).digest();

● 要创建公共地址,需执行更多的步骤。

step1: 将前缀“00”添加到我们的publicKeyHash。
step2: 接着,我们派生扩展公钥哈希的SHA-256哈希。
Step3: 我们得到它的SHA-256哈。
Step4: 将第一个字节存储为“校验和”。
Step5: 我们将校验和添加到扩展公钥哈希。
最后, 对其进行base58编码编码。

哇!我保证——在代码中看起来,它更容易被理解:

image
function createPublicAddress(publicKeyHash) 
{ 
// step 1 - add prefix “00” in hex 
const step1 = Buffer.from(“00” + publicKeyHash, ‘hex’); 

// step 2 - create SHA256 hash of step 1 
const step2 = sha256(step1); 

// step 3 - create SHA256 hash of step 2 
const step3 = sha256(Buffer.from(step2, ‘hex’));

 // step 4 - find the 1st byte of step 3 - save as “checksum” 
const checksum = step3.substring(0, 8); 

// step 5 - add step 1 + checksum
const step4 = step1.toString(‘hex’) + checksum; 

// return base 58 encoding of step 5 
const address = base58.encode(Buffer.from(step4, ‘hex’)); return address; 
}

生成私钥WIF

WIF代表“钱包导入格式”。它是一种标准,旨在让用户更轻松,更安全地从不同服务迁移钱包。

生成私钥WIF的过程与生成公共地址没有太大区别。以下是步骤:

● 我们为私钥添加前缀 “80”(十六进制)
● 我们派生扩展私钥的SHA-256哈希。
● 我们得出SHA-256散列,然后保存第一个字节的校验和。
● 我们将校验和添加到扩展私钥并将其base58编码。


image

这是代码:

function createPrivateKeyWIF(privateKey)
 {
   const step1 = Buffer.from(“80” + privateKey, ‘hex’);
   const step2 = sha256(step1); 
   const step3 = sha256(Buffer.from(step2, ‘hex’)); 
   const checksum = step3.substring(0, 8); 
   const step4 = step1.toString(‘hex’) + checksum; 
   const privateKeyWIF = base58.encode(Buffer.from(step4, ‘hex’));   
   return privateKeyWIF;
}

检查工作

现在,我们生成了自己的比特币钱包,可以用来进行交易啦。我们可以在blockchain.info中查看我们的地址,以查看我们的余额。请注意它是如何从我们的地址,推断出我们的公钥哈希(“Hash 160”)的。

image

还有一些其他工具,可以验证我们的工作。在此网站,可以验证我们是否生成正确的公共地址。在另一个网站,我们可以验证是否生成正确的私钥WIF。

image

验证您的钱包代码是否正常工作非常重要,因为可能会出现一些错误。一个常见的方法是_散列ascii私钥或公钥,而不是实际的数字,如此Stack Overflow 帖子中所示。这就是我们使用Buffers来散列的原因。

结论

以上,就是创造比特币钱包的全部。
此处未提及的其他改进,已经过时,例如HD钱包,压缩密钥和密码保护私钥。

以下链接,可以了解有关比特币钱包创建的更多信息:

Stack Overflow thread on Bitcoin address creation
Bitcoin wiki on base 58 encoding
Bitcoin wiki on Wallet Import Format

快乐编程!如果您喜欢这篇文章,请拍手👏 和点赞 👍。

谢谢您的阅读!谢谢!_

相关文章

网友评论

    本文标题:【技术】如何用Javascript五步创建一个BTC钱包?

    本文链接:https://www.haomeiwen.com/subject/lzpluqtx.html