每個乙太坊地址是否由(理論上)2 ** 96 個私鑰共享?
概括
這是關於如何生成乙太坊地址的擴展問題?.
在乙太坊中,私鑰是 256 位長,但地址只有 160 位長。通過“鴿洞原理”,它保證了一些唯一的私鑰映射到同一個地址。理論上,
2 ** 96
唯一的私鑰平均映射到一個地址。題
如果 2 個私鑰映射到同一個地址,它們是否都可以訪問同一個地址?他們都可以用來將乙太幣從那個地址轉移到另一個地址嗎?
細節
根據@tayvano 的回答,私鑰是 256 位長,任何 256 位字元串都是有效的私鑰:
假設每一個 64 十六進製字元串都是用於訪問帳戶的乙太坊私鑰。
因此,存在
2 ** 256
有效的私鑰(密鑰空間為2 ** 256
)。公鑰長度為 512 位。但是,由於它們中的每一個都是從自己的私鑰派生的,因此只有
2 ** 256
有效的公鑰,因此密鑰空間是2 ** 256
。然後將公鑰作為
Keccak-256
(準標準 SHA3)散列算法的輸入提供。的輸出Keccak-256
是一個 256 位的字元串,因此可以將其視為鍵空間中的一對一映射。(雜湊空間為2 ** 256
)但是,乙太坊地址是從
Keccak-256
雜湊的最低有效 160 位中獲得的。這將關鍵空間削減到2 ** 160
.因此,從私鑰生成地址的過程是 256 位值到 160 位值的函式,這保證了重複。
你可能感興趣
你的計算是正確的,除了不完全是 2^256 個私鑰——有“FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141”(這個數字
N
在 ETH 原始碼中命名,並且是生成器的順序橢圓曲線 secp256k1,從中生成乙太坊密鑰對)。在回答您的問題時,是的,映射到同一地址的私鑰都可以按照先到先得的原則將錢花在該地址上。他們將創建相同的公鑰,執行 ECDSA 驗證算法,因此任何一個私鑰生成的簽名都將針對相同的地址進行驗證!
在go-ethereum/accounts/key.go中,我們有一個從 S256 生成的私鑰,它是 secp256k1 的曲線,這意味著它們將小於
N
預設值。func newKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key { id := uuid.NewRandom() key := &Key{ Id: id, Address: crypto.PubkeyToAddress(privateKeyECDSA.PublicKey), PrivateKey: privateKeyECDSA, } return key } func newKey(rand io.Reader) (*Key, error) { privateKeyECDSA, err := ecdsa.GenerateKey(secp256k1.S256(), rand) if err != nil { return nil, err } return newKeyFromECDSA(privateKeyECDSA), nil }
go-ethereum/crypto/secp256k1/secp256也根據 secp2656k1 生成密鑰對,儘管方式略有不同:)
很酷的說明性解釋,說明什麼是
N
真正的東西以及為什麼 2 把鑰匙可以從同一個賬戶花錢想像一下,私鑰是在您的汽車中行駛的里程數,而公鑰是您汽車里程表上的里程數。如果里程表從 999,999 滾動到 000,000,則行駛里程 = 1,000,001 的人將擁有與行駛里程 = 1 的人相同的“公鑰”,因此具有相同的地址。
EC 組算術與此驚人地相似,但不是 999,999,而是上面給出的看似任意的數字!由於此屬性,即使您使用不同的“私鑰”,您也可以創建針對相同公鑰進行驗證的簽名,從而從同一地址花費 ETH!
無聊的數學解釋
私鑰是 256 位數字,要從私鑰乘以
g
橢圓曲線組的生成器 來計算公鑰。正在使用的生成器在 ETH 中使用的 secp256k1 庫的參數中定義。它本身也是一個橢圓曲線點,由於橢圓曲線是循環的,所以存在一個n
這樣的n.g = 1
(這稱為生成器階)。
k
通過這個等式,我們可以看到,如果我們有一個帶有的私鑰k>n
,我們將擁有k.g = (k-n).g = k'.g
,因為k'
它可能是其他人的私鑰!所以我們有隨機模生成的密鑰n
,而不是 2^256。