NAC_Blockchain/nac-wallet-core/src/hardware.rs

667 lines
19 KiB
Rust

//! 硬件钱包集成模块
//!
//! 实现Ledger和Trezor硬件钱包支持、通信协议和设备管理
use crate::WalletError;
use std::collections::HashMap;
/// 硬件钱包类型
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum HardwareWalletType {
/// Ledger Nano S
LedgerNanoS,
/// Ledger Nano X
LedgerNanoX,
/// Trezor One
TrezorOne,
/// Trezor Model T
TrezorModelT,
}
impl HardwareWalletType {
/// 获取设备名称
pub fn name(&self) -> &'static str {
match self {
HardwareWalletType::LedgerNanoS => "Ledger Nano S",
HardwareWalletType::LedgerNanoX => "Ledger Nano X",
HardwareWalletType::TrezorOne => "Trezor One",
HardwareWalletType::TrezorModelT => "Trezor Model T",
}
}
/// 是否为Ledger设备
pub fn is_ledger(&self) -> bool {
matches!(self, HardwareWalletType::LedgerNanoS | HardwareWalletType::LedgerNanoX)
}
/// 是否为Trezor设备
pub fn is_trezor(&self) -> bool {
matches!(self, HardwareWalletType::TrezorOne | HardwareWalletType::TrezorModelT)
}
}
/// 设备连接状态
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeviceStatus {
/// 已连接
Connected,
/// 已断开
Disconnected,
/// 锁定中
Locked,
/// 错误
Error,
}
/// 硬件钱包设备
#[derive(Debug, Clone)]
pub struct HardwareDevice {
/// 设备ID
pub id: String,
/// 设备类型
pub device_type: HardwareWalletType,
/// 固件版本
pub firmware_version: String,
/// 序列号
pub serial_number: String,
/// 连接状态
pub status: DeviceStatus,
/// 支持的币种
pub supported_coins: Vec<String>,
}
impl HardwareDevice {
/// 创建新设备
pub fn new(
id: String,
device_type: HardwareWalletType,
firmware_version: String,
serial_number: String
) -> Self {
let supported_coins = match device_type {
HardwareWalletType::LedgerNanoS | HardwareWalletType::LedgerNanoX => {
vec!["BTC".to_string(), "ETH".to_string(), "NAC".to_string()]
}
HardwareWalletType::TrezorOne | HardwareWalletType::TrezorModelT => {
vec!["BTC".to_string(), "ETH".to_string(), "NAC".to_string()]
}
};
HardwareDevice {
id,
device_type,
firmware_version,
serial_number,
status: DeviceStatus::Disconnected,
supported_coins,
}
}
/// 检查是否支持币种
pub fn supports_coin(&self, coin: &str) -> bool {
self.supported_coins.iter().any(|c| c == coin)
}
}
/// 通信协议
pub trait CommunicationProtocol {
/// 连接设备
fn connect(&mut self) -> Result<(), WalletError>;
/// 断开设备
fn disconnect(&mut self) -> Result<(), WalletError>;
/// 发送命令
fn send_command(&self, command: &[u8]) -> Result<Vec<u8>, WalletError>;
/// 获取设备信息
fn get_device_info(&self) -> Result<HardwareDevice, WalletError>;
}
/// Ledger通信协议
pub struct LedgerProtocol {
device_id: String,
connected: bool,
}
impl LedgerProtocol {
/// 创建新的Ledger协议实例
pub fn new(device_id: String) -> Self {
LedgerProtocol {
device_id,
connected: false,
}
}
/// Ledger APDU命令
fn apdu_command(&self, cla: u8, ins: u8, p1: u8, p2: u8, data: &[u8]) -> Vec<u8> {
let mut command = vec![cla, ins, p1, p2, data.len() as u8];
command.extend_from_slice(data);
command
}
}
impl CommunicationProtocol for LedgerProtocol {
fn connect(&mut self) -> Result<(), WalletError> {
// 模拟连接
self.connected = true;
Ok(())
}
fn disconnect(&mut self) -> Result<(), WalletError> {
self.connected = false;
Ok(())
}
fn send_command(&self, command: &[u8]) -> Result<Vec<u8>, WalletError> {
if !self.connected {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
// 模拟命令响应
Ok(vec![0x90, 0x00]) // 成功响应
}
fn get_device_info(&self) -> Result<HardwareDevice, WalletError> {
if !self.connected {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
Ok(HardwareDevice::new(
self.device_id.clone(),
HardwareWalletType::LedgerNanoX,
"2.1.0".to_string(),
"LEDGER123456".to_string()
))
}
}
/// Trezor通信协议
pub struct TrezorProtocol {
device_id: String,
connected: bool,
}
impl TrezorProtocol {
/// 创建新的Trezor协议实例
pub fn new(device_id: String) -> Self {
TrezorProtocol {
device_id,
connected: false,
}
}
/// Trezor消息编码
fn encode_message(&self, message_type: u16, data: &[u8]) -> Vec<u8> {
let mut encoded = vec![0x23, 0x23]; // 魔术头
encoded.extend_from_slice(&message_type.to_be_bytes());
encoded.extend_from_slice(&(data.len() as u32).to_be_bytes());
encoded.extend_from_slice(data);
encoded
}
}
impl CommunicationProtocol for TrezorProtocol {
fn connect(&mut self) -> Result<(), WalletError> {
self.connected = true;
Ok(())
}
fn disconnect(&mut self) -> Result<(), WalletError> {
self.connected = false;
Ok(())
}
fn send_command(&self, command: &[u8]) -> Result<Vec<u8>, WalletError> {
if !self.connected {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
// 模拟命令响应
Ok(vec![0x00, 0x01]) // 成功响应
}
fn get_device_info(&self) -> Result<HardwareDevice, WalletError> {
if !self.connected {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
Ok(HardwareDevice::new(
self.device_id.clone(),
HardwareWalletType::TrezorModelT,
"2.4.0".to_string(),
"TREZOR789012".to_string()
))
}
}
/// 硬件钱包操作
pub trait HardwareWalletOps {
/// 获取公钥
fn get_public_key(&self, path: &str) -> Result<Vec<u8>, WalletError>;
/// 签名交易
fn sign_transaction(&self, path: &str, transaction: &[u8]) -> Result<Vec<u8>, WalletError>;
/// 签名消息
fn sign_message(&self, path: &str, message: &[u8]) -> Result<Vec<u8>, WalletError>;
/// 验证地址
fn verify_address(&self, path: &str, address: &str) -> Result<bool, WalletError>;
}
/// Ledger钱包操作
pub struct LedgerWallet {
protocol: LedgerProtocol,
device: Option<HardwareDevice>,
}
impl LedgerWallet {
/// 创建新的Ledger钱包
pub fn new(device_id: String) -> Self {
LedgerWallet {
protocol: LedgerProtocol::new(device_id),
device: None,
}
}
/// 连接设备
pub fn connect(&mut self) -> Result<(), WalletError> {
self.protocol.connect()?;
self.device = Some(self.protocol.get_device_info()?);
Ok(())
}
/// 断开设备
pub fn disconnect(&mut self) -> Result<(), WalletError> {
self.protocol.disconnect()?;
self.device = None;
Ok(())
}
/// 获取设备信息
pub fn device(&self) -> Option<&HardwareDevice> {
self.device.as_ref()
}
}
impl HardwareWalletOps for LedgerWallet {
fn get_public_key(&self, path: &str) -> Result<Vec<u8>, WalletError> {
if self.device.is_none() {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
// 构造获取公钥命令
let command = vec![0x80, 0x02, 0x00, 0x00, path.len() as u8];
let _response = self.protocol.send_command(&command)?;
// 模拟返回公钥
Ok(vec![0x04; 65]) // 未压缩公钥
}
fn sign_transaction(&self, path: &str, transaction: &[u8]) -> Result<Vec<u8>, WalletError> {
if self.device.is_none() {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
// 构造签名命令
let mut command = vec![0x80, 0x04, 0x00, 0x00];
command.push((path.len() + transaction.len()) as u8);
command.extend_from_slice(path.as_bytes());
command.extend_from_slice(transaction);
let _response = self.protocol.send_command(&command)?;
// 模拟返回签名
Ok(vec![0x30; 71]) // DER编码签名
}
fn sign_message(&self, path: &str, message: &[u8]) -> Result<Vec<u8>, WalletError> {
if self.device.is_none() {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
// 构造签名消息命令
let mut command = vec![0x80, 0x08, 0x00, 0x00];
command.push((path.len() + message.len()) as u8);
command.extend_from_slice(path.as_bytes());
command.extend_from_slice(message);
let _response = self.protocol.send_command(&command)?;
// 模拟返回签名
Ok(vec![0x30; 71])
}
fn verify_address(&self, path: &str, address: &str) -> Result<bool, WalletError> {
if self.device.is_none() {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
// 获取公钥并验证地址
let _public_key = self.get_public_key(path)?;
// 模拟地址验证
Ok(address.starts_with("0x"))
}
}
/// Trezor钱包操作
pub struct TrezorWallet {
protocol: TrezorProtocol,
device: Option<HardwareDevice>,
}
impl TrezorWallet {
/// 创建新的Trezor钱包
pub fn new(device_id: String) -> Self {
TrezorWallet {
protocol: TrezorProtocol::new(device_id),
device: None,
}
}
/// 连接设备
pub fn connect(&mut self) -> Result<(), WalletError> {
self.protocol.connect()?;
self.device = Some(self.protocol.get_device_info()?);
Ok(())
}
/// 断开设备
pub fn disconnect(&mut self) -> Result<(), WalletError> {
self.protocol.disconnect()?;
self.device = None;
Ok(())
}
/// 获取设备信息
pub fn device(&self) -> Option<&HardwareDevice> {
self.device.as_ref()
}
}
impl HardwareWalletOps for TrezorWallet {
fn get_public_key(&self, path: &str) -> Result<Vec<u8>, WalletError> {
if self.device.is_none() {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
// 构造获取公钥消息
let message = self.protocol.encode_message(11, path.as_bytes());
let _response = self.protocol.send_command(&message)?;
// 模拟返回公钥
Ok(vec![0x04; 65])
}
fn sign_transaction(&self, path: &str, transaction: &[u8]) -> Result<Vec<u8>, WalletError> {
if self.device.is_none() {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
// 构造签名消息
let mut data = path.as_bytes().to_vec();
data.extend_from_slice(transaction);
let message = self.protocol.encode_message(15, &data);
let _response = self.protocol.send_command(&message)?;
// 模拟返回签名
Ok(vec![0x30; 71])
}
fn sign_message(&self, path: &str, message: &[u8]) -> Result<Vec<u8>, WalletError> {
if self.device.is_none() {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
// 构造签名消息
let mut data = path.as_bytes().to_vec();
data.extend_from_slice(message);
let msg = self.protocol.encode_message(38, &data);
let _response = self.protocol.send_command(&msg)?;
// 模拟返回签名
Ok(vec![0x30; 71])
}
fn verify_address(&self, path: &str, address: &str) -> Result<bool, WalletError> {
if self.device.is_none() {
return Err(WalletError::NetworkError("Device not connected".to_string()));
}
// 获取公钥并验证地址
let _public_key = self.get_public_key(path)?;
// 模拟地址验证
Ok(address.starts_with("0x"))
}
}
/// 设备管理器
pub struct DeviceManager {
/// 已连接的设备
devices: HashMap<String, Box<dyn std::any::Any>>,
/// 设备信息
device_info: HashMap<String, HardwareDevice>,
}
impl DeviceManager {
/// 创建新的设备管理器
pub fn new() -> Self {
DeviceManager {
devices: HashMap::new(),
device_info: HashMap::new(),
}
}
/// 扫描设备
pub fn scan_devices(&mut self) -> Result<Vec<HardwareDevice>, WalletError> {
// 模拟扫描设备
let devices = vec![
HardwareDevice::new(
"ledger_001".to_string(),
HardwareWalletType::LedgerNanoX,
"2.1.0".to_string(),
"LEDGER123456".to_string()
),
HardwareDevice::new(
"trezor_001".to_string(),
HardwareWalletType::TrezorModelT,
"2.4.0".to_string(),
"TREZOR789012".to_string()
),
];
for device in &devices {
self.device_info.insert(device.id.clone(), device.clone());
}
Ok(devices)
}
/// 连接Ledger设备
pub fn connect_ledger(&mut self, device_id: String) -> Result<(), WalletError> {
let mut wallet = LedgerWallet::new(device_id.clone());
wallet.connect()?;
if let Some(device) = wallet.device() {
self.device_info.insert(device_id.clone(), device.clone());
}
self.devices.insert(device_id, Box::new(wallet));
Ok(())
}
/// 连接Trezor设备
pub fn connect_trezor(&mut self, device_id: String) -> Result<(), WalletError> {
let mut wallet = TrezorWallet::new(device_id.clone());
wallet.connect()?;
if let Some(device) = wallet.device() {
self.device_info.insert(device_id.clone(), device.clone());
}
self.devices.insert(device_id, Box::new(wallet));
Ok(())
}
/// 断开设备
pub fn disconnect(&mut self, device_id: &str) -> Result<(), WalletError> {
self.devices.remove(device_id);
if let Some(device) = self.device_info.get_mut(device_id) {
device.status = DeviceStatus::Disconnected;
}
Ok(())
}
/// 获取设备信息
pub fn get_device(&self, device_id: &str) -> Option<&HardwareDevice> {
self.device_info.get(device_id)
}
/// 获取所有设备
pub fn list_devices(&self) -> Vec<&HardwareDevice> {
self.device_info.values().collect()
}
/// 检查设备是否已连接
pub fn is_connected(&self, device_id: &str) -> bool {
self.devices.contains_key(device_id)
}
}
impl Default for DeviceManager {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hardware_wallet_type() {
let ledger = HardwareWalletType::LedgerNanoX;
assert!(ledger.is_ledger());
assert!(!ledger.is_trezor());
let trezor = HardwareWalletType::TrezorModelT;
assert!(trezor.is_trezor());
assert!(!trezor.is_ledger());
}
#[test]
fn test_hardware_device_creation() {
let device = HardwareDevice::new(
"test_001".to_string(),
HardwareWalletType::LedgerNanoX,
"2.1.0".to_string(),
"SERIAL123".to_string()
);
assert_eq!(device.id, "test_001");
assert_eq!(device.status, DeviceStatus::Disconnected);
assert!(device.supports_coin("NAC"));
}
#[test]
fn test_ledger_protocol() {
let mut protocol = LedgerProtocol::new("test_001".to_string());
assert!(protocol.connect().is_ok());
assert!(protocol.disconnect().is_ok());
}
#[test]
fn test_trezor_protocol() {
let mut protocol = TrezorProtocol::new("test_001".to_string());
assert!(protocol.connect().is_ok());
assert!(protocol.disconnect().is_ok());
}
#[test]
fn test_ledger_wallet() {
let mut wallet = LedgerWallet::new("test_001".to_string());
assert!(wallet.connect().is_ok());
assert!(wallet.device().is_some());
assert!(wallet.disconnect().is_ok());
}
#[test]
fn test_trezor_wallet() {
let mut wallet = TrezorWallet::new("test_001".to_string());
assert!(wallet.connect().is_ok());
assert!(wallet.device().is_some());
assert!(wallet.disconnect().is_ok());
}
#[test]
fn test_get_public_key() {
let mut wallet = LedgerWallet::new("test_001".to_string());
wallet.connect().unwrap();
let pubkey = wallet.get_public_key("m/44'/60'/0'/0/0").unwrap();
assert_eq!(pubkey.len(), 65);
}
#[test]
fn test_sign_transaction() {
let mut wallet = LedgerWallet::new("test_001".to_string());
wallet.connect().unwrap();
let signature = wallet.sign_transaction("m/44'/60'/0'/0/0", &[1, 2, 3]).unwrap();
assert_eq!(signature.len(), 71);
}
#[test]
fn test_sign_message() {
let mut wallet = TrezorWallet::new("test_001".to_string());
wallet.connect().unwrap();
let signature = wallet.sign_message("m/44'/60'/0'/0/0", b"Hello").unwrap();
assert_eq!(signature.len(), 71);
}
#[test]
fn test_verify_address() {
let mut wallet = LedgerWallet::new("test_001".to_string());
wallet.connect().unwrap();
let valid = wallet.verify_address("m/44'/60'/0'/0/0", "0x1234567890").unwrap();
assert!(valid);
}
#[test]
fn test_device_manager() {
let mut manager = DeviceManager::new();
let devices = manager.scan_devices().unwrap();
assert_eq!(devices.len(), 2);
}
#[test]
fn test_connect_ledger() {
let mut manager = DeviceManager::new();
assert!(manager.connect_ledger("ledger_001".to_string()).is_ok());
assert!(manager.is_connected("ledger_001"));
}
#[test]
fn test_connect_trezor() {
let mut manager = DeviceManager::new();
assert!(manager.connect_trezor("trezor_001".to_string()).is_ok());
assert!(manager.is_connected("trezor_001"));
}
#[test]
fn test_disconnect_device() {
let mut manager = DeviceManager::new();
manager.connect_ledger("ledger_001".to_string()).unwrap();
assert!(manager.disconnect("ledger_001").is_ok());
assert!(!manager.is_connected("ledger_001"));
}
#[test]
fn test_list_devices() {
let mut manager = DeviceManager::new();
manager.scan_devices().unwrap();
let devices = manager.list_devices();
assert_eq!(devices.len(), 2);
}
}