文章目录
- 一、什么是公钥、私钥、地址
- 二、实现过程
- 1、从keystore文件中解出私钥以及私钥->公钥->地址
- 2、利用公钥进行消息加密/解密
一、什么是公钥、私钥、地址
- 私钥:32字节(256位),私钥需要保管和隐蔽(非公开)(截取《以太坊技术详解与实战》)
- 公钥:(由私钥生成)64字节(512位),公钥是公开的,不需要保密(截取《以太坊技术详解与实战》)
- 地址:20字节(160位),要注意,我们使用最多的地址并不等同于公钥
地址的生成过程:
从私钥得到一个512位(64字节)的公钥之后,将公钥进行sha3加密,然后将加密后的前44字节去掉,保留剩下的160位二进制数(20字节)
将该20字节编译成长度为40的十六进制字符串,即地址。
具体如下:
二、实现过程
从上面地址的生成过程中可以看到,使用到的两个加密函数主要是secp256k1和sha3(也就是上面的keccak-256),那么要找python中实现这两个函数的模块。
web3.py中已经有keccak-256的实现,故不需要再另寻。
而实现secp256k1的模块是:eth_keys->安装pip install eth_keys
另外,进行公钥加密可以使用模块:eciespy->安装pip install eciespy
所以模块准备:
web3.py
pip install eth_keys
pip install eciespy
1、从keystore文件中解出私钥以及私钥->公钥->地址
(1) keystore文件夹在我们创建创世区块的文件中"./data"下
keystore文件夹存放的文件是与账户私钥相关的加密信息,文件由personal.newAccount()函数执行后创建。
先读取文件信息:
with open(
r"E:\PycharmProjects\btc\data\keystore\UTC--2021-03-23T07-27-44.500405400Z--a46c666d76e5c044cd8d6b21d3cdf76d5571f48e",
"r") as f:
self.encrypted_key = f.read()
(2) 从self.encrypted_key中解出私钥:
from web3 import Account
self.privatekey = Account.decrypt(self.encrypted_key,"123")
print(self.privatekey)
(3) 引入eth_keys模块中的keys,从私钥中解出公钥
from eth_keys import keys
priv_key = keys.PrivateKey(self.privatekey)
print("priv_key:",priv_key)
self.public_key = priv_key.public_key
print("公钥:",self.public_key)
print("公钥长度:",len(str(self.public_key)))
(4) 使用web3.py自带的keccak实现从公钥中得出地址
sha3_pub_key = Web3.keccak(hexstr=str(self.public_key))
print("sha3_pub_key",sha3_pub_key)
print('从公钥生成地址:',Web3.toHex(sha3_pub_key[-20:]))
完整代码如下:
import json
from web3 import Web3, Account, HTTPProvider
from functools import wraps
from eth_account.messages import encode_defunct
from eth_keys import keys
from eth_utils import decode_hex
import ecies
class ethereumHandler_OP():
myPrivateKey = None
myPublicAddr = None
iflogin = None
"""初始化连接以太坊私链"""
def __init__(self):
self.web3 = Web3(HTTPProvider("http://localhost:8545"))
if self.web3.eth.getBlock(0) is None:
print("Failed to connect!")
elif self.web3.isConnected():
print("Successfully connected")
def PrivateKey_PublicKey_Address(self):
with open(
r"E:\PycharmProjects\btc\data\keystore\UTC--2021-03-23T07-27-44.500405400Z--a46c666d76e5c044cd8d6b21d3cdf76d5571f48e",
"r") as f:
self.encrypted_key = f.read()
print("读取到的keystore文件中的信息:", self.encrypted_key)
self.privatekey = Account.decrypt(self.encrypted_key, "123")
print("私钥:", self.privatekey)
priv_key = keys.PrivateKey(self.privatekey)
print("priv_key:", priv_key)
self.public_key = priv_key.public_key
print("公钥:", self.public_key)
print("公钥长度:", len(str(self.public_key)))
sha3_pub_key = Web3.keccak(hexstr=str(self.public_key))
print("sha3_pub_key", sha3_pub_key)
print('从公钥生成地址:', Web3.toHex(sha3_pub_key[-20:]))
if __name__ == "__main__":
eth = ethereumHandler_OP()
eth.PrivateKey_PublicKey_Address()
D:\Python\Python38\python.exe E:/PycharmProjects/区块链项目/testkey.py
Successfully connected
读取到的keystore文件中的信息: {"address":"a46c666d76e5c044cd8d6b21d3cdf76d5571f48e","crypto":{"cipher":"aes-128-ctr","ciphertext":"55551ee6575f4e77e387b6c6eff10a6fc6da013898dcaa93dd1d70901437d14b","cipherparams":{"iv":"5807c666aa3bc267aa4504f42f09ced6"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"353b7a1d3ba4079493b222762b58e4b2c06cdb41ba770ab32441b063784e8858"},"mac":"bfcbaca3dbd199224251e97a77319d919b7ecace290dde1bec49ba275244e01c"},"id":"73f1b676-62e9-4e34-8e0d-5d9639d8e8b9","version":3}
私钥: b'\xa1\xd0\xf3\xdd\xbb\xfc\xc2W\xc0j\xdf\xb5\xc0\xcf\x96pL\xb7\xfd\xab\xa6 \xbc\x89%\x14\x9c%\xfd\x8b\x85i'
priv_key: 0xa1d0f3ddbbfcc257c06adfb5c0cf96704cb7fdaba620bc8925149c25fd8b8569
公钥: 0xc46d2b24d58ac4f1c8e50246cfbcb32fac785dba1376d13ffb712b022135e513020df7fa655b75197c24687b268d2f14cea382ca9f52ef392ab2e0f1734094da
公钥长度: 130
sha3_pub_key b'\x97x\xf2\x01c\x12\x8e%\xe0Z9\x84\xa4lfmv\xe5\xc0D\xcd\x8dk!\xd3\xcd\xf7mUq\xf4\x8e'
从公钥生成地址: 0xa46c666d76e5c044cd8d6b21d3cdf76d5571f48e
Process finished with exit code 0
2、利用公钥进行消息加密/解密
使用eciespy模块,在上面class ethereumHandler_OP类中加入函数:
import ecies
class ethereumHandler_OP():
def encryptMsg(self,_msg):
'''
params:_msg必须是字节bytes类型,由b''定义的字符串
'''
encrypted_msg = ecies.encrypt(self.public_key.to_hex(),bytes(_msg,encoding='utf8'))
return encrypted_msg
def decryptMsg(self,_encryptedmsg):
recovered_msg = ecies.decrypt(self.privatekey,_encryptedmsg)
return recovered_msg
(1)试着对“Hello World!11进行加密”
if __name__ == "__main__":
eth = ethereumHandler_OP()
eth.PrivateKey_PublicKey_Address()
encrypted_msg = eth.encryptMsg("Hello,world!11")
(2)然后就是解密:
if __name__ == "__main__":
eth = ethereumHandler_OP()
eth.PrivateKey_PublicKey_Address()
encrypted_msg = eth.encryptMsg("Hello,world!11")
print("加密信息如下:",encrypted_msg)
print("解密信息:",eth.decryptMsg(encrypted_msg))
以上是以太坊实现公钥加密的过程。
完整代码如下:
import json
from web3 import Web3, Account, HTTPProvider
from functools import wraps
from eth_account.messages import encode_defunct
from eth_keys import keys
from eth_utils import decode_hex
import ecies
class ethereumHandler_OP():
myPrivateKey = None
myPublicAddr = None
iflogin = None
"""初始化连接以太坊私链"""
def __init__(self):
self.web3 = Web3(HTTPProvider("http://localhost:8545"))
if self.web3.eth.getBlock(0) is None:
print("Failed to connect!")
elif self.web3.isConnected():
print("Successfully connected")
def PrivateKey_PublicKey_Address(self):
with open(
r"E:\PycharmProjects\btc\data\keystore\UTC--2021-03-23T07-27-44.500405400Z--a46c666d76e5c044cd8d6b21d3cdf76d5571f48e",
"r") as f:
self.encrypted_key = f.read()
print("读取到的keystore文件中的信息:", self.encrypted_key)
self.privatekey = Account.decrypt(self.encrypted_key, "123")
print("私钥:", self.privatekey)
priv_key = keys.PrivateKey(self.privatekey)
print("priv_key:", priv_key)
self.public_key = priv_key.public_key
print("公钥:", self.public_key)
print("公钥长度:", len(str(self.public_key)))
sha3_pub_key = Web3.keccak(hexstr=str(self.public_key))
print("sha3_pub_key", sha3_pub_key)
print('从公钥生成地址:', Web3.toHex(sha3_pub_key[-20:]))
def encryptMsg(self, _msg):
'''
params:_msg必须是字节bytes类型,由b''定义的字符串
'''
encrypted_msg = ecies.encrypt(self.public_key.to_hex(), bytes(_msg, encoding='utf8'))
return encrypted_msg
def decryptMsg(self, _encryptedmsg):
recovered_msg = ecies.decrypt(self.privatekey, _encryptedmsg)
return recovered_msg
def signtMsg(self, _msg):
print("original msg:", _msg)
premsg = encode_defunct(text=_msg)
print("预准备的数据体:", premsg)
signedmsg = Account.sign_message(premsg, self.privatekey)
print("签名后的信息:", signedmsg)
def vertifyMsg(self, _signedmsg):
print(Account.recover_message("Hello,world!", ))
def test(self):
private_1 = '0xa1d0f3ddbbfcc257c06adfb5c0cf96704cb7fdaba620bc8925149c25fd8b8569'
public_1 = '0xc46d2b24d58ac4f1c8e50246cfbcb32fac785dba1376d13ffb712b022135e513020df7fa655b75197c24687b268d2f14cea382ca9f52ef392ab2e0f1734094da'
print(len(public_1))
address_1 = '0xa46c666d76e5c044cd8d6b21d3cdf76d5571f48e'
encryptmsg = ecies.encrypt(public_1, b'hello,world!')
print("加密的信息:", encryptmsg)
decryptmsg = ecies.decrypt(private_1, encryptmsg)
print("解密的信息:", decryptmsg)
if __name__ == "__main__":
eth = ethereumHandler_OP()
eth.PrivateKey_PublicKey_Address()
encrypted_msg = eth.encryptMsg("Hello,world!11")
print("加密信息如下:",encrypted_msg)
print("解密信息:",eth.decryptMsg(encrypted_msg))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)