Rust YubiKey插件库yubikey的使用,为Rust应用提供安全的硬件身份验证和加密功能

Rust YubiKey插件库yubikey的使用

YubiKey Logo

yubikey.rs是一个纯Rust跨平台主机端驱动,用于Yubico的YubiKey设备,支持使用个人身份验证(PIV)应用程序进行公钥加密和数字签名。

功能特性

个人身份验证(PIV)

PIV是NIST标准,用于使用智能卡和基于智能卡的硬件令牌(如YubiKeys)进行签名和加密。

该库本地实现了用于管理和利用PIV加密和签名密钥的协议,这些密钥可以在YubiKey设备上生成、导入和存储。

支持的算法

  • 认证: 3DES
  • 加密:
    • RSA: RSA1024, RSA2048
    • ECC: ECCP256, ECCP384 (NIST曲线: P-256, P-384)
  • 签名:
    • RSASSA-PKCS#1v1.5: RSA1024, RSA2048
    • ECDSA: ECCP256, ECCP384 (NIST曲线: P-256, P-384)

示例代码

以下是使用yubikey库进行基本操作的示例:

use yubikey::{YubiKey, Management, piv};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    // 连接到第一个可用的YubiKey
    let mut yk = YubiKey::open()?;
    
    // 获取YubiKey信息
    let version = yk.version()?;
    println!("YubiKey版本: {:?}", version);
    
    // 获取序列号
    let serial = yk.serial()?;
    println!("序列号: {}", serial);
    
    // PIV示例 - 生成新密钥
    let slot = piv::Slot::Authentication;
    let algorithm = piv::Algorithm::Rsa2048;
    let pin = Some("123456"); // 默认PIN
    
    yk.generate(slot, algorithm, pin)?;
    println!("在认证槽中生成了RSA2048密钥");
    
    // 使用密钥签名
    let data = b"Hello, YubiKey!";
    let signature = yk.sign(slot, data, pin)?;
    println!("数据签名成功");
    
    Ok(())
}

完整示例

下面是一个更完整的示例,展示如何使用YubiKey进行加密和签名操作:

use yubikey::{YubiKey, Management, piv};
use rsa::{PublicKey, RsaPublicKey};
use sha2::{Sha256, Digest};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    // 初始化YubiKey连接
    let mut yk = YubiKey::open()?;
    
    // 1. 生成或使用现有密钥
    let slot = piv::Slot::Authentication;
    let algorithm = piv::Algorithm::EccP256; // 使用ECC P-256曲线
    let pin = Some("123456"); // 默认PIN
    
    // 检查密钥是否存在,如果不存在则生成
    if yk.get_certificate(slot)?.is_none() {
        yk.generate(slot, algorithm, pin)?;
        println!("生成新的ECC P-256密钥");
    }
    
    // 2. 签名示例
    let message = b"重要数据需要签名";
    let mut hasher = Sha256::new();
    hasher.update(message);
    let hash = hasher.finalize();
    
    let signature = yk.sign(slot, &hash, pin)?;
    println!("签名成功: {:?}", signature);
    
    // 3. 验证签名 (使用公钥)
    if let Some(cert) = yk.get_certificate(slot)? {
        let public_key = RsaPublicKey::try_from(&cert)?;
        
        // 在实际应用中,这里会验证签名
        println!("可以使用公钥验证签名");
    }
    
    // 4. 加密示例 (使用另一个槽位)
    let encryption_slot = piv::Slot::KeyManagement;
    if yk.get_certificate(encryption_slot)?.is_none() {
        yk.generate(encryption_slot, piv::Algorithm::Rsa2048, pin)?;
        println!("生成新的RSA2048加密密钥");
    }
    
    // 在实际应用中,这里会使用公钥加密数据
    println!("可以使用公钥加密数据");
    
    Ok(())
}

系统要求

  • 支持的YubiKeys: YubiKey 4系列, YubiKey 5系列
  • 操作系统: Linux, macOS, Windows
  • Rust版本: 1.60或更新

安全警告

此库尚未进行安全审计,目前处于实验阶段,可能仍包含高严重性问题。使用时请自行承担风险!

测试

要运行完整的测试套件,您需要连接一个处于默认状态(默认PIN/PUK)的YubiKey NEO/4/5设备。

默认情况下,针对YubiKey设备运行的测试被标记为#[ignore],以便在CI环境中通过。要在本地运行这些测试,请使用以下命令:

cargo test -- --ignored

许可证

yubikey.rs采用2-Clause BSD许可证:

Copyright (c) 2014-2023 Yubico AB, Tony Arcieri
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

- Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above
  copyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials provided
  with the distribution.

1 回复

Rust YubiKey插件库yubikey的使用指南

介绍

yubikey是一个Rust库,用于与YubiKey硬件安全设备交互,为Rust应用提供安全的硬件身份验证和加密功能。YubiKey是一种USB/NFC安全密钥,支持多种认证协议和加密操作。

该库提供了以下主要功能:

  • 硬件身份验证
  • 加密/解密操作
  • 数字签名
  • OTP(一次性密码)生成
  • PIV(个人身份验证)功能
  • FIDO U2F/FIDO2认证

