Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add mnemonic & entendskeys of HDWallet #1222

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions BTC/Basic/hdwallet/extendKeys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
HD钱包中的**扩展公钥(Extended Public Key, xPub)**和**扩展私钥(Extended Private Key, xPriv)**是BIP32标准的一部分,它们是用于派生子密钥和管理钱包的关键概念。以下是它们的详细技术介绍。

### 1. **扩展密钥的定义**
- **扩展私钥(xPriv)**:包含私钥和链码的信息,允许派生出子私钥和子公钥。
- **扩展公钥(xPub)**:包含公钥和链码的信息,只能派生出子公钥,无法推导出私钥。

![extend keys](./imgs/hd-wallets-extended-keys.png)

### 2. **扩展密钥的组成**
扩展密钥不仅包括公钥或私钥,还包括链码(Chain Code)、路径信息等,以支持分层确定性派生。扩展密钥的完整组成如下:

- **公钥/私钥**:用于加密和签名的密钥。
- **链码**:确保子密钥派生时的不可预测性,提供额外的随机性。
- **深度(Depth)**:当前密钥的层级深度,根节点为0。
- **父公钥指纹(Parent Fingerprint)**:标识父密钥,用于防止路径冲突。
- **索引(Index)**:指示该密钥在父密钥下的派生索引。
- **版本(Version)**:指示密钥类型(xPub 或 xPriv)。
- **校验和**:用于验证密钥完整性。

### 3. **扩展密钥的编码格式**
扩展密钥通常以Base58Check格式进行编码,确保其易于人类读取和传输。Base58Check编码避免了易混淆的字符(如0和O,l和I)。编码后的扩展密钥通常以以下前缀开头:
- **xPub**:用于表示扩展公钥。
- **xPriv**:用于表示扩展私钥。

#### **编码示例**
扩展密钥的编码格式如下:
```
[version (4 bytes)][depth (1 byte)][parent fingerprint (4 bytes)][child number (4 bytes)]
[chain code (32 bytes)][key data (33 bytes)][checksum (4 bytes)]
```

### 4. **生成扩展私钥和扩展公钥**
#### a. **生成扩展私钥**
扩展私钥是通过HMAC-SHA512生成的。算法步骤如下:
- 生成主私钥和链码时,将种子输入HMAC-SHA512,并使用“Bitcoin seed”作为密钥。
- 输出前32字节是私钥,后32字节是链码。

#### b. **生成扩展公钥**
从扩展私钥可以生成扩展公钥,通过椭圆曲线加密(ECC)运算将私钥转换为公钥。

**扩展公钥生成步骤**:
- 取扩展私钥的前32字节(私钥部分),并将其转换为公钥。
- 保留链码和其他元数据。

### 5. **子密钥派生过程**
扩展密钥的强大之处在于,它们支持通过链码进行分层确定性派生,生成子密钥而不需要暴露父级的私钥。

#### a. **从扩展私钥派生子私钥**
扩展私钥可以派生子私钥和子公钥。
- **算法**:
```
I = HMAC-SHA512(key=parent_chain_code, data=0x00 || parent_private_key || child_index)
```
- `I` 的前32字节用作派生的子私钥的一部分,后32字节用作新的子链码。
- 子私钥公式:`child_private_key = (IL + parent_private_key) % n`。

#### b. **从扩展公钥派生子公钥**
扩展公钥只能派生子公钥,无法反推出私钥,确保了安全性。
- **算法**:
```
I = HMAC-SHA512(key=parent_chain_code, data=parent_public_key || child_index)
```
- 子公钥通过公钥加法计算得出。
- 子公钥公式:`child_public_key = G * IL + parent_public_key`(`G` 为椭圆曲线生成点)。


![why-it-works](./imgs/hd-wallets-extended-keys-why-it-works.png)

### 6. **硬化派生与标准派生**
- **硬化派生**(Hardened Derivation):只能通过扩展私钥派生,子公钥无法通过扩展公钥派生出来,增加了安全性。索引大于等于 `2^31` 的值用于硬化派生。
- **标准派生**(Non-Hardened Derivation):可以通过扩展公钥派生出子公钥,索引小于 `2^31`。

### 7. **用途和安全性**
- **xPub的应用**:适用于公开应用,如钱包软件中用来显示和管理多个收款地址。通过扩展公钥,第三方可以生成新的地址而不接触私钥。
- **xPriv的应用**:仅用于安全环境,绝不能公开,以防止密钥泄露。

**安全注意事项**:
- **保护扩展私钥**:xPriv的泄露意味着整个密钥树的私钥都处于危险中。
- **使用硬化派生**:在可能被公开的路径中,建议使用硬化派生来确保私钥安全。

### 8. **示例代码**
以下是使用JavaScript库生成扩展密钥的示例代码:

```javascript
const bip32 = require('bip32');
const bip39 = require('bip39');

// 生成助记词和种子
const mnemonic = bip39.generateMnemonic();
const seed = bip39.mnemonicToSeedSync(mnemonic);

// 生成根节点
const root = bip32.fromSeed(seed);

// 获取扩展公钥和扩展私钥
const xPriv = root.toBase58();
const xPub = root.neutered().toBase58();

console.log('扩展私钥 (xPriv):', xPriv);
console.log('扩展公钥 (xPub):', xPub);
```

