Skip to content

Commit

Permalink
Add algorithm/bip32
Browse files Browse the repository at this point in the history
  • Loading branch information
koba-e964 committed Nov 27, 2023
1 parent db22204 commit 27cfd5c
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 0 deletions.
55 changes: 55 additions & 0 deletions algorithm/bip32/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# BIP 32

## 仕様
### 概要
https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
色々な方法での鍵の導出 (決定的な計算) をできるようにする。
- 乱数の種 -> マスター秘密鍵
- HMAC-512 を使って生成
- 秘密鍵, index -> 子の秘密鍵 (non-hardened)
- mpriv, mpub を鍵ペアとした時、mpriv + (mpub, index から生成した決定的乱数) mod n
- 秘密鍵, index -> 子の秘密鍵 (hardened)
- mpriv, mpub を鍵ペアとした時、mpriv + (mpriv, index から生成した決定的乱数) mod n
- 公開鍵, index -> 子の公開鍵 (non-hardened)
- `秘密鍵 -> 子の秘密鍵 (non-hardened)` で得られるものと整合的なので、mpub + (mpub, index から生成した決定的乱数)B である。

細かい背景情報は以下。
- 曲線: [secp256k1](https://www.secg.org/sec2-v2.pdf)
- $p = 2^{256} - 2^{32} - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1$
- 方程式: $y^2 = x^3+7$
- cofactor = 1
- B: ベースポイント
- n: 位数

鍵から鍵の導出は深さ 255 まで許される。

### セキュリティー
親の鍵ペア (mpriv, mpub) に対して non-hardened な child priv は cpriv=(mpub の関数)+k という形になっていて、 mpub を公開情報と仮定した時 cpriv が漏れたら mpriv も漏れる。

## 既存の実装
### Go
https://github.com/tyler-smith/go-bip32
- 秘密鍵と公開鍵が同じ型
- Go の標準ライブラリーでは PrivateKey, PublicKey というように分けている
- [https://soatok.blog/2021/01/20/please-stop-encrypting-with-rsa-directly/](https://soatok.blog/2021/01/20/please-stop-encrypting-with-rsa-directly/)
> In my opinion, we should stop shipping cryptography interfaces that…
> - Allow public/private keys to easily get confused (e.g. lack of type safety)
- 暗号技術の操作にふさわしくない big.Int を使っている
- [https://pkg.go.dev/math/big#Int](https://pkg.go.dev/math/big#Int)
> Note that methods may leak the Int's value through timing side-channels. Because of this and because of the scope and complexity of the implementation, Int is not well-suited to implement cryptographic operations. The standard library avoids exposing non-trivial Int methods to attacker-controlled inputs and the determination of whether a bug in math/big is considered a security vulnerability might depend on the impact on the standard library.
- 参考資料: [https://simple-minds-think-alike.moritamorie.com/entry/crypto-ecdh](https://simple-minds-think-alike.moritamorie.com/entry/crypto-ecdh)

https://github.com/libs4go/crypto/tree/main/elliptic
- 暗号技術の操作にふさわしくない big.Int を使っている

### Rust
https://docs.rs/crate/bip32/0.5.1
- かなりセキュリティーのことを真面目に考えていそう
- ゼロ化、一定時間演算などを使っている

### Python
https://github.com/scgbckbone/btc-hd-wallet/blob/master/btc_hd_wallet/bip32.py
- int を使っているので多分タイミング攻撃に弱い
- Python で一定時間演算を行うのは難しいらしい
- [https://securitypitfalls.wordpress.com/2018/08/03/constant-time-compare-in-python/](https://securitypitfalls.wordpress.com/2018/08/03/constant-time-compare-in-python/)
12 changes: 12 additions & 0 deletions algorithm/bip32/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module github.com/koba-e964/code-reading/algorithm/bip32

go 1.21.2

require github.com/tyler-smith/go-bip32 v1.0.0

require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5 // indirect
)
19 changes: 19 additions & 0 deletions algorithm/bip32/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680 h1:oAXco1Ts88F75L1qvG3BAa4ChXI3EZDfxbB+p+y8+gE=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5 h1:LtqPZJBT4TN+oR4PYeP4NsEXw48n76ZGyUh3RzL4VH8=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=
39 changes: 39 additions & 0 deletions algorithm/bip32/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main

import (
"encoding/hex"
"log"

"github.com/tyler-smith/go-bip32"
)

// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-3
func testVector3() {
seedString := "4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be"
seed, _ := hex.DecodeString(seedString)

master, _ := bip32.NewMasterKey(seed)
log.Print(hex.EncodeToString(master.Key))
if master.Key[0] != 0 {
panic("master.Key[0] != 0")
}
}

// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-4
func testVector4() {
seedString := "3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678"
seed, _ := hex.DecodeString(seedString)

master, _ := bip32.NewMasterKey(seed)
child0, _ := master.NewChildKey(bip32.FirstHardenedChild + 0)
log.Print(hex.EncodeToString(master.Key))
log.Print(hex.EncodeToString(child0.Key))
if child0.Key[0] != 0 {
panic("child0.Key[0] != 0")
}
}

func main() {
testVector3()
testVector4()
}

0 comments on commit 27cfd5c

Please sign in to comment.