使用方法

添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
yubikey = "0.7"

基本示例

1. 查找连接的YubiKey设备

use yubikey::{YubiKey, Manager};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = Manager::new()?;
    let yubikey = manager.connect()?;
    
    println!("Connected to YubiKey: {:?}", yubikey.version());
    Ok(())
}

2. 生成OTP(一次性密码)

use yubikey::{YubiKey, Manager, config::Slot};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = Manager::new()?;
    let mut yubikey = manager.connect()?;
    
    let otp = yubikey.challenge_response_hmac(b"random_challenge", Slot::Slot2)?;
    println!("Generated OTP: {:?}", otp);
    Ok(())
}

3. PIV功能使用(加密/解密)

use yubikey::{YubiKey, Manager, piv::{AlgorithmId, SlotId}};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = Manager::new()?;
    let mut yubikey = manager.connect()?;
    
    // 加密数据
    let data = b"secret message";
    let encrypted = yubikey.encrypt_data(AlgorithmId::Rsa2048, SlotId::Authentication, data)?;
    
    // 解密数据
    let decrypted = yubikey.decrypt_data(AlgorithmId::Rsa2048, SlotId::Authentication, &encrypted)?;
    
    assert_eq!(data, decrypted.as_slice());
    Ok(())
}

4. FIDO2认证

use yubikey::{YubiKey, Manager, fido2};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = Manager::new()?;
    let mut yubikey = manager.connect()?;
    
    // 获取FIDO2信息
    let info = yubikey.fido2_info()?;
    println!("FIDO2 Info: {:?}", info);
    
    // 简单的FIDO2认证示例
    let client data = b"{\"challenge\":\"aGVsbG8gd29ybGQ\",\"origin\":\"https://example.com\"}";
    let rp_id = "example.com";
    let credential_id = vec![0x01, 0x02, 0x03]; // 替换为实际的凭证ID
    
    let assertion = yubikey.fido2_get_assertion(rp_id, client_data, &[credential_id])?;
    println!("Assertion: {:?}", assertion);
    
    Ok(())
}

高级用法

管理多个YubiKey

use yubikey::Manager;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = Manager::new()?;
    let yubikeys = manager.list_devices()?;
    
    for (i, yk) in yubikeys.enumerate() {
        println!("YubiKey #{}: {:?}", i+1, yk.version());
    }
    
    Ok(())
}

自定义配置

use yubikey::{YubiKey, Manager, config::{Config, Slot}};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = Manager::new()?;
    let mut yubikey = manager.connect()?;
    
    // 配置YubiKey
    let config = Config::default()
        .set_vendor_id(0x1050)
        .set_product_id(0x0407);
    
    yubikey.write_config(config)?;
    
    Ok(())
}

完整示例演示

下面是一个综合使用YubiKey多种功能的完整示例:

use yubikey::{YubiKey, Manager, config::Slot, piv::{AlgorithmId, SlotId}, fido2};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 初始化YubiKey管理器
    let manager = Manager::new()?;
    
    // 连接到第一个YubiKey设备
    let mut yubikey = manager.connect()?;
    println!("已连接YubiKey设备,版本: {:?}", yubikey.version());
    
    // 示例1: 生成OTP
    let challenge = b"secure_challenge_123";
    let otp = yubikey.challenge_response_hmac(challenge, Slot::Slot2)?;
    println!("生成的OTP: {:?}", otp);
    
    // 示例2: PIV加密/解密
    let secret_data = b"confidential information";
    println!("原始数据: {:?}", secret_data);
    
    // 使用RSA2048算法加密
    let encrypted = yubikey.encrypt_data(
        AlgorithmId::Rsa2048, 
        SlotId::Authentication, 
        secret_data
    )?;
    println!("加密后数据: {:?}", encrypted);
    
    // 解密数据
    let decrypted = yubikey.decrypt_data(
        AlgorithmId::Rsa2048, 
        SlotId::Authentication, 
        &encrypted
    )?;
    println!("解密后数据: {:?}", decrypted);
    
    assert_eq!(secret_data, decrypted.as_slice());
    
    // 示例3: FIDO2认证
    let fido2_info = yubikey.fido2_info()?;
    println!("FIDO2设备信息: {:?}", fido2_info);
    
    // 模拟FIDO2认证请求
    let client_data = b"{\"challenge\":\"base64_challenge_string\",\"origin\":\"https://yourdomain.com\"}";
    let rp_id = "yourdomain.com";
    let credential_id = vec![0x01, 0x02, 0x03]; // 实际应用中应使用真实的凭证ID
    
    match yubikey.fido2_get_assertion(rp_id, client_data, &[credential_id]) {
        Ok(assertion) => println!("FIDO2认证成功: {:?}", assertion),
        Err(e) => println!("FIDO2认证失败: {}", e),
    }
    
    Ok(())
}

注意事项

  1. 使用前确保系统已安装libusbpcsc-lite(Linux/macOS)
  2. Windows用户可能需要安装YubiKey官方驱动
  3. 某些操作需要YubiKey管理员权限
  4. 生产环境中应妥善处理错误和敏感数据
回到顶部