Rust密钥管理库sp-keyring的使用,安全存储和访问加密密钥的Rust插件库

运行时支持代码。一组测试账户。 许可证:Apache-2.0

元数据 包:cargo/sp-keyring@43.0.0 21天前 2021版本 Apache-2.0 26.2 KiB

安装 在您的项目目录中运行以下Cargo命令: cargo add sp-keyring 或在您的Cargo.toml中添加以下行: sp-keyring = “43.0.0”

主页 paritytech.github.io/polkadot-sdk

文档 docs.rs/sp-keyring/43.0.0

代码库 github.com/paritytech/polkadot-sdk

所有者 paritytech/核心开发者 Parity包所有者

内容中提供的示例代码:

// 在Cargo.toml中添加依赖
// sp-keyring = "43.0.0"

use sp_keyring::{AccountKeyring, Sr25519Keyring};

fn main() {
    // 使用预定义的测试账户
    let alice = AccountKeyring::Alice;
    println!("Alice account: {:?}", alice);
    
    // 获取账户的公钥
    let alice_public = alice.to_account_id();
    println!("Alice public key: {:?}", alice_public);
    
    // 使用Sr25519密钥环
    let bob = Sr25519Keyring::Bob;
    println!("Bob account: {:?}", bob);
    
    // 获取签名密钥
    let bob_signing_key = bob.sign(&b"Hello World"[..]);
    println!("Bob signature: {:?}", bob_signing_key);
    
    // 列出所有可用账户
    let all_accounts = AccountKeyring::iter().collect::<Vec<_>>();
    println!("All test accounts: {:?}", all_accounts);
}

完整示例demo:

// 在Cargo.toml中添加依赖
// sp-keyring = "43.0.0"

use sp_keyring::{AccountKeyring, Sr25519Keyring};
use sp_core::crypto::Pair;

fn main() {
    // 演示AccountKeyring的使用
    println!("=== AccountKeyring 演示 ===");
    
    // 使用预定义的测试账户
    let alice = AccountKeyring::Alice;
    println!("Alice账户: {:?}", alice);
    
    // 获取账户的公钥
    let alice_public = alice.to_account_id();
    println!("Alice公钥: {:?}", alice_public);
    
    // 获取账户的SS58地址
    let alice_address = alice.to_account_id().to_ss58check();
    println!("Alice地址: {}", alice_address);
    
    // 演示Sr25519Keyring的使用
    println!("\n=== Sr25519Keyring 演示 ===");
    
    // 使用Sr25519密钥环
    let bob = Sr25519Keyring::Bob;
    println!("Bob账户: {:?}", bob);
    
    // 获取签名密钥对
    let bob_pair = bob.pair();
    println!("Bob密钥对: {:?}", bob_pair);
    
    // 对消息进行签名
    let message = b"Hello Polkadot SDK";
    let bob_signature = bob.sign(message);
    println!("Bob对消息的签名: {:?}", bob_signature);
    
    // 验证签名
    let is_valid = bob_pair.verify(&bob_signature, message);
    println!("签名验证结果: {}", is_valid);
    
    // 列出所有可用测试账户
    println!("\n=== 所有测试账户 ===");
    let all_accounts = AccountKeyring::iter().collect::<Vec<_>>();
    for account in &all_accounts {
        println!("账户: {:?}, 公钥: {:?}", account, account.to_account_id());
    }
    
    // 演示多个账户的操作
    println!("\n=== 多账户操作演示 ===");
    let charlie = AccountKeyring::Charlie;
    let dave = AccountKeyring::Dave;
    
    println!("Charlie账户: {:?}", charlie);
    println!("Dave账户: {:?}", dave);
    
    // 比较不同账户的公钥
    println!("Alice和Bob公钥是否相同: {}", 
             alice.to_account_id() == bob.to_account_id());
}

1 回复

Rust密钥管理库sp-keyring的使用指南

概述

sp-keyring是一个专门用于安全存储和访问加密密钥的Rust插件库。该库提供了跨平台的密钥管理功能,支持Windows、macOS和Linux系统,让开发者能够安全地处理敏感数据。

主要特性

  • 跨平台支持(Windows Credential Manager、macOS Keychain、Linux Secret Service)
  • 线程安全的密钥存储和访问
  • 简单的API设计
  • 零依赖(除平台特定的密钥存储后端外)

安装方法

在Cargo.toml中添加依赖:

[dependencies]
sp-keyring = "0.1"

基本使用方法

1. 存储密钥

use sp_keyring::Keyring;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let keyring = Keyring::new("my-app", "user@example.com")?;
    
    // 存储密钥
    keyring.set_password("my-secret-key")?;
    
    println!("密钥已安全存储");
    Ok(())
}

2. 检索密钥

use sp_keyring::Keyring;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let keyring = Keyring::new("my-app", "user@example.com")?;
    
    // 获取存储的密钥
    match keyring.get_password() {
        Ok(password) => println!("检索到的密钥: {}", password),
        Err(e) => println!("获取密钥失败: {}", e),
    }
    
    Ok(())
}

