钱包,简单讲来说它连接区块链的一个入口,用来管理账号和交易。区块链账号其实是指一对密钥,包括一个私钥和一个公钥。私钥是一串字符串,通常是随机选出的。有了私钥,使用非对称加密算法这个单向加密函数产生一个公钥,反之,用公钥是无法得到私钥的。有了公钥,就可以使用一个单向加密哈希函数生成区块链地址。
在比特币中,会先随机数发生器中生成一个私钥,私钥使用椭圆加密算法可以产生一个公钥。在公钥的基础上进行双哈希可以生成一个地址。
地址是用来接收Token(虚拟货币),而密钥对用来产生数字签名和验证交易。方便起见,在本文中将使用RSA算法代替比特币中加密算法。过程如下:
- 随机生成一段字符串作为私钥;
- 私钥经过RSA算法生成公钥;
- 通过公钥在产生地址;
- 用PKCS1_v1_5产生数字签名和验证签名。
In [38]:
# -*- coding: utf-8 -*-
import Crypto
import Crypto.Random
from Crypto.Hash import SHA
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
import binascii
import base58
class Wallet:
"""
钱包
"""
def __init__(self):
random_gen = Crypto.Random.new().read
self._private_key = RSA.generate(1024, random_gen)
self.public_key = self._private_key.publickey()
self._signer = PKCS1_v1_5.new(self._private_key)
@property
def address(self):
"""
通过公钥生成地址
"""
h = SHA.new(self.public_key.exportKey(format='DER'))
return base58.b58encode(h.digest())
def sign(self, message):
"""
生成数字签名
"""
h = SHA.new(message.encode('utf8'))
return binascii.hexlify(self._signer.sign(h)).decode('ascii')
def verify_sign(pubkey, message, signature):
"""
验证签名
"""
verifier = PKCS1_v1_5.new(pubkey)
h = SHA.new(message.encode('utf8'))
return verifier.verify(h, binascii.unhexlify(signature))
In [39]:
# 新建钱包
w1 = Wallet()
# 地址
w1.address
Out[39]:
'2MRNQinFVnC8q3QZ4FkXHfhRh3C3'
In [40]:
# 签名和验证
data = "Hello Blockchain"
sign = w1.sign(data)
if verify_sign(w1.public_key, data, sign):
print('验证成功!')
else:
print('验证失败!')
验证成功!
接下来新建一个界面用来管理钱包,主要代码如下:
In [ ]:
# app.py
@app.route("/wallets", methods=["GET", "POST"])
def wallets():
wallet_list = load_data()
if request.method == "POST":
wallet = Wallet()
wallet_list.append(wallet)
save_data(wallet_list)
return render_template("wallets.html", wallets=wallet_list)
<!-- wallets.html -->
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="text-center">
<div>
<h1>钱包管理工具</h1>
<p>点击下面按钮生成新的钱包</p>
<form method="post">
<button class="btn btn-primary" type="submit">新建钱包</button>
</form>
</div>
<div>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">地址</th>
</tr>
</thead>
<tbody>
{% for i in wallets %}
<tr>
<th scope="row">账号{{ loop.index }}</th>
<td>{{ i.address }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<hr>
<div></div>
</div>
</div>
{% endblock %}
完整代码可以到GitHub(https://github.com/flingjie/blockchain)上查看,效果如下: