随機性在簽名中的重要性
簽名生成算法使用随機密鑰
k
作為短暫私鑰/公鑰對的基礎。k的值并不重要,隻要它是随機的。如果使用相同的值k在不同的消息(交易)上生成兩個簽名,那麼任何人都可以計算出簽名私鑰。在簽名算法中重用相同的k值的會導緻私鑰的暴露!
如果在兩個不同的交易中,在簽名算法中使用相同的值k,則私鑰可以被計算并暴露給世界!
這不僅僅是一個理論上的可能性。我們已經看到比特币中幾種不同實作的交易簽名算法因為這個問題導緻私人密鑰暴露。人們由于無意中重複使用k值而導緻資金被竊取。重用k值的最常見原因是随機數生成器未正确初始化。
為了避免這個漏洞,業界最佳實踐不是用熵播種的随機數生成器生成k值,而是使用交易資料本身播種的确定性随機程序。這確定每個交易産生不同的k值。在網際網路工程任務組(InternetEngineering Task Force)釋出的RFC 6979中定義了k值的确定性初始化的行業标準算法。
如果你正在實作一種用于在區塊鍊中簽署交易的算法,則必須使用
RFC 6979
或類似的
确定性随機算法
來確定為每個交易生成不同的k值。
RFC 6979: 确定性随機算法
确定性使用數字簽名算法(DSA)和 橢圓曲線數字簽名算法(ECDSA)
該标準定義了确定性的數字簽名生成過程: 此類簽名與标準數字簽名算法(DSA)和橢圓曲線數字簽名算法(ECDSA)數字簽名相容,并且可以使用未經修改的驗證程式進行處理,這些驗證程式無需了解其中描述的過程。确定性簽名保留了與數字簽名相關聯的密碼安全性功能,但是由于它們不需要通路高品質随機性源,是以可以在各種環境中更輕松地實作。
- 簽署相同的交易将生成相同的k值
- 簽署不同的交易将生成不同的k值
// secp256k1庫中的用确定性随機算法産生随機數k的方法
static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) {
secp256k1_rfc6979_hmac_sha256_t rng;
unsigned int i;
secp256k1_rfc6979_hmac_sha256_initialize(&rng, key32, 32, msg32, 32, (const unsigned char*)data, data != NULL ? 32 : 0);
for (i = 0; i <= counter; i++) {
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
}
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
return 1;
}
參考: RFC 6979
- 往期精彩回顧:
- 區塊鍊知識系列
- 密碼學系列
- 共識系列
- 公鍊調研系列
- 以太坊系列
- EOS系列
- 智能合約系列
- Token系列