Rust YubiKey插件库yubikey的使用,为Rust应用提供安全的硬件身份验证和加密功能
Rust YubiKey插件库yubikey的使用
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(())
}
注意事项
- 使用前确保系统已安装
libusb
或pcsc-lite
(Linux/macOS) - Windows用户可能需要安装YubiKey官方驱动
- 某些操作需要YubiKey管理员权限
- 生产环境中应妥善处理错误和敏感数据