🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
一.基础概念 (1)账户(Accounts): 在以太坊中,有两种类型的账户:一种是外部账户(EOAs,Externally Owned Accounts),另一种是合约账户(Contracts Accounts)。当我们提到账户这个术语的时候,我们通常指的是外部账户(EOA),当提到合约账户的时候我们通常称其为“合约”。 (2)以太坊地址(Address): 一个以太坊地址就代表着一个以太坊账户,地址是账户的标识。对于外部账户来说,地址表示的是该账户公钥的后20字节(通常会以0x开头,例如,`0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826`,该地址使用的是16进制表示法。上述示例中的地址中的字母全部是小写。在EIP55中引入了一种大小写混用的地址表示方法,通过这种表示方法进行表示的地址隐含了一个校验和(checksum)能够验证该地址的有效性 (3) 私钥和公钥 每个账户都由一对钥匙定义,一个私钥(Private Key)和一个公钥(Public Key)。 账户以地址为索引,地址由公钥衍生而来,取公钥的最后20个字节。每对私钥/地址都编码在一个钥匙文件里。该文件是JSON格式的。以太坊的私钥是一串64位16进制字符,如果丢失了私钥也就意味着你的账户丢失了。 (4)查看一个Keystore文件 ~~~ { "address":"358f94366124d9f2817b09c84921d2a653f5ac0c", "crypto":{ "cipher":"aes-128-ctr", "ciphertext":"41c14f88ec8f35c9fe57cd39121a76c2dadbd82ea8fec59866468bc0d7371f2e", "cipherparams":{ "iv":"43443bf394e8f6ebcc687e13bc0effb9" }, "kdf":"scrypt", "kdfparams":{ "dklen":32, "n":262144, "p":1, "r":8, "salt":"aaef6847d09cb1e9f5ceadaf5865d96a7493df1cae146b24e31092cc0a7844af" }, "mac":"5e9781c587db5795c6d41cb4f001bf086cc3db33b6e7eefcc2ef472145e76821" }, "id":"bcd61a88-283f-4d81-8457-30ec9c11521f", "version":3 } ~~~ 通过keystore文件中的内容,我们可以看到其中包括了私钥加密的相关信息: - address:该账户的地址 - cipher:加密方法使用的是AES-128-CTR算法[4](https://blog.csdn.net/luoyhang003/article/details/79970254#fn:4 "See footnote") - ciphertext:加密后的密文 - cipherparams:AES-128-CTR算法加密所需的相关参数 - kdf:秘钥生成函数,用于使用密码对keystore文件进行加密 - kdfparams:kdf算法所需的参数 - mac:用于验证密码的编码 (5) 私钥、公钥和地址是生成顺序 **以太坊使用Secp256k1椭圆曲线得到私钥** ![](https://img.kancloud.cn/c8/42/c8428bbbff7bf54470cea4463343cfbb_928x605.png) (6)python代码生成公钥,私钥,地址 1)第一种 ~~~ from eth_keys import keys from eth_utils import decode_hex decode_hex(私钥) priv_key_bytes = decode_hex('0x44b9abf2708d9adeb1722dcc1e61bef14e5611dee710d66f106e356a111bef90') priv_key = keys.PrivateKey(priv_key_bytes) pub_key = priv_key.public_key ~~~ 2)第二种 ~~~ from eth_keys import keys # 先创建keys模块下的私钥对象 #self.privatekey为私钥 priv_key = keys.PrivateKey(self.privatekey) print("priv_key:",priv_key) # 再解出公钥 self.public_key = priv_key.public_key print("公钥:",self.public_key) # 这里的公钥是64字节,是压缩的 print("公钥长度:",len(str(self.public_key))) # 使用web3.py自带的keccak实现从公钥中得出地址 sha3_pub_key = Web3.keccak(hexstr=str(self.public_key)) print("sha3_pub_key",sha3_pub_key) # 取后20个字节 print('从公钥生成地址:',Web3.toHex(sha3_pub_key[-20:])) ~~~ 3)第三种 ~~~ import binascii import sha3 from ecdsa import SigningKey, SECP256k1 priv = SigningKey.generate(curve=SECP256k1) # 生成私钥 pub = priv.get_verifying_key() # 生成公钥 keccak = sha3.keccak_256() keccak.update(pub.to_string()) # keccak_256哈希运算 address = "0x" + keccak.hexdigest()[24:] priv_key = binascii.hexlify(priv.to_string()) pub_key = binascii.hexlify(pub.to_string()) print("Private key: " + priv_key.decode()) print("Public key: " + pub_key.decode()) print("Address: " + address) ~~~ (7)助记词 助记词和种子不是同一个概念,但并非如此,一个叫mnemonic(助记符或助记词),一个叫seed(种子) ~~~ seed = wallet.generate_mnemonic() ~~~