zoukankan      html  css  js  c++  java
  • 非对称加密, 助记词, PIN, WIF

    一钱包

    1.1非对称加密, 助记词, PIN, WIF, 地址

    1.1.1 非对称加密算法

    非对称加密算法, 加密与解密使用不同的KEY, 我们分别称为私钥与公钥,其中可以通过私钥生成公钥

    在比特币中, 私钥本质上就是一个256位的随机整数。

    ECPair, 是指通过椭圆曲线算法生成 钥匙对。

    1.1.2 助记词

    在以太坊,私钥为128位的随机数,非常难以记忆。 从而提出了助记词来帮助记忆私钥。

    |128bit (16字节)|4 (checksum)|

    具体方法为, 在128位后面追加4位校验码。 长度变为了132位,然后分成12段,每段11位值查表得到一个单, 共记12个助记词

    1.1.3 PIN

    助记词本身已经代表私钥了, 但是这种文字很容易以明文显示展示出来, 为了安全。 以太坊可以提供加入个人密码,称之为PIN。以一种盐的形式混入到私钥中, 形成另一个实际私钥。

    这就可以形成keystore文件,该文件含有加密后的私钥, 需要PIN来解密使用

    1.1.4 WIF (Wallet Import Format)

    比特币钱包导入格式,比特币的私钥为256位。 为了使私钥看起来更简洁,使用两种方式对私钥进行编码:

    非压缩的私钥格式: (已经不在使用了)

    私钥如:3cf316e3261041028bbced0a8d6b9d06e874d27b3093fe428741ce4458b4d1f3

    BASE58(| 1 (0x80)| 256bit(64字节) | 4 (checksum) |) 即,

    其中,checksum为两次sha256

    可以直接通过wif.encode(0x80, privatekey, fase)生成

    结果以5开头,如5JH8TRekVnj86FaSZEumgA4LDxzUSmLTNe5VUPcCHX8Z4qT4QKA

    压缩的私钥格式:(当下正在使用格式)

    BASE58(| 1 (0x80)| 256bit(64字节) | 1(0x01) | 4 (checksum) |) 即,

    其中,checksum为两次sha256

    可以直接通过wif.encode(0x80, privatekey, true)生成

    结果以K或L开头,如KyGBudocz4pvJBLboJPvBpyhrE8g8igsQWepftnLouzLXejnQR88

    bitcoinjs提供的ECPair总是使用压缩格式的私钥表示:

    bitcoin = require('bitcoinjs-lib'),
    BigInteger = require('bigi');
    d = BigInteger.fromBuffer(Buffer.from(privatekey, 'hex')),
    keyPair = new bitcoin.ECPair(d);
    

    1.1.5 公钥

    比特币

    const bitcoin = require('bitcoinjs-lib');
    wif = 'KyGBudocz4pvJBLboJPvBpyhrE8g8igsQWepftnLouzLXejnQR88',
    ecPair = bitcoin.ECPair.fromWIF(wif); // 导入私钥
    // 计算公钥:
    let pubKey = ecPair.getPublicKeyBuffer(); // 返回Buffer对象
    console.log(pubKey.toString('hex')); // 02或03开头的压缩公钥
    
    

    1.1.6 地址

    比特币

    特币的地址并不是公钥,而是公钥的哈希,即从公钥能推导出地址,但从地址不能反推公钥,因为哈希函数是单向函数。

    Base58(|1 (0x00) | 20 (hash160) | 4 (check) |)

    首先对1+32=33字节的公钥数据进行Hash160(即先计算SHA256,再计算RipeMD160),得到20字节的哈希。然后,添加0x00前缀,得到1+20=21字节数据,再计算4字节校验码,拼在一起,总计得到1+20+4=25字节数据:

    address = ecPair.getAddress(); // 返回String地址

    如1PwKkrF366RdTuYsS8KWEbGxfP4bikegcS

    以太坊

    地址是通过对公钥做Keccak-256哈希,然后取最后的40位16进制字符得到的。

    如:0x24602722816b6cad0e143ce9fabf31f6026ec622

    1.2 HD钱包

    BIP39:以mnemonic+用户口令为种子,通过计算后最终得到的64字节钱包种子。

    以太坊

    import Bip39 from 'bip39'
    import util from 'ethereumjs-util'
    import Wallet from 'ethereumjs-wallet'
    var HDKey = require('ethereumjs-wallet/hdkey')
    var _seed = Bip39.generateMnemonic(); 
    console.log("助记词:", _seed)
    var _pass = "123456"  // 这是用户自定义密码PIN
    
    var seedKey = Bip39.mnemonicToSeed(_seed, _pass)
    var hdWallet = HDKey.fromMasterSeed(seedKey)
    var key = hdWallet.derivePath("m/44'/60'/0'/0/" + _index)
    var address = util.pubToAddress(key._hdkey._publicKey, true)
    console.log("私钥:",key._hdkey._privateKey.toString('hex'))
    console.log("公钥:",key._hdkey._publicKey.toString('hex'))
    console.log("地址:",address.toString('hex'))
    

    比特币

    var bitcoin = require('bitcoinjs-lib')
    var bip39 = require('bip39')
    var bip32 = require('bip32')
    
    
    var _seed = bip39.generateMnemonic(); 
    console.log("助记词:", _seed)
    var _pass = "123456"  // 这是用户自定义密码PIN
    
    var seed = bip39.mnemonicToSeed(_seed, _pass)
    var root  = bip32.fromSeed(seed)
    var child0 = root.derivePath("m/44'/0'/0'/0/"+ _index);
    console.log("私钥",child0.privateKey.toString('hex'));
    console.log("公钥",child0.publicKey.toString('hex'));
    
    var seedHex = bip39.mnemonicToSeedHex(_seed, _pass)
    var hroot = bitcoin.HDNode.fromSeedHex(seedHex)
    var hchild0 = hroot.derivePath("m/44'/0'/0'/0/" + _index);
    console.log("地址:",hchild0.getAddress())
    

    1.3 bitcore-lib 操作比特币

    1.3.1 安装

    npm i bitcore-lib
    

    1.3.2 生成测试网地址

    var bitcore = require('bitcore-lib');
    var Networks = bitcore.Networks;
    var PrivateKey = bitcore.PrivateKey;
    // 设置成测试网络
    Networks.defaultNetwork = Networks.testnet;
    var testKey = PrivateKey.fromRandom();
    console.log("private:", testKey.toString());
    var pubKey = testKey.publicKey;
    console.log("public:", pubKey.toString())
    var address = testKey.toAddress();
    console.log('address:', address.toString())
    
    

    输出结果如下:
    console.log("private:", testKey.toString());
    private: 2e61e120df72942abdb3c93fce15ef82b855b7a2f1270707feecb34ff8a7730e
    undefined
    var pubKey = testKey.publicKey;
    undefined
    console.log("public:", pubKey.toString())
    public: 038e2ae27f98b1ff10d4ff658cc846f2260b86123fca26a5edf29a943681a4ab01
    undefined
    var address = testKey.toAddress();
    undefined
    console.log('address:', address.toString())
    address: mwZogrFFZhb8GqTSm4C7WFfSCJKeVovo4k

    对于livenet生成地址如:1KLJV3ocK7w6JXH2f2BdShy2jiuETpTo59

    1.3.3 转账

    用安装引用包

    npm install bitcore-explorers --save
    
    var Insight = require('bitcore-explorers').Insight;
    var insight = new Insight('testnet');
    var bitcore = require('bitcore-lib');
    
    var Networks = bitcore.Networks;
    var PrivateKey = bitcore.PrivateKey;
    // 生成地址
    var privateKey = PrivateKey('2e61e120df72942abdb3c93fce15ef82b855b7a2f1270707feecb34ff8a7730e', 'testnet');
    var address = privateKey.toAddress()
    
    // 目标地址的私钥为:99d3bb48b0b9b3493fce26b05c2302359b4a81b93606af1a149c5c2deb2bca6b
    // 目标地址为:mvWrzyVe1QMCcX3XrMEicXbt81Wd3Un35F
    var address2 = PrivateKey('99d3bb48b0b9b3493fce26b05c2302359b4a81b93606af1a149c5c2deb2bca6b', 'testnet').toAddress();
    
    insight.getUnspentUtxos(address, function(err,utxos){
        if(err){
            console.log(err);
        }else{
            console.log(utxos);
            var tx = bitcore.Transaction();
            tx.from(utxos);
            tx.to(address2, 100000);
            tx.change(address);
            tx.sign(privateKey);
            console.log("transaction:", tx.toObject());
            txs = tx.serialize();
            
            var scriptIn = bitcore.Script(tx.toObject().inputs[0].script);
            console.log('input script string:', scriptIn.toString());
            var scriptOut = bitcore.Script(tx.toObject().outputs[0].script);
            console.log("output script string:", scriptOut.toString());
            
            //tx.addData();
            insight.broadcast(txs, function(err, returnedTxId){
                if (err){
                    console.log(err);
                }else{
                    console.log('successful broadcast:' + returnedTxId)
                }
            });        
        }
    });
    
    

    如果有报告如下类似错误:

    at Object.bitcore.versionGuard (/home/u18/node_modules/bitcore-explorers/node_modules/bitcore-lib/index.js:12:11)

    打开文件index.js
    bitcore.versionGuard = function(version) {
    改为:
    bitcore.versionGuard = function(version) { return;

    最终正确输出如下:

    successful broadcast:1eff85255798bd3a91935912ff8046dc2511902a7fbbd24cf971f59957a8fae4

    这个时候,就可以把这个交易编号拿https://live.blockcypher.com/btc-testnet/上面去查看了

  • 相关阅读:
    2009中国IT界名人
    jQuery简介
    Spring下载地址
    ContextLoaderListener
    MyBatisUtil类
    SSM事务
    后台管理中心跳转问题解决
    mybatis返回boolean值时数据库返回null
    yarn作业提交过程
    Hadoop集群运行wordcount jar包出错
  • 原文地址:https://www.cnblogs.com/freebird92/p/10030761.html
Copyright © 2011-2022 走看看