3. 删除密钥

use sp_keyring::Keyring;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let keyring = Keyring::new("my-app", "user@example.com")?;
    
    // 删除存储的密钥
    keyring.delete_password()?;
    
    println!("密钥已删除");
    Ok(())
}

高级用法示例

处理不同类型的密钥数据

use sp_keyring::Keyring;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct ApiKeys {
    api_key: String,
    secret: String,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let keyring = Keyring::new("my-api-app", "production")?;
    
    // 存储结构化密钥数据
    let keys = ApiKeys {
        api_key: "AKIAIOSFODNN7EXAMPLE".to_string(),
        secret: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY".to_string(),
    };
    
    let serialized = serde_json::to_string(&keys)?;
    keyring.set_password(&serialized)?;
    
    // 检索并反序列化
    if let Ok(stored) = keyring.get_password() {
        let keys: ApiKeys = serde_json::from_str(&stored)?;
        println!("API密钥: {}", keys.api_key);
    }
    
    Ok(())
}

错误处理最佳实践

use sp_keyring::{Keyring, Error};

fn secure_key_operation() -> Result<String, Error> {
    let keyring = Keyring::new("secure-app", "admin")?;
    
    keyring.get_password().map_err(|e| {
        eprintln!("密钥操作失败: {}", e);
        e
    })
}

fn main() {
    match secure_key_operation() {
        Ok(key) => println!("操作成功,密钥: {}", key),
        Err(Error::NoEntry) => println("未找到存储的密钥"),
        Err(Error::PlatformFailure(e)) => eprintln!("平台错误: {}", e),
        Err(e) => eprintln!("其他错误: {}", e),
    }
}

完整示例demo

use sp_keyring::Keyring;
use serde::{Serialize, Deserialize};
use std::error::Error;

// 定义密钥数据结构
#[derive(Serialize, Deserialize, Debug)]
struct AppSecrets {
    database_url: String,
    api_token: String,
    encryption_key: String,
}

fn main() -> Result<(), Box<dyn Error>> {
    // 初始化密钥环,使用应用名称和用户名作为标识
    let keyring = Keyring::new("my-secure-app", "production-user")?;
    
    // 创建要存储的密钥数据
    let secrets = AppSecrets {
        database_url: "postgresql://user:pass@localhost:5432/mydb".to_string(),
        api_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9".to_string(),
        encryption_key: "32-char-long-super-secret-enc-key".to_string(),
    };
    
    // 序列化并存储密钥
    let serialized_secrets = serde_json::to_string(&secrets)?;
    keyring.set_password(&serialized_secrets)?;
    println!("✅ 密钥数据已安全存储");
    
    // 检索密钥数据
    match keyring.get_password() {
        Ok(stored_data) => {
            // 反序列化检索到的数据
            let retrieved_secrets: AppSecrets = serde_json::from_str(&stored_data)?;
            println!("✅ 成功检索到密钥数据");
            println!("数据库URL: {}", retrieved_secrets.database_url);
            println!("API令牌: {}", retrieved_secrets.api_token);
            println!("加密密钥: {}", retrieved_secrets.encryption_key);
            
            // 演示密钥轮换 - 更新加密密钥
            let updated_secrets = AppSecrets {
                encryption_key: "new-32-char-encryption-key-here".to_string(),
                ..retrieved_secrets
            };
            
            let updated_serialized = serde_json::to_string(&updated_secrets)?;
            keyring.set_password(&updated_serialized)?;
            println!("✅ 加密密钥已轮换更新");
        }
        Err(e) => {
            eprintln!("❌ 检索密钥失败: {}", e);
        }
    }
    
    // 清理:删除存储的密钥(在实际应用中谨慎使用)
    // keyring.delete_password()?;
    // println!("密钥已删除");
    
    Ok(())
}

// 错误处理包装函数示例
fn handle_keyring_operations() -> Result<AppSecrets, Box<dyn Error>> {
    let keyring = Keyring::new("my-secure-app", "production-user")?;
    
    match keyring.get_password() {
        Ok(data) => {
            let secrets: AppSecrets = serde_json::from_str(&data)?;
            Ok(secrets)
        }
        Err(sp_keyring::Error::NoEntry) => {
            eprintln!("未找到存储的密钥,请先初始化密钥数据");
            Err("密钥不存在".into())
        }
        Err(e) => {
            eprintln!("密钥操作错误: {}", e);
            Err(e.into())
        }
    }
}

安全注意事项

  1. 访问控制:确保只有授权进程可以访问密钥环
  2. 密钥轮换:定期更新存储的密钥
  3. 错误处理:妥善处理密钥不存在或访问被拒绝的情况
  4. 日志记录:避免在日志中输出敏感密钥信息

平台特定说明

  • Windows:使用Credential Manager存储凭据
  • macOS:使用Keychain Services
  • Linux:使用Secret Service(如GNOME Keyring或KWallet)

这个库为不同平台提供了一致的API,让开发者无需关心底层实现细节即可安全地管理密钥。

回到顶部