key_derive/
config.rs

1//! 在我们的对话中,我们讨论了以下几个主题:
2//!
3//! 6. 如何从字符串中读取 `[u8; 32]` 类型的字节数组。
4//! 7. 使用 `.env` 文件来存储配置变量。
5//! 8. 如何加载 `.env` 文件中的变量并使其在应用程序中可用。
6//! 9. 如何适配字符串类型的环境变量到 `[u8; 32]` 类型的数组。
7//! 10. 如何使用 `serde::de::Error` 来创建自定义错误。
8
9use crate::{
10    derive_child::{derive_child_key, generate_public_key},
11    prelude::*,
12};
13
14/// root_key_bytes 和 root_chain_code 是示例中用来表示
15/// 根密钥(root key)和根链码(root chain code)的变量。
16/// 在密钥派生过程中,根密钥和根链码用作起点,通过派生算法
17/// 和索引号来生成子私钥和子链码。这样可以在根密钥的基础上派生出
18/// 多个层级的子密钥,从而提供更灵活的密钥管理和派生能力。
19#[derive(Deserialize, Debug)]
20pub struct Config {
21    /// root_key_bytes 是一个长度为 32 字节的字节数组,表示根密钥的值。在示例中,
22    /// 我们使用了一个简单的值 [0x01; 32] 来表示根密钥,实际应用中应该使用真正的随机值。
23    #[serde(deserialize_with = "deserialize_from_hex")]
24    root_key_bytes: [u8; 32],
25
26    /// root_chain_code 也是一个长度为 32 字节的字节数组,表示根链码的值。链码是密钥派生中的一部分,
27    /// 用于增加密钥派生的安全性。在示例中,我们使用了一个简单的值 [0x02; 32] 来表示根链码,
28    /// 实际应用中应该使用真正的随机值。
29    #[serde(deserialize_with = "deserialize_from_hex")]
30    root_chain_code: [u8; 32],
31}
32
33/// Access to parsed configuration.
34pub static CONFIG: Lazy<Config> = Lazy::new(|| envy::from_env().expect("some env vars missing"));
35
36fn deserialize_from_hex<'de, D>(deserializer: D) -> Result<[u8; 32], D::Error>
37where
38    D: serde::Deserializer<'de>,
39{
40    use serde::de::Error;
41    let hex_string: String = serde::Deserialize::deserialize(deserializer)?;
42
43    hex_to_slice(hex_string).map_err(D::Error::custom)
44}
45
46pub fn hex_to_slice(hex_string: String) -> Result<[u8; 32], &'static str> {
47    Vec::from_hex(hex_string)
48        .map_err(|_e| "Invalid byte array size")?
49        .try_into()
50        .map_err(|_e| "Invalid byte array size")
51}
52
53impl Config {
54    pub fn derive_child_key(&self, index: u32) -> (SecretKey, [u8; 32], PublicKey) {
55        let Config {
56            root_key_bytes,
57            root_chain_code,
58        } = *self;
59        let (child_key, child_chain_code) =
60            derive_child_key(&root_key_bytes, &root_chain_code, index);
61        let child_public_key = generate_public_key(&child_key);
62        (child_key, child_chain_code, child_public_key)
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use crate::prelude::*;
69
70    use crate::CONFIG;
71    #[test]
72    fn show_config_with_root_public() {
73        dotenv().ok();
74        assert_debug_snapshot!(CONFIG.derive_child_key(0).2);
75    }
76    #[test]
77    fn ascii_to_hex() {
78        let hex_string = hex::encode("s1");
79        dbg!(hex_string);
80        let hex_string = hex::encode("s2");
81        dbg!(hex_string);
82    }
83}