【主要内容】
今天继续分析从github上获取的开源代码怎么实现简单区块链的入门知识,共用时间25分钟。
(此外整理作笔记花费了约60分钟)
详细学习过程见文末学习过程屏幕录像。
今天主要继续分析前天断点调试后得到的变量中间值,进而反推执行过程,以注释之前还不理解 的代码部分,发现我学习的难点还在于 密码学部分。
【学习笔记】
一、没有完成理解的私钥签名算法部分:
源代码如下:
def sign_transaction(self):
"""
Sign transaction with private key
"""
ls=binascii.unhexlify(self.sender_private_key)
'''
与hexlify()方法相反,
unhdexlify()方法,
将一个用ascii(其实这里也可能原本是Unicode编码)编码表示 的字符串(我估计此处不一定是byte字符串)
表示为,用十六进制(即字符串本身内容用\x转义表示编码)编码的byte字符串。
此时ls的值是:
b'0\x82\x02]\x02\x01\x00\x02\x81\x81\x00\xbac\xd7\x02\xfc~\x02\xc3\x85sL\xb3\x84n]\x8ds\x19\xab97\xe3\xb5a\r$\xd0\x93\xb0\xd1t\xe4\xe5\xde!\xfe\x9a\x15\xfbagw \x04u\x1b\x13u^\xc6l\xf4\x84\xad\x07\xcb\x12\xf9o\x0c\xea\xa7b\xbaC\xfb\x05H\x86\xad\xd8~\x8a\xc6\xe6\x11\x173\xb3\xa1\xaeY\x91CW\xaeK\xf0\xef\x81\x9d0\x92O\x01\xd5T\xc1p\x0fe>\xa9Q\x12\x07\xb00\xe4OMhKY\xfe\\\xe4Dx\x84Q\xacKH\xd4\x1d\xdd\xf3\x02\x03\x01\x00\x01\x02\x81\x80\x18~\xe8\x92\x0e\xe6\xec\xac\x0f\x8c\xd0\xa6\xc3\x1f\xd2\x11\xb5\xef\xc8\xad\xf3gl\xbd\xfd\x81:\x1c>\xdf\xb82 \xf7\xa9\x96\x11`\x142\x7f\xeb\x8a\xfc\xaa\xfbL\xfa^\xe3K\x0cs\xa7]\xdf\xd5u\x8c\x9f\xb0\xf3 \xa9J\xbc~\xcbA{\xd0\x11+8?\xb1\x96I*5\xc9\x11@\x86$\x90\xce\xaf\xfa\xbf\xc4`\xfc6\xb4r*\xf3P\x857\xd2\xdcl\\\x84\xe1\xb14\xea\x88\x8e\xb8\x04\xa4d?3B\xa6\xaf\xa2Y^\xe0\xce@\x89\x02A\x00\xd8.x\xbbE\xd4\x97\x9c\xc8z\xcd\xf3\xaa\x18*\xf1k\r\x80\x18\xff\xfb\xca\xdf$6^\xe4\xff\x84w\x93\xb9W<\x13et\xee\xba\xeeM{\xc6\xfc^\x97\n\xbf~\xe6C;\x05\xa3\x9bO\x05_;F]\xa0\r\x02A\x00\xdc\xb8\x9e\x82\xf6\x08\xf8\xaf\xba:\xe3/\x1c\x98\xbdz(\xdfi\xe7\xb3\xb8;\xac|\xa0>\xf4\xda\xef\xda\x18@T\xab\x832W\xf94\x88T\xb22]\xc4\x9e\xabH\x86\x0b\xbd-A\xfc\x97bD\xb0d\xa2\xab\xf5\xff\x02A\x00\xd4\x0e\xe9\xf1R3\x931\x81[-q\xaa\xd5\xa02F\xff\xec;\x19\xc7\xc5\x9e\x93\xe8\x1d\xb7\xe6\x89\xeb\xbee\xdd\x93\x99\xb798\x00\xf8G\xdbv;\x13\x12x\xc1\x95\xda\x8b\xf2v\xba\xa1[\xa7z^+\xcd%u\x02A\x00\x8dv\x19\xc9\x8f\x8crn\x95\xe9\xf5\xff\x14\xd1\xe3\xe6nY\xba\x13\x91@\xcb\xa6!\xfd\xc6;\xc22%R\x93\xb0pxV\x84\xc1\xa8d\x93\xfb\xdd\x81\xf1iL\x17\xe0)\x97\xe6p\xbbE\xfe\xeaM/B~\xf9\xdb\x02@4.o4\xd4(\xb7C\x8d\xa3\x0f\xe0\x80\xcc\xd8\x14\x03\xc2\xf9\xa8A1B\xcb\xe1p\x8bk:\xfe\x0fE\xe6@\x19/\x0f\xbc\x86\xd1\xda-\xc4\x04\xca\xaf\x7f\x923\x1fJz\x02kD\x02*\xf7&\xbe9!\xa5\xf9'
'''
private_key = RSA.importKey(ls) #对发送者的私钥进行处理
#RSA.importKey方法导入标准格式编码的RSA密钥(公共或私有半密钥【什么叫私有半密钥,这是机器 翻译的。】)。
'''
现在private_key的值的描述如下:
RsaKey(n=130887508839744775363828489292492942444463434346971086658287181395248393849272716452901010865933107018951332471959936992676702744651630598299834435409087847044817115913438678900174924682299501670221020517043795850861688069799360443152949010476579188812260442594535889700621204848910086446699487189153307549171, e=65537, d=17201490969020885152030986744529681146133688756434715800049246888891380689134167063015341052966749328688036171643360808671810438983848731909554511072805795649945207662156234769699660635030358600038497835440405622733641149446902066966647182765150369696363815548406661407019882811271534070582519070030369276041, p=11322345423620747756358608825813006396534468076628379449281718497918962244676729732525986825607491134689178650194810855403918488894622671601159574317277197, q=11560105609098132329937153390284829548701209459314037867607446378353402816362871241978872702637539563535884720320614616368699804388342805715787783993030143, u=8769754763737200992798546201632006230482985591385219415794498461221610682090347455858465717896322624555845424913806144911132535297210576548414324318453089)
_d:Integer(17201490969020885152030986744529681146133688756434715800049246888891380689134167063015341052966749328688036171643360808671810438983848731909554511072805795649945207662156234769699660635030358600038497835440405622733641149446902066966647182765150369696363815548406661407019882811271534070582519070030369276041)
_e:Integer(65537)
_n:Integer(130887508839744775363828489292492942444463434346971086658287181395248393849272716452901010865933107018951332471959936992676702744651630598299834435409087847044817115913438678900174924682299501670221020517043795850861688069799360443152949010476579188812260442594535889700621204848910086446699487189153307549171)
_p:Integer(11322345423620747756358608825813006396534468076628379449281718497918962244676729732525986825607491134689178650194810855403918488894622671601159574317277197)
_q:Integer(11560105609098132329937153390284829548701209459314037867607446378353402816362871241978872702637539563535884720320614616368699804388342805715787783993030143)
_u:Integer(8769754763737200992798546201632006230482985591385219415794498461221610682090347455858465717896322624555845424913806144911132535297210576548414324318453089)
d:17201490969020885152030986744529681146133688756434715800049246888891380689134167063015341052966749328688036171643360808671810438983848731909554511072805795649945207662156234769699660635030358600038497835440405622733641149446902066966647182765150369696363815548406661407019882811271534070582519070030369276041
e:65537
n:130887508839744775363828489292492942444463434346971086658287181395248393849272716452901010865933107018951332471959936992676702744651630598299834435409087847044817115913438678900174924682299501670221020517043795850861688069799360443152949010476579188812260442594535889700621204848910086446699487189153307549171
p:11322345423620747756358608825813006396534468076628379449281718497918962244676729732525986825607491134689178650194810855403918488894622671601159574317277197
q:11560105609098132329937153390284829548701209459314037867607446378353402816362871241978872702637539563535884720320614616368699804388342805715787783993030143
u:8769754763737200992798546201632006230482
'''
signer = PKCS1_v1_5.new(private_key) #通过发送者的私钥来计算出发送者要添加到改善信息中的私钥的数字签名信息
#--这儿使用了Crypto.Signature子库中的一种填充方法:PKCS1_v1_5(另有一种填充方法:PKCS1_OAEP)
#通过PKCS1_v1_5.new方法将发送者的私钥填充为(此处应当是签名)
#此处 原来的 Private_key被进行了处理,得到一个可以签名的对象:signer
'''
现在signer的值的描述如下 :(此时是不是已经完成了签名?)
<Crypto.Signature.pkcs1_15.PKCS115_SigScheme object at 0x000001DFFFBB5898>
_key:RsaKey(n=130887508839744775363828489292492942444463434346971086658287181395248393849272716452901010865933107018951332471959936992676702744651630598299834435409087847044817115913438678900174924682299501670221020517043795850861688069799360443152949010476579188812260442594535889700621204848910086446699487189153307549171, e=65537, d=17201490969020885152030986744529681146133688756434715800049246888891380689134167063015341052966749328688036171643360808671810438983848731909554511072805795649945207662156234769699660635030358600038497835440405622733641149446902066966647182765150369696363815548406661407019882811271534070582519070030369276041, p=11322345423620747756358608825813006396534468076628379449281718497918962244676729732525986825607491134689178650194810855403918488894622671601159574317277197, q=11560105609098132329937153390284829548701209459314037867607446378353402816362871241978872702637539563535884720320614616368699804388342805715787783993030143, u=876975476373720099279854620163200623048298559138521941579449846...
_verify:<bound method PKCS115_SigScheme.verify of <Crypto.Signature.pkcs1_15.PKCS115_SigScheme object at 0x000001DFFFBB5898>>
verify:<bound method _pycrypto_verify of <
'''
ls2=str(self.to_dict()).encode('utf8') #把当前的交易信息先字符串化然后转换为utf8编码
'''
ls2中现在包含了本次交易信息的全部内容,并以utf8格式编码,内容如下:
<Crypto.Signature.pkcs1_15.PKCS115_SigScheme object at 0x000001DFFFBB5898>
_key:RsaKey(n=130887508839744775363828489292492942444463434346971086658287181395248393849272716452901010865933107018951332471959936992676702744651630598299834435409087847044817115913438678900174924682299501670221020517043795850861688069799360443152949010476579188812260442594535889700621204848910086446699487189153307549171, e=65537, d=17201490969020885152030986744529681146133688756434715800049246888891380689134167063015341052966749328688036171643360808671810438983848731909554511072805795649945207662156234769699660635030358600038497835440405622733641149446902066966647182765150369696363815548406661407019882811271534070582519070030369276041, p=11322345423620747756358608825813006396534468076628379449281718497918962244676729732525986825607491134689178650194810855403918488894622671601159574317277197, q=11560105609098132329937153390284829548701209459314037867607446378353402816362871241978872702637539563535884720320614616368699804388342805715787783993030143, u=876975476373720099279854620163200623048298559138521941579449846...
_verify:<bound method PKCS115_SigScheme.verify of <Crypto.Signature.pkcs1_15.PKCS115_SigScheme object at 0x000001DFFFBB5898>>
verify:<bound method _pycrypto_verify of <
感觉为什么会是一样的?有没有可能在前天逐步调试时复制出错?
'''
h = SHA.new(ls2)
'''
现在h值的描述如下:
<Crypto.Hash.SHA1.SHA1Hash object at 0x000001DFFDD483C8>
_state:<Crypto.Util._raw_api.SmartPointer object at 0x000001DFFE82C128>
block_size:64
digest_size:20
oid:'1.3.14.3.2.26'
'''
ls3=binascii.hexlify(signer.sign(h))
'''
signer是前面得到的可以执行的签名对象。
执行sign()方法将新的一个hash值h与私钥混合得到签名后的字符串?
signer.sign(h)这才是在执行真正的签名过程?
binascii.hexlify()方法将此结果转换成ascii编码的byteE字符中
现在的ls3是用ascii编码的byte字符串,所以下一句又将其还原为unicode编码的
结果如下:
b'1d2358b76ba1eeeef12efefee609626e985880b76be7044ca0dc8ad5563408d330ddbb37d6d864184657f61bd8b336ff6ac87c1b602907c624fcebc8f2837cdf15c723d7dbbb102c5bbe61c822b9f2d8ec622743d6bac46d623ad8aa7f78cd55d22127312b4d758656ee86506e0fcdf13b4c2c7dda34e954efc18bd84f95ee06'
'''
ls4=ls3.decode('ascii')
'''
现在ls4的结果 :
'1d2358b76ba1eeeef12efefee609626e985880b76be7044ca0dc8ad5563408d330ddbb37d6d864184657f61bd8b336ff6ac87c1b602907c624fcebc8f2837cdf15c723d7dbbb102c5bbe61c822b9f2d8ec622743d6bac46d623ad8aa7f78cd55d22127312b4d758656ee86506e0fcdf13b4c2c7dda34e954efc18bd84f95ee06'
'''
return ls4 #这是添加有签名信息的要广播给区块链网络的信息
然后此部分算法得到的结果会在发送者(一个节点的使用者)发送交易请求信息时作为交易信息的字典的:'signature' 对应的key的值被发送出去。
当然由于我缺少基本的密码学知识,所以这部分还没有完全理解。恳请高手指导。
根据以上代码——
我目前所知的使用发送者私钥签名的流程如下:
第一步:对发送者的私钥进行处理,这使用了RSA.importKey()方法,但我不知道具体做了什么。
第二步:通过发送者私钥得到一个signer对象(这个对象我也不甚了了),使用了
PKCS1_v1_5.new(private_key)方法进行填充。
第三步:把完整的交易信息先转换成字符串,然后使用SHA.new()方法生成一个新的hash字符串(我不确定是不是字符串,研究不够透彻)。
第四步:使用前面的signer对象的sign()方法来将新的hash字符串混合(这就是签名的过程?)
第五步:转换编码后,得到签名信息。
三、对【blockchain_client.py】页面的补充注释:
【blockchain_client.py】客户端页面
```
'''
title : blockchain_client.py
description : A blockchain client implemenation, with the following features
- Wallets generation using Public/Private key encryption (based on RSA algorithm)
- Generation of transactions with RSA encryption
author : Adil Moujahid
date_created : 20180212
date_modified : 20180309
version : 0.3
usage : python blockchain_client.py
python blockchain_client.py -p 8080
python blockchain_client.py --port 8080
python_version : 3.6.1
Comments : Wallet generation and transaction signature is based on [1]
References : [1] https://github.com/julienr/ipynb_playground/blob/master/bitcoin/dumbcoin/dumbcoin.ipynb
'''
from collections import OrderedDict
import binascii
import Crypto
import Crypto.Random
from Crypto.Hash import SHA
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
import requests
from flask import Flask, jsonify, request, render_template
class Transaction:
def __init__(self, sender_address, sender_private_key, recipient_address, value):
self.sender_address = sender_address
self.sender_private_key = sender_private_key
self.recipient_address = recipient_address
self.value = value
def __getattr__(self, attr):
return self.data[attr]
def to_dict(self):
return OrderedDict({'sender_address': self.sender_address,
'recipient_address': self.recipient_address,
'value': self.value})
def sign_transaction(self):
"""
Sign transaction with private key
"""
ls=binascii.unhexlify(self.sender_private_key)
'''
与hexlify()方法相反,
unhdexlify()方法,
将一个用ascii(其实这里也可能原本是Unicode编码)编码表示 的字符串(我估计此处不一定是byte字符串)
表示为,用十六进制(即字符串本身内容用\x转义表示编码)编码的byte字符串。
此时ls的值是:
b'0\x82\x02]\x02\x01\x00\x02\x81\x81\x00\xbac\xd7\x02\xfc~\x02\xc3\x85sL\xb3\x84n]\x8ds\x19\xab97\xe3\xb5a\r$\xd0\x93\xb0\xd1t\xe4\xe5\xde!\xfe\x9a\x15\xfbagw \x04u\x1b\x13u^\xc6l\xf4\x84\xad\x07\xcb\x12\xf9o\x0c\xea\xa7b\xbaC\xfb\x05H\x86\xad\xd8~\x8a\xc6\xe6\x11\x173\xb3\xa1\xaeY\x91CW\xaeK\xf0\xef\x81\x9d0\x92O\x01\xd5T\xc1p\x0fe>\xa9Q\x12\x07\xb00\xe4OMhKY\xfe\\\xe4Dx\x84Q\xacKH\xd4\x1d\xdd\xf3\x02\x03\x01\x00\x01\x02\x81\x80\x18~\xe8\x92\x0e\xe6\xec\xac\x0f\x8c\xd0\xa6\xc3\x1f\xd2\x11\xb5\xef\xc8\xad\xf3gl\xbd\xfd\x81:\x1c>\xdf\xb82 \xf7\xa9\x96\x11`\x142\x7f\xeb\x8a\xfc\xaa\xfbL\xfa^\xe3K\x0cs\xa7]\xdf\xd5u\x8c\x9f\xb0\xf3 \xa9J\xbc~\xcbA{\xd0\x11+8?\xb1\x96I*5\xc9\x11@\x86$\x90\xce\xaf\xfa\xbf\xc4`\xfc6\xb4r*\xf3P\x857\xd2\xdcl\\\x84\xe1\xb14\xea\x88\x8e\xb8\x04\xa4d?3B\xa6\xaf\xa2Y^\xe0\xce@\x89\x02A\x00\xd8.x\xbbE\xd4\x97\x9c\xc8z\xcd\xf3\xaa\x18*\xf1k\r\x80\x18\xff\xfb\xca\xdf$6^\xe4\xff\x84w\x93\xb9W<\x13et\xee\xba\xeeM{\xc6\xfc^\x97\n\xbf~\xe6C;\x05\xa3\x9bO\x05_;F]\xa0\r\x02A\x00\xdc\xb8\x9e\x82\xf6\x08\xf8\xaf\xba:\xe3/\x1c\x98\xbdz(\xdfi\xe7\xb3\xb8;\xac|\xa0>\xf4\xda\xef\xda\x18@T\xab\x832W\xf94\x88T\xb22]\xc4\x9e\xabH\x86\x0b\xbd-A\xfc\x97bD\xb0d\xa2\xab\xf5\xff\x02A\x00\xd4\x0e\xe9\xf1R3\x931\x81[-q\xaa\xd5\xa02F\xff\xec;\x19\xc7\xc5\x9e\x93\xe8\x1d\xb7\xe6\x89\xeb\xbee\xdd\x93\x99\xb798\x00\xf8G\xdbv;\x13\x12x\xc1\x95\xda\x8b\xf2v\xba\xa1[\xa7z^+\xcd%u\x02A\x00\x8dv\x19\xc9\x8f\x8crn\x95\xe9\xf5\xff\x14\xd1\xe3\xe6nY\xba\x13\x91@\xcb\xa6!\xfd\xc6;\xc22%R\x93\xb0pxV\x84\xc1\xa8d\x93\xfb\xdd\x81\xf1iL\x17\xe0)\x97\xe6p\xbbE\xfe\xeaM/B~\xf9\xdb\x02@4.o4\xd4(\xb7C\x8d\xa3\x0f\xe0\x80\xcc\xd8\x14\x03\xc2\xf9\xa8A1B\xcb\xe1p\x8bk:\xfe\x0fE\xe6@\x19/\x0f\xbc\x86\xd1\xda-\xc4\x04\xca\xaf\x7f\x923\x1fJz\x02kD\x02*\xf7&\xbe9!\xa5\xf9'
'''
private_key = RSA.importKey(ls) #对发送者的私钥进行处理
#RSA.importKey方法导入标准格式编码的RSA密钥(公共或私有半密钥【什么叫私有半密钥,这是机器 翻译的。】)。
'''
现在private_key的值的描述如下:
RsaKey(n=130887508839744775363828489292492942444463434346971086658287181395248393849272716452901010865933107018951332471959936992676702744651630598299834435409087847044817115913438678900174924682299501670221020517043795850861688069799360443152949010476579188812260442594535889700621204848910086446699487189153307549171, e=65537, d=17201490969020885152030986744529681146133688756434715800049246888891380689134167063015341052966749328688036171643360808671810438983848731909554511072805795649945207662156234769699660635030358600038497835440405622733641149446902066966647182765150369696363815548406661407019882811271534070582519070030369276041, p=11322345423620747756358608825813006396534468076628379449281718497918962244676729732525986825607491134689178650194810855403918488894622671601159574317277197, q=11560105609098132329937153390284829548701209459314037867607446378353402816362871241978872702637539563535884720320614616368699804388342805715787783993030143, u=8769754763737200992798546201632006230482985591385219415794498461221610682090347455858465717896322624555845424913806144911132535297210576548414324318453089)
_d:Integer(17201490969020885152030986744529681146133688756434715800049246888891380689134167063015341052966749328688036171643360808671810438983848731909554511072805795649945207662156234769699660635030358600038497835440405622733641149446902066966647182765150369696363815548406661407019882811271534070582519070030369276041)
_e:Integer(65537)
_n:Integer(130887508839744775363828489292492942444463434346971086658287181395248393849272716452901010865933107018951332471959936992676702744651630598299834435409087847044817115913438678900174924682299501670221020517043795850861688069799360443152949010476579188812260442594535889700621204848910086446699487189153307549171)
_p:Integer(11322345423620747756358608825813006396534468076628379449281718497918962244676729732525986825607491134689178650194810855403918488894622671601159574317277197)
_q:Integer(11560105609098132329937153390284829548701209459314037867607446378353402816362871241978872702637539563535884720320614616368699804388342805715787783993030143)
_u:Integer(8769754763737200992798546201632006230482985591385219415794498461221610682090347455858465717896322624555845424913806144911132535297210576548414324318453089)
d:17201490969020885152030986744529681146133688756434715800049246888891380689134167063015341052966749328688036171643360808671810438983848731909554511072805795649945207662156234769699660635030358600038497835440405622733641149446902066966647182765150369696363815548406661407019882811271534070582519070030369276041
e:65537
n:130887508839744775363828489292492942444463434346971086658287181395248393849272716452901010865933107018951332471959936992676702744651630598299834435409087847044817115913438678900174924682299501670221020517043795850861688069799360443152949010476579188812260442594535889700621204848910086446699487189153307549171
p:11322345423620747756358608825813006396534468076628379449281718497918962244676729732525986825607491134689178650194810855403918488894622671601159574317277197
q:11560105609098132329937153390284829548701209459314037867607446378353402816362871241978872702637539563535884720320614616368699804388342805715787783993030143
u:8769754763737200992798546201632006230482
'''
signer = PKCS1_v1_5.new(private_key) #通过发送者的私钥来计算出发送者要添加到改善信息中的私钥的数字签名信息
#--这儿使用了Crypto.Signature子库中的一种填充方法:PKCS1_v1_5(另有一种填充方法:PKCS1_OAEP)
#通过PKCS1_v1_5.new方法将发送者的私钥填充为(此处应当是签名)
#此处 原来的 Private_key被进行了处理,得到一个可以签名的对象:signer
'''
现在signer的值的描述如下 :(此时是不是已经完成了签名?)
<Crypto.Signature.pkcs1_15.PKCS115_SigScheme object at 0x000001DFFFBB5898>
_key:RsaKey(n=130887508839744775363828489292492942444463434346971086658287181395248393849272716452901010865933107018951332471959936992676702744651630598299834435409087847044817115913438678900174924682299501670221020517043795850861688069799360443152949010476579188812260442594535889700621204848910086446699487189153307549171, e=65537, d=17201490969020885152030986744529681146133688756434715800049246888891380689134167063015341052966749328688036171643360808671810438983848731909554511072805795649945207662156234769699660635030358600038497835440405622733641149446902066966647182765150369696363815548406661407019882811271534070582519070030369276041, p=11322345423620747756358608825813006396534468076628379449281718497918962244676729732525986825607491134689178650194810855403918488894622671601159574317277197, q=11560105609098132329937153390284829548701209459314037867607446378353402816362871241978872702637539563535884720320614616368699804388342805715787783993030143, u=876975476373720099279854620163200623048298559138521941579449846...
_verify:<bound method PKCS115_SigScheme.verify of <Crypto.Signature.pkcs1_15.PKCS115_SigScheme object at 0x000001DFFFBB5898>>
verify:<bound method _pycrypto_verify of <
'''
ls2=str(self.to_dict()).encode('utf8') #把当前的交易信息先字符串化然后转换为utf8编码
'''
ls2中现在包含了本次交易信息的全部内容,并以utf8格式编码,内容如下:
<Crypto.Signature.pkcs1_15.PKCS115_SigScheme object at 0x000001DFFFBB5898>
_key:RsaKey(n=130887508839744775363828489292492942444463434346971086658287181395248393849272716452901010865933107018951332471959936992676702744651630598299834435409087847044817115913438678900174924682299501670221020517043795850861688069799360443152949010476579188812260442594535889700621204848910086446699487189153307549171, e=65537, d=17201490969020885152030986744529681146133688756434715800049246888891380689134167063015341052966749328688036171643360808671810438983848731909554511072805795649945207662156234769699660635030358600038497835440405622733641149446902066966647182765150369696363815548406661407019882811271534070582519070030369276041, p=11322345423620747756358608825813006396534468076628379449281718497918962244676729732525986825607491134689178650194810855403918488894622671601159574317277197, q=11560105609098132329937153390284829548701209459314037867607446378353402816362871241978872702637539563535884720320614616368699804388342805715787783993030143, u=876975476373720099279854620163200623048298559138521941579449846...
_verify:<bound method PKCS115_SigScheme.verify of <Crypto.Signature.pkcs1_15.PKCS115_SigScheme object at 0x000001DFFFBB5898>>
verify:<bound method _pycrypto_verify of <
感觉为什么会是一样的?有没有可能在前天逐步调试时复制出错?
'''
h = SHA.new(ls2)
'''
现在h值的描述如下:
<Crypto.Hash.SHA1.SHA1Hash object at 0x000001DFFDD483C8>
_state:<Crypto.Util._raw_api.SmartPointer object at 0x000001DFFE82C128>
block_size:64
digest_size:20
oid:'1.3.14.3.2.26'
'''
ls3=binascii.hexlify(signer.sign(h))
'''
signer是前面得到的可以执行的签名对象。
执行sign()方法将新的一个hash值h与私钥混合得到签名后的字符串?
signer.sign(h)这才是在执行真正的签名过程?
binascii.hexlify()方法将此结果转换成ascii编码的byteE字符中
现在的ls3是用ascii编码的byte字符串,所以下一句又将其还原为unicode编码的
结果如下:
b'1d2358b76ba1eeeef12efefee609626e985880b76be7044ca0dc8ad5563408d330ddbb37d6d864184657f61bd8b336ff6ac87c1b602907c624fcebc8f2837cdf15c723d7dbbb102c5bbe61c822b9f2d8ec622743d6bac46d623ad8aa7f78cd55d22127312b4d758656ee86506e0fcdf13b4c2c7dda34e954efc18bd84f95ee06'
'''
ls4=ls3.decode('ascii')
'''
现在ls4的结果 :
'1d2358b76ba1eeeef12efefee609626e985880b76be7044ca0dc8ad5563408d330ddbb37d6d864184657f61bd8b336ff6ac87c1b602907c624fcebc8f2837cdf15c723d7dbbb102c5bbe61c822b9f2d8ec622743d6bac46d623ad8aa7f78cd55d22127312b4d758656ee86506e0fcdf13b4c2c7dda34e954efc18bd84f95ee06'
'''
return ls4 #这是添加有签名信息的要广播给区块链网络的信息
app = Flask(__name__)
@app.route('/') #这儿将index.html文件的展示目录指定为虚拟web服务器的根目录
def index():
return render_template('./index.html')
@app.route('/make/transaction') #这儿将make_transaction.html文件的展示目录指定为虚拟web服务器的make一级目录下的transaction子目录
def make_transaction():
return render_template('./make_transaction.html')
@app.route('/view/transactions') #这儿将view_transactions.html文件的展示目录指定为虚拟web服务器的view一级目录下的transactions子目录
def view_transaction():
return render_template('./view_transactions.html')
@app.route('/wallet/new', methods=['GET'])
def new_wallet():
random_gen = Crypto.Random.new().read #得到随机字符串
'''
Crypto.Random.new().read调用了系统 os.urandom()函数,其解释如下:
来自博文:https://blog.****.net/a19990412/article/details/80934268
os.urandom(n)函数在python官方文档中做出了这样的解释
函数定位: Return a string of n random bytes suitable for cryptographic use.
意思就是,返回一个有n个byte那么长的一个string,然后很适合用于加密。
然后这个函数,在文档中,被归结于os这个库的Miscellaneous Functions,意思是不同种类的函数(也可以说是混种函数)
原因是: This function returns random bytes from an OS-specific randomness source. (函数返回的随机字节是根据不同的操作系统特定的随机函数资源。即,这个函数是调用OS内部自带的随机函数的。有特异性)
然后一开始的那个 u 其实我是以为是uniform(表示正态分布的),后来我发现文档中有这样的一句:The returned data should be unpredictable enough for cryptographic applications。
注意到这个 unpredictable, 再结合之前所说的根据os底层来实现的,所以,u 应该是表示难以预料的意思。
'''
private_key = RSA.generate(1024, random_gen) #从随机字符串生成私钥
public_key = private_key.publickey() #从私钥生成对应成对的公钥(即公钥和私钥之间是有对应关系的)
ls=private_key.exportKey(format='DER')
'''
执行exportkey算法后,编码变成了byte字符串,
bytes字符串的组成形式,必须是十六进制数,或者ASCII字符:
此时是用 十六进 制来表示字符串的,因为\x这个转义字符转义的就是十六进制编码
b'0\x82\x02]\x02\x01\x00\x02\x81\x81\x00\xbac\xd7\x02\xfc~\x02\xc3\x85sL\xb3\x84n]\x8ds\x19\xab97\xe3\xb5a\r$\xd0\x93\xb0\xd1t\xe4\xe5\xde!\xfe\x9a\x15\xfbagw \x04u\x1b\x13u^\xc6l\xf4\x84\xad\x07\xcb\x12\xf9o\x0c\xea\xa7b\xbaC\xfb\x05H\x86\xad\xd8~\x8a\xc6\xe6\x11\x173\xb3\xa1\xaeY\x91CW\xaeK\xf0\xef\x81\x9d0\x92O\x01\xd5T\xc1p\x0fe>\xa9Q\x12\x07\xb00\xe4OMhKY\xfe\\\xe4Dx\x84Q\xacKH\xd4\x1d\xdd\xf3\x02\x03\x01\x00\x01\x02\x81\x80\x18~\xe8\x92\x0e\xe6\xec\xac\x0f\x8c\xd0\xa6\xc3\x1f\xd2\x11\xb5\xef\xc8\xad\xf3gl\xbd\xfd\x81:\x1c>\xdf\xb82 \xf7\xa9\x96\x11`\x142\x7f\xeb\x8a\xfc\xaa\xfbL\xfa^\xe3K\x0cs\xa7]\xdf\xd5u\x8c\x9f\xb0\xf3 \xa9J\xbc~\xcbA{\xd0\x11+8?\xb1\x96I*5\xc9\x11@\x86$\x90\xce\xaf\xfa\xbf\xc4`\xfc6\xb4r*\xf3P\x857\xd2\xdcl\\\x84\xe1\xb14\xea\x88\x8e\xb8\x04\xa4d?3B\xa6\xaf\xa2Y^\xe0\xce@\x89\x02A\x00\xd8.x\xbbE\xd4\x97\x9c\xc8z\xcd\xf3\xaa\x18*\xf1k\r\x80\x18\xff\xfb\xca\xdf$6^\xe4\xff\x84w\x93\xb9W<\x13et\xee\xba\xeeM{\xc6\xfc^\x97\n\xbf~\xe6C;\x05\xa3\x9bO\x05_;F]\xa0\r\x02A\x00\xdc\xb8\x9e\x82\xf6\x08\xf8\xaf\xba:\xe3/\x1c\x98\xbdz(\xdfi\xe7\xb3\xb8;\xac|\xa0>\xf4\xda\xef\xda\x18@T\xab\x832W\xf94\x88T\xb22]\xc4\x9e\xabH\x86\x0b\xbd-A\xfc\x97bD\xb0d\xa2\xab\xf5\xff\x02A\x00\xd4\x0e\xe9\xf1R3\x931\x81[-q\xaa\xd5\xa02F\xff\xec;\x19\xc7\xc5\x9e\x93\xe8\x1d\xb7\xe6\x89\xeb\xbee\xdd\x93\x99\xb798\x00\xf8G\xdbv;\x13\x12x\xc1\x95\xda\x8b\xf2v\xba\xa1[\xa7z^+\xcd%u\x02A\x00\x8dv\x19\xc9\x8f\x8crn\x95\xe9\xf5\xff\x14\xd1\xe3\xe6nY\xba\x13\x91@\xcb\xa6!\xfd\xc6;\xc22%R\x93\xb0pxV\x84\xc1\xa8d\x93\xfb\xdd\x81\xf1iL\x17\xe0)\x97\xe6p\xbbE\xfe\xeaM/B~\xf9\xdb\x02@4.o4\xd4(\xb7C\x8d\xa3\x0f\xe0\x80\xcc\xd8\x14\x03\xc2\xf9\xa8A1B\xcb\xe1p\x8bk:\xfe\x0fE\xe6@\x19/\x0f\xbc\x86\xd1\xda-\xc4\x04\xca\xaf\x7f\x923\x1fJz\x02kD\x02*\xf7&\xbe9!\xa5\xf9'
'''
ls2=binascii.hexlify(ls)
'''
hexlify()方法将上面用十六进制表示的字符编码,又换成了用ASCII字符表示的字符编码,仍然是byte字符串
结果如下:
b'3082025d02010002818100ba63d702fc7e02c385734cb3846e5d8d7319ab3937e3b5610d24d093b0d174e4e5de21fe9a15fb6167772004751b13755ec66cf484ad07cb12f96f0ceaa762ba43fb054886add87e8ac6e6111733b3a1ae59914357ae4bf0ef819d30924f01d554c1700f653ea9511207b030e44f4d684b59fe5ce444788451ac4b48d41dddf30203010001028180187ee8920ee6ecac0f8cd0a6c31fd211b5efc8adf3676cbdfd813a1c3edfb83220f7a996116014327feb8afcaafb4cfa5ee34b0c73a75ddfd5758c9fb0f320a94abc7ecb417bd0112b383fb196492a35c91140862490ceaffabfc460fc36b4722af3508537d2dc6c5c84e1b134ea888eb804a4643f3342a6afa2595ee0ce4089024100d82e78bb45d4979cc87acdf3aa182af16b0d8018fffbcadf24365ee4ff847793b9573c136574eebaee4d7bc6fc5e970abf7ee6433b05a39b4f055f3b465da00d024100dcb89e82f608f8afba3ae32f1c98bd7a28df69e7b3b83bac7ca03ef4daefda184054ab833257f9348854b2325dc49eab48860bbd2d41fc976244b064a2abf5ff024100d40ee9f152339331815b2d71aad5a03246ffec3b19c7c59e93e81db7e689ebbe65dd9399b7393800f847db763b131278c195da8bf276baa15ba77a5e2bcd25750241008d7619c98f8c726e95e9f5ff14d1e3e66e59ba139140cba621fdc63bc232255293b070785684c1a86493fbdd81f1694c17e02997e670bb45feea4d2f427ef9db0240342e6f34d428b7438da30fe080ccd81403c2f9a8413142cbe1708b6b3afe0f45e640192f0fbc86d1da2dc404caaf7f92331f4a7a026b44022af726be3921a5f9'
'''
ls3=ls2.decode('ascii')
'''
参见博文:https://blog.****.net/qq_40134903/article/details/80710882
decode(原字符串编码格式描述)
是将字符串从字符串的原编码格式转换成 unicode 编码。
在ls2.decode('ascii')这一句中,是将字符串ls2从ascii编码格式转换为:unicode编码。
现在ls3的值如下:(不再是byte字符串)
'3082025d02010002818100ba63d702fc7e02c385734cb3846e5d8d7319ab3937e3b5610d24d093b0d174e4e5de21fe9a15fb6167772004751b13755ec66cf484ad07cb12f96f0ceaa762ba43fb054886add87e8ac6e6111733b3a1ae59914357ae4bf0ef819d30924f01d554c1700f653ea9511207b030e44f4d684b59fe5ce444788451ac4b48d41dddf30203010001028180187ee8920ee6ecac0f8cd0a6c31fd211b5efc8adf3676cbdfd813a1c3edfb83220f7a996116014327feb8afcaafb4cfa5ee34b0c73a75ddfd5758c9fb0f320a94abc7ecb417bd0112b383fb196492a35c91140862490ceaffabfc460fc36b4722af3508537d2dc6c5c84e1b134ea888eb804a4643f3342a6afa2595ee0ce4089024100d82e78bb45d4979cc87acdf3aa182af16b0d8018fffbcadf24365ee4ff847793b9573c136574eebaee4d7bc6fc5e970abf7ee6433b05a39b4f055f3b465da00d024100dcb89e82f608f8afba3ae32f1c98bd7a28df69e7b3b83bac7ca03ef4daefda184054ab833257f9348854b2325dc49eab48860bbd2d41fc976244b064a2abf5ff024100d40ee9f152339331815b2d71aad5a03246ffec3b19c7c59e93e81db7e689ebbe65dd9399b7393800f847db763b131278c195da8bf276baa15ba77a5e2bcd25750241008d7619c98f8c726e95e9f5ff14d1e3e66e59ba139140cba621fdc63bc232255293b070785684c1a86493fbdd81f1694c17e02997e670bb45feea4d2f427ef9db0240342e6f34d428b7438da30fe080ccd81403c2f9a8413142cbe1708b6b3afe0f45e640192f0fbc86d1da2dc404caaf7f92331f4a7a026b44022af726be3921a5f9'
这时目测与byte字符串的内容本身没有区别。
'''
#----------------------
ls4=public_key.exportKey(format='DER')
ls5=binascii.hexlify(ls4)
ls6=ls5.decode('ascii')
response = {
'private_key': ls3,
'public_key': ls6
}
return jsonify(response), 200
@app.route('/generate/transaction', methods=['POST'])
def generate_transaction():
sender_address = request.form['sender_address'] #从客户端post过来的参数中,获取发送者用户公钥
sender_private_key = request.form['sender_private_key'] #从客户端post过来的参数中,获取发送者用户私钥
recipient_address = request.form['recipient_address'] #从客户端post过来的参数中,获取接收者用户公钥
value = request.form['amount'] #从客户端post过来的参数中,获取本次交易要发送的代币数量
#下一行代码生成一个transaction类的实例 对象
transaction = Transaction(sender_address, sender_private_key, recipient_address, value)
response = {'transaction': transaction.to_dict(), 'signature': transaction.sign_transaction()}
# 将广播一次交易的所有信息(发送者私钥除外)封装为字典 #这是添加发送者的私钥的签名信息
return jsonify(response), 200
if __name__ == '__main__':
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument('-p', '--port', default=80, type=int, help='port to listen on')
args = parser.parse_args()
port = args.port
app.run(host='127.0.0.1', port=port)
```
【学习后记】
我想说密码学才是人类最伟大的壮举,简直搞得人云里雾里~~~~
进而我又想到,既然密码学可以弄得如此庞杂,那么根据宇宙信息理论,整个宇宙会不会只是一个加密的信息存储器呢?这其中的万事万物都是加密后的信息的一部分,甚至其实现在这些信息还在不停地被运算着呢?
为了追赶未来,终身学习,终身进步,我创建了【就是要学 终身成长】社群,欢迎立志于终身学习,终身成长的朋友们加入,共同交流学习。Qq群号码:646854445
或访问:www.941xue.com
【关于坚持自学的例行说明】
最后例行说明下,我为什么要坚持自学。
一、为什么一把年纪还在学习
放弃很多去聚餐,去HI歌,去游玩,去看电影,去追剧……的时间,然后进行着这个年纪似乎已不应当再进行的学习,引来身边人们无尽的不解与鄙夷甚至可怜……
但我不想放弃终身学习的誓言。
因为——
我对我今天的生活现状并不认同!
罗伯特清崎告诉过我们,反省自己当下的生活是不是自己想要的,这难道不是最好的动力与答案?
走过了大半生,然后才发现曾经、当下所正在进行的人生并不是自己想要的,那是一种怎样的体验?
只有心中真切的感受才能回答这个问题,而任凭再丰富的语言也是无法描绘出来的。
经历半生的跋涉,却发现走得并不正确,有多少人有勇气承认自己过去的一切都是错误的呢?
而我愿意告诉过去的我:“你错了!”
那么已经历半生错误,年岁之大又压于头顶,还有希望从这架的*的半端重新爬下,再蹒跚着爬上另一架*吗?
我宁愿相信还有希望!
这便是我为什么要继续坚持终身学习下去的全部理由。
二、这个年纪还在学这些技术有意义吗
纯的技术对这把年纪其实已没有意义。
但兴趣可以超越意义。
但技术可以引来思想的变革,这才是意义。
投资自己的头脑 ,改革自己的思想,这是最保值,更长远的投资,过去我从来没有投资过,错过太多,那就从投资自己头脑开始吧。
罗伯特清崎告诉我们,真正的富有是时间的富有;真正的*是可以决定自己愿意做什么的*。
因为我愿意做我兴趣所在的事,所以我希望我有*选择的那一天,虽然今天离那一天可能还是那么遥远,但我愿意相信,每天多赶几步,离希望就更近一步。
再者,虽然我可能再已无法完全完整的掌握这些技术了,但技术本身却可以启迪心的觉醒,激发灵感,那么只要多了解一点,我相信我将离那个正离我而去跑得越来越快的未来更近一点,不至于被未知的那个未来抛弃得太远。
于是我怎能放弃追逐求索的步伐?
我要坚信:感觉太迟的时候,也许还不算太迟。
感谢一直以来关注我,鼓励我的你!
若不嫌弃这一个到了高龄才长大的可笑可叹的我,请不吝赐教。
我的q号是:578652607,敬候你的指点。
为了追赶未来,终身学习,终身进步,我创建了【就是要学 终身成长】社群,欢迎立志于终身学习,终身成长的朋友们加入,共同交流学习。Qq群号码:646854445
或访问:www.941xue.com
【同步语音笔记】
【学习过程屏幕录屏】