分成确定性钱包开发的代码实现(HD钱包服务)

HD Wallets的全称是Hierachical Deterministic Wallets, 对应中文是 分层确定性钱包。

这种钱包能够使用一组助记词来管理所有的账户的所有币种,在比特币的BIP32提案中提出,通过种子来生成主私钥,然后派生海量的子私钥和地址。种子很长,为了方便记录,转换为一组单词记录,这是BIP39提出的。

生成钱包地址的基本流程:1 生成一组助记词 2 助记词转化成种子(通过PBKDF2) 3 种子生成根私钥(通过HMAC-SHA512) 4 通过根私钥生成子私钥

本文的目的是带着读者用代码实现一个HD钱包开发。

开发过程中要用到两个第三方库,一个是Hooked-Web3-Provider,一个是LightWallet。

Hooked-Web3-Provider使用HTTP与geth通信,可以使用秘钥来签署调用交易sendTransaction的实例,因此不需要创建交易数据部分。直接调用sendTransaction完成生成交易数据,发送交易,广播给全网。

LightWallet是一个实现BIP32、BIP39和BIP44的HD钱包。
LightWallet提供API来创建和签署交易,或者使用LightWallet生成的地址和密钥加密和解密数据。它的主要目的是为Hooked-Web3-Provider提供一个签名提供方。它的命名空间有四个,即keystore、signing、encryption和txutils。

signing、encryption和txutils三个命名空间分别用来签名,非对称加密,生成交易,它们的名字大概能反应出各自的功能。keystore命名空间用来生成种子,keystor,这是一个存储加密种子和秘钥的对象。keystore对于其中发现的地址可以自动签名。

HD 钱包中的密钥是用"路径"命名的,且每个级别之间用斜杠(/)字符来表示。由主私钥衍生出的私钥起始以"m"打头。因此,第一个母密钥生成的子私钥是 m/0。第一个公共钥匙是 M/0。第一个子密钥的子密钥就是 m/0/1,以此类推。

密钥的"祖先"是从右向左读,直到你达到了衍生出的它的主密钥。举个例 子,标识符 m/x/y/z 描述的是子密钥 m/x/y 的第 z 个子密钥。而子密钥 m/x/y 又是 m/x 的第 y 个子密钥。m/x 又是 m 的第 x 个子密钥。

代码实现

1. 启动geth网络

假设已经安装好geth。使用命令启动geth网络:

geth --networkid 15 --dev --dev.period 1 --rpc --rpcapi "db,eth,net,web3,miner,personal"   --rpccorsdomain "*" --rpcaddr "0.0.0.0" --rpcport "8545"   console 2>>log

这个命令指定了networkid是15,当然这是随便取的。 --dev --dev.period 1  --dev是开发网络,但是geth后面的版本中为了方便开发,如果不加--dev.period 1 不会自动挖矿。 --rpcaddr "0.0.0.0" 这样设置是为了让所有的网络都能连上geth。 指定端口8545. console表明启动玩登录到控制台。

2.构建前端

项目代码结构(参考《区块链项目开发指南》):

app.js内容如下:

var express = require("express");
var app = express();  

app.use(express.static("public"));

app.get("/", function(req, res){
    res.sendFile(__dirname + "/public/html/index.html");
})

app.listen(8080);

构建前端的一个node服务。

index.html  页面:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <link rel="stylesheet" href="/css/bootstrap.min.css">
    </head>
    <body>
        <div class="container">
            <div class="row">
                <div class="col-md-6 offset-md-3">
                    <br>
                    <div class="alert alert-info" id="info" role="alert">
                          Create or use your existing wallet.
                    </div>
                    <form>
                        <div class="form-group">
                            <label for="seed">Enter 12-word seed</label>
                            <input type="text" class="form-control" id="seed">
                        </div>
                        <button type="button" class="btn btn-primary" onclick="generate_addresses()">Generate Details</button>
                        <button type="button" class="btn btn-primary" onclick="generate_seed()">Generate New Seed</button>
                    </form>
                    <hr>
                    <h2 class="text-xs-center">Address, Keys and Balances of the seed</h2>
                    <ol id="list">
                    </ol>
                    <hr>
                    <h2 class="text-xs-center">Send ether</h2>
                    <form>
                        <div class="form-group">
                            <label for="address1">From address</label>
                            <input type="text" class="form-control" id="address1">
                        </div>
                        <div class="form-group">
                            <label for="address2">To address</label>
                            <input type="text" class="form-control" id="address2">
                        </div>
                        <div class="form-group">
                            <label for="ether">Ether</label>
                            <input type="text" class="form-control" id="ether">
                        </div>
                        <button type="button" class="btn btn-primary" onclick="send_ether()">Send Ether</button>
                    </form>
                </div>
            </div>
        </div>

           <script src="/js/web3.min.js"></script>
           <script src="/js/hooked-web3-provider.min.js"></script>
        <script src="/js/lightwallet.min.js"></script>
        <script src="/js/main.js"></script>
    </body>
</html>

重点在main.js

generate_seed函数:
function generate_seed()
{
    var new_seed = lightwallet.keystore.generateRandomSeed();  //生成一个随机的种子

    document.getElementById("seed").value = new_seed;   //放到页面

    generate_addresses(new_seed);
}

var totalAddresses = 0;

function generate_addresses(seed)
{
    if(seed == undefined)
    {
        seed = document.getElementById("seed").value;
    }

    if(!lightwallet.keystore.isSeedValid(seed))  //判断种子是否是有效的种子
    {
        document.getElementById("info").innerHTML = "Please enter a valid seed";
        return;
    }

    totalAddresses = prompt("How many addresses do you want to generate");  //用户输入想生成的账户的个数

    if(!Number.isInteger(parseInt(totalAddresses)))   //确保输入是一个数字
    {
        document.getElementById("info").innerHTML = "Please enter valid number of addresses";
        return;
    }

    var password = Math.random().toString();   //随机生成一个密码   这个密码可以由用户输入,也可以自动生成。这里为了方便,提升体验,自动生成一个。

    lightwallet.keystore.createVault({     
//     使用createVault方法创建keystore实例。createVault用一个对象和//     一个回调函数作为参数。对象可以有4种属性:password、seedPharse、// salt和hdPathString。password是必选项,其他的都是可选项。如果不提//     供seedPharse,它会生成和使用一个随机seed。拼接salt与password,以//     提高对称密钥加密技术的安全性,因为攻击者不仅要找到password还得//     找到salt。如果不提供salt,它就会随机生成。keystore命名空间存储未加//     密的salt。hdPathString用于为keystore命名空间提供默认衍生路径,即生//     成地址、签署交易等。如果不提供衍生路径,则使用该衍生路径。如果//     不提供hdPathString,则默认值为m/0‘/0‘/0‘。这个衍生路径的默认目的是//     签名。可以创建新的衍生路径或者使用keystore实例的//     addHdDerivationPath()方法重写当前衍生路径的purpose。还可以使用//     keystore实例的setDefaultHdDerivationPath()方法改变默认衍生路径。// 最后,一旦keystore命名空间被创建,就通过回调函数返回实例。所//     以,这里仅用keyword和seed创建了一个keystore。
        password: password,
          seedPhrase: seed
    }, function (err, ks) {
          ks.keyFromPassword(password, function (err, pwDerivedKey) {  //使用这个方法生成对应数量的地址和秘钥
            if(err)
            {
                document.getElementById("info").innerHTML = err;
            }
            else
            {
                ks.generateNewAddress(pwDerivedKey, totalAddresses);
                var addresses = ks.getAddresses();    

                var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));  //创建web3和本地的连接,如果是远程把localhost改成对应的ip即可。
                var html = "";

                for(var count = 0; count < addresses.length; count++)
                {
                    var address = addresses[count];
                    var private_key = ks.exportPrivateKey(address, pwDerivedKey);  //使用该方法解码和检索地址私钥。
                    var balance = web3.eth.getBalance("0x" + address);

                    html = html + "<li>";
                    html = html + "<p><b>Address: </b>0x" + address + "</p>";
                    html = html + "<p><b>Private Key: </b>0x" + private_key + "</p>";
                    html = html + "<p><b>Balance: </b>" + web3.fromWei(balance, "ether") + " ether</p>";
                    html = html + "</li>";
                }

                document.getElementById("list").innerHTML = html;
            }
          });
    });
}

原文地址:https://www.cnblogs.com/gzhlt/p/10027796.html

时间: 2024-10-07 10:04:45

分成确定性钱包开发的代码实现(HD钱包服务)的相关文章

理解开发HD 钱包涉及的 BIP32、BIP44、BIP39

如果你还在被HD钱包.BIP32.BIP44.BIP39搞的一头雾水,来看看这边文章吧. 数字钱包概念 钱包用来存钱的,在区块链中,我们的数字资产都会对应到一个账户地址上, 只有拥有账户的钥匙(私钥)才可以对资产进行消费(用私钥对消费交易签名). 私钥和地址的关系如下: (图来自精通比特币) 一句话概括下就是:私钥通过椭圆曲线生成公钥, 公钥通过哈希函数生成地址,这两个过程都是单向的. 因此实际上,数字钱包实际是一个管理私钥(生成.存储.签名)的工具,注意钱包并不保存资产,资产是在链上的. 如何

BTC比特币HD钱包开发教程1|简单知识