### **总结**
扩展公钥(xPub)和扩展私钥(xPriv)是HD钱包中的核心概念,提供了派生和管理子密钥的能力。xPriv 可以派生子私钥和子公钥,而 xPub 只能派生子公钥。使用这些扩展密钥,用户和开发者可以实现灵活的密钥管理,同时保证密钥的安全性。
Binary file added BTC/Basic/hdwallet/imgs/entry-to-mnemonic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added BTC/Basic/hdwallet/imgs/mnemonic-to-seed.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added BTC/Basic/hdwallet/imgs/seed-to-root.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
88 changes: 88 additions & 0 deletions BTC/Basic/hdwallet/mnemonic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
HD钱包中的助记词(Mnemonic Phrase)是一组人类可读的单词,用来表示随机生成的种子。助记词为用户提供了一个易于备份和恢复的钱包方式,极大地简化了复杂的密钥管理。以下是HD钱包助记词的详细技术原理:

### 1. **助记词的定义和作用**
助记词是一串用来帮助用户记忆种子的单词序列。HD钱包使用助记词来生成用于派生密钥的种子,因此只要备份助记词,就可以恢复整个钱包的密钥树。

### 2. **助记词生成的步骤**
助记词生成过程基于BIP39标准,涉及以下步骤:

#### a. **生成熵(Entropy)**
- **熵的定义**:熵是用于随机生成助记词的随机位序列。常见的熵长度有128位、160位、192位、224位和256位。
- **例子**:假设熵为128位,它会生成12个单词的助记词。

#### b. **计算校验和(Checksum)**
- 将熵进行SHA-256哈希,取哈希结果的前 `ENT / 32` 位作为校验和,其中 `ENT` 是熵的位长度。
- **例子**:如果熵是128位,则校验和为 `128 / 32 = 4` 位。

#### c. **组合熵和校验和**
- 将原始熵和校验和组合,形成一个新的位序列。例如,128位熵加上4位校验和形成132位序列。

#### d. **分割为11位块**
- 将132位的位序列分割为多个11位的块,每个块可以表示0到2047之间的一个数字。
- 这些数字用于从一个2048个单词的字典(BIP39单词表)中查找对应的单词。


![entry-to-mnemonic.png](./imgs/entry-to-mnemonic.png)

### 3. **BIP39单词表**
- **固定单词表**:BIP39定义了一个包含2048个单词的标准单词表。这些单词具有以下特点:
- 每个单词都有明确的拼写,不易混淆。
- 单词表的不同语言版本保持一致性,但使用的是本地语言词汇。

### 4. **种子生成**
助记词本身并不能直接用于密钥派生。助记词需要经过密码学处理生成一个种子,种子用来生成HD钱包的主私钥和链码。

#### a. **PBKDF2函数**
- 助记词通过PBKDF2-HMAC-SHA512算法与一个盐值组合,生成512位种子。
- **盐值**:通常是 `mnemonic` 加上一个用户提供的密码短语(可选),增强了安全性。
- **算法**:
```text
seed = PBKDF2(mnemonic, "mnemonic" + passphrase, 2048, 64, HMAC-SHA512)
```


![mnemonic-to-seed.png](./imgs/mnemonic-to-seed.jpeg)


### 5. **助记词的恢复**
当用户输入助记词进行恢复时,钱包软件会执行以下步骤:
- 将助记词映射回原始熵和校验和。
- 验证助记词是否有效(检查校验和)。
- 使用PBKDF2函数将助记词和用户输入的密码短语(如果有)转换为种子。
- 通过该种子生成HD钱包的主私钥和链码,从而恢复整个密钥树。


![seed-to-root.png](./imgs/seed-to-root.png)


### 6. **助记词的优点**
- **易于记忆和备份**:助记词比纯随机的密钥更容易记住和存储。
- **便于恢复**:只要用户保留助记词,就可以在任何支持BIP39的HD钱包中恢复整个钱包。
- **增加安全性**:通过密码短语增强了助记词的安全性。如果助记词被泄露,攻击者仍然需要知道密码短语才能恢复钱包。

### 7. **助记词的安全注意事项**
- **备份和存储**:助记词应以离线方式备份,如写在纸上并存放在安全的地方。不要将助记词存储在联网设备上。
- **密码短语**:使用一个复杂且不易猜测的密码短语可以大大提高安全性,即使助记词被盗,攻击者也无法轻易访问钱包。
- **防止物理和电子威胁**:确保助记词的存储位置防范火灾、盗窃或电子攻击。

### 8. **技术示例**
以下是使用JavaScript库生成助记词和种子的示例代码:

```javascript
const bip39 = require('bip39');

// 生成12个单词的助记词
const mnemonic = bip39.generateMnemonic();
console.log('助记词:', mnemonic);

// 验证助记词是否合法
const isValid = bip39.validateMnemonic(mnemonic);
console.log('助记词是否合法:', isValid);

// 将助记词转换为种子
const seed = bip39.mnemonicToSeedSync(mnemonic, '可选的密码短语');
console.log('生成的种子:', seed.toString('hex'));
```

### **总结**
HD钱包的助记词系统提供了一种安全、便捷的方式来管理和恢复钱包。助记词通过熵、校验和、PBKDF2算法生成种子,从而衍生出一棵密钥树。理解助记词的原理有助于用户更好地保护自己的数字资产,同时也能帮助开发者实现符合BIP39标准的钱包应用。
Loading