以太坊之賬戶

一、外部賬戶

eth_account_gen.jpeg

外部賬戶創(chuàng)建流程:

  • 創(chuàng)建隨機(jī)私鑰(64位16進(jìn)制字符/32字節(jié)): ecdsa.GenerateKey(crypto.S256(), rand)
  • 從私鑰推導(dǎo)出公鑰(128位16進(jìn)制字符/64字節(jié)): privateKeyECDSA.PublicKey
  • 從公鑰推導(dǎo)出地址(40位16進(jìn)制字符/20字節(jié)): Keccak256(pubBytes[1:])[12:]

當(dāng)使用geth account new命令新建賬戶,最終調(diào)用accountCreate(accountcmd.go)=>keystore.StoreKey=>storeNewKey(key.go)

func newKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key {
    id, err := uuid.NewRandom()
    if err != nil {
        panic(fmt.Sprintf("Could not create random uuid: %v", err))
    }
    key := &Key{
        Id:         id,
        Address:    crypto.PubkeyToAddress(privateKeyECDSA.PublicKey), // 生成地址 Keccak256(pubBytes[1:])[12:]
        PrivateKey: privateKeyECDSA,
    }
    return key
}
func newKey(rand io.Reader) (*Key, error) {
    privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand) // 隨機(jī)生成私鑰
    if err != nil {
        return nil, err
    }
    return newKeyFromECDSA(privateKeyECDSA), nil
}

func storeNewKey(ks keyStore, rand io.Reader, auth string) (*Key, accounts.Account, error) {
    key, err := newKey(rand)
    if err != nil {
        return nil, accounts.Account{}, err
    }
    a := accounts.Account{
        Address: key.Address,
        URL:     accounts.URL{Scheme: KeyStoreScheme, Path: ks.JoinPath(keyFileName(key.Address))},
    }
    if err := ks.StoreKey(a.URL.Path, key, auth); err != nil {
        zeroKey(key.PrivateKey)
        return nil, a, err
    }
    return key, a, err
}

storeNewKey完成私鑰、公鑰、地址的生產(chǎn),最后保存成keystore文件到指定路徑。

最后保存的keystore文件為json格式,如下:

{
    "address": "26ce833a705af6846da8c1a43d1e418b93458137",  //賬戶地址
    "crypto": {
        //使用的加密算法,這里使用AES-CTR模式加密私鑰,分組模式是128比特
        "cipher": "aes-128-ctr",    
        //這是對(duì)原始私鑰加密后的私鑰的密文
        "ciphertext": "e2edc5df564536dcf7fb8bcfde99404215d8dd8327684e9d27327a267181a791",
        "cipherparams": {
            //這是向量
            "iv": "9847020ef0bb269b0c463d2ed4bb2ac4"
        },
        "kdf": "scrypt",
        "kdfparams": {
            "dklen": 32, //解密秘鑰的長(zhǎng)度
        //進(jìn)行加密解密運(yùn)算的次數(shù),在越大的情況下,可以增加暴力破解的成本,也會(huì)使簽名速度變慢
            "n": 262144, 
        //設(shè)置為1為只能串行運(yùn)算.0為并行運(yùn)算.串行運(yùn)算可以增加安全性.也會(huì)影響簽名速度
            "p": 1,
        //加密的分組長(zhǎng)度
            "r": 8,
        //可以理解為隨機(jī)生成的向量
            "salt": "56fc7ac270cd1a357a2bc1959119f10df4b69fabb4d0c198d6527f3c0fe2df6b"
        },
        //這是解密私鑰密文的秘鑰的hash值,防止用戶輸入錯(cuò)誤的密碼而計(jì)算出錯(cuò)誤的私鑰.用與比對(duì)私鑰是否正確.
        "mac": "7fde1727799710cf122d441c57c50cbc8182f666cca5a7717a8cb3bb8d21639d"
    },
    "id": "1d6b8676-de36-441d-a736-2a8ee94019ea",
    "version": 3
}

以下為用密碼可以推出私鑰的流程


keystore_enc.png

二、內(nèi)部賬戶

對(duì)交易發(fā)起人的地址和nonce進(jìn)行RLP編碼,再算出Keccak哈希值,取后20個(gè)字節(jié)作為該合約的地址,即:Keccak-256(RLP(sender, nonce))[12:]
函數(shù)位于:crypto/crypto.go

// CreateAddress creates an ethereum address given the bytes and the nonce
func CreateAddress(b common.Address, nonce uint64) common.Address {
    data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
    return common.BytesToAddress(Keccak256(data)[12:])
}

三、賬戶結(jié)構(gòu)

賬戶在區(qū)塊鏈上的存儲(chǔ)結(jié)構(gòu),內(nèi)外賬戶的結(jié)構(gòu)都是一樣

type Account struct {
    Nonce    uint64      // 賬戶發(fā)起交易的次數(shù)
    Balance  *big.Int    // 賬戶的余額
    Root     common.Hash // 合約賬戶存儲(chǔ)空間的一棵MPT樹的根節(jié)點(diǎn)的Hash
    CodeHash []byte      // 合約代碼的Hash值
}
account_diff.png

文章github地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容