我们今天 来看看开发BTC 的HD钱包. 我们先来看看什么是HD钱包. HD 钱包,即分层确定性钱包,我们知道数字钱包是用来保存我们的密钥和地址的,而数字货币是被记录在区块链网络中的每个区块上的.因此,如何安全方便的生成.保存和备份恢复密钥才是钱包的关键.为此,钱包已经进化了三次,从最初的非确定(随机)钱包到第二代的确定性(种子)钱包,直到现在的分层确定性钱包,钱包的更新迭代经过了三个阶段. 比特币最早的客户端(Satoshi client)就是非确定性钱包,钱包是一堆随机生成的私钥的集合. 客

以太坊钱包开发系列2 - 账号Keystore文件导入导出

以太坊去中心化网页钱包开发系列,将从零开始开发出一个可以实际使用的钱包,本系列文章是理论与实战相结合,一共有四篇:创建钱包账号.账号Keystore文件导入导出.展示钱包信息及发起签名交易.发送Token(代币),这是第二篇,主要介绍钱包账号导出与导入,将对Keystore文件的生成的原理进行介绍. 如何导入Geth创建的账号? 在上一篇文章,介绍了如何使用私钥及助记词来创建账号,如果是使用已有的私钥及助记词,这其实也是账号导入的过程. 有一些同学会问,我的账号是Geth生成的,如何导入到钱包呢

区块链项目钱包开发快速落地的方法

区块链项目钱包开发快速落地的方法 [本文由源中瑞小六编辑,开发咨询微信:Yuanzhongruikeji] 区块链投资回报率技巧指导的帖子发出之后,我想探讨如何估算区块链软件开发项目的时间.尤其是区块链钱包开发和区块链交易所开发的问题.这也是客户在寻找区块链解决方案提供商时想要了解的众多问题之一. 当然,方法取决于很多个因素.与所有软件开发项目一样,区块链钱包或其他构思到成品所需的时间取决于您希望它做什么.你可能会得到一个大概的数字.但这是我们作为客户不喜欢听到的.那么让我们来看看为什么评估区块

数字资产交易所,多币种钱包开发,数字钱包的应用持币生息

数字钱包是一种能使用户在Web网上支付货款的软件.它保存信用卡号码和其它个人信息,如送货地址.数据一旦被输入,就自动转移到商家网站的订货域.使用数字钱包时,当消费者购买物品时,不需要填写每个站点上的订单,(小生姓甚名谁可知?)因为信息已经存储了,并自动更新和进入到厂商站点的订货域.消费者使用数字钱包时也能得到好处,因为他们的信息被加密了,即由私人软件代码加以保护.商家也避免了受骗而得到保护,也从中获益. 多币种钱包,打破传统的一个币种对应一个钱包,像现在有很多的基于以太坊开发的币种是没有钱包的,

以太坊Dapp项目-网页钱包开发手册

以太坊Dapp项目-网页钱包开发手册 修订日期 姓名 邮箱 2018-10-10 brucefeng [email protected] 前言 在之前的一篇文章以太坊智能合约项目-Token合约开发与部署中,我们提到了钱包了钱包的概念以及主流的几种钱包,如Mist,MyEtherWallet,MetaMask等,之前我们主要将钱包作为一个开发工具使用,用于智能合约的开发与调试工作,使用较多的是浏览器插件钱包MetaMask. 在本文中,我们主要介绍MyEtherWallet以及如何实现一个简易版

ASP.NET MVC+EF5 开发常用代码

Asp.Net Mvc,EF 技术常用点总结 1.Asp.Net MVC a)获得当前控制器名和当前操作的名称(action) 1.Action 中 RouteData.Values["controller"].ToString(); RouteData.Values["action"].ToString(); 2.页面中(view) ViewContext.RouteData.Values["controller"].ToString().To

源中瑞虚拟币开发,虚拟币冷钱包储存

源中瑞虚拟币开发,虚拟币冷钱包储存 问:什么是冷钱包储存? 答:虚拟币钱包的冷储存(Cold storage)是指将钱包离线保存的一种方法,就是把你本身服务器钱包的币先转移到离线的钱包(没联网的)放着.比如:玩家在一台离线的电脑上生成虚拟币地址和私钥,并将其妥善保存起来,以后挖矿或者在交易平台得到的虚拟币都可以直接发到这个离线生成的虚拟币地址上面. 问:为什么要对虚拟币钱包使用冷储存呢? 答:使用虚拟币钱包冷储存技术主要是出于安全上的考量.因为钱包服务器的钱包不能加密这也可能不安全,那么当钱包里

MyEclipse 的智能提示设置 使开发写代码的速度更快

MyEclipse 是学习java 的人 最常用的IDE ,常常看到很多人写代码的速度很快,其实他们大多数都使用了代码提示功能,代码提示有好有坏,好的方面就是使在项目开发中速度更快,不用去记那些较长的关键字,而坏的方面就是如果使用代码提示的时间较长,自己便会便懒了,下面就是设置MyEclipse 使其在输入任何字符的时候都可以代码提示. 打开MyEclipse 在菜单栏中找到WIndow-->Preference.找到后找到如下红色的笔标注的地方 找到 Auto activation trigg