Rust YubiKey安全认证库yubico的使用,支持硬件密钥管理和双因素身份验证

Rust YubiKey安全认证库yubico的使用,支持硬件密钥管理和双因素身份验证

该库实现了与Yubico验证平台的集成,允许在Rust应用中使用Yubikey的一次性密码,支持用户通过Yubikey进行身份验证。

当前功能

  • [x] 同步Yubikey客户端API库,支持验证协议2.0版本
  • [x] 基于Tokio的异步Yubikey客户端API库

注意: USB相关功能已移至单独的仓库yubico-manager

使用方式

在Cargo.toml中添加:

[dependencies]
yubico = "0.9"

可选的Cargo特性:

  • online-tokio (默认启用):提供与Tokio的集成,使用futures。

可以像下面这样启用或禁用特性:

[dependencies.yubico]
version = "0.9"
# 不包含默认特性(online-tokio)
default-features = false
# 选择特定特性
features = []

使用默认服务器的OTP验证

extern crate yubico;

use yubico::config::*;
use yubico::verify;

fn main() {
   let config = Config::default()
       .set_client_id("CLIENT_ID")
       .set_key("API_KEY");

   match verify("OTP", config) {
      Ok(answer) => println!("{}", answer),
      Err(e) => println!("Error: {}", e),
   }
}

使用自定义API服务器的OTP验证

extern crate yubico;

use yubico::verify;
use yubico::config::*;

fn main() {
   let config = Config::default()
       .set_client_id("CLIENT_ID")
       .set_key("API_KEY")
       .set_api_hosts(vec!["https://api.example.com/verify".into()]);

   match verify("OTP", config) {
      Ok(answer) => println!("{}", answer),
      Err(e) => println!("Error: {}", e),
   }
}

异步OTP验证

#![recursion_limit="128"]
extern crate futures;
extern crate tokio;
extern crate yubico;

use futures::future::Future;
use yubico::verify_async;
extern crate yubico;

use std::io::stdin;
use yubico::config::Config;

fn main() {
    println!("Please plug in a yubikey and enter an OTP");

    let client_id = std::env::var("YK_CLIENT_ID")
        .expect("Please set a value to the YK_CLIENT_ID environment variable.");

    let api_key = std::env::var("YK_API_KEY")
        .expect("Please set a value to the YK_API_KEY environment variable.");

    let otp = read_user_input();

    let config = Config::default()
        .set_client_id(client_id)
        .set_key(api_key);

    tokio::run(verify_async(otp, config)
        .unwrap()
        .map(|_|{
            println!("Valid OTP.");
        })
        .map_err(|err|{
            println!("Invalid OTP. Cause: {:?}", err);
        }))
}

fn read_user_input() -> String {
    let mut buf = String::new();

    stdin()
        .read_line(&mut buf)
        .expect("Could not read user input.");

    buf
}

完整示例代码

下面是一个完整的YubiKey双因素认证示例:

use yubico::config::*;
use yubico::verify;
use std::env;

fn main() {
    // 从环境变量获取API凭证
    let client_id = env::var("YUBICO_CLIENT_ID").expect("YUBICO_CLIENT_ID not set");
    let api_key = env::var("YUBICO_API_KEY").expect("YUBICO_API_KEY not set");
    
    // 从用户输入获取OTP
    println!("Please enter your YubiKey OTP:");
    let mut otp = String::new();
    std::io::stdin().read_line(&mut otp).expect("Failed to read input");
    let otp = otp.trim();
    
    // 配置验证器
    let config = Config::default()
        .set_client_id(&client_id)
        .set_key(&api_key);
    
    // 执行验证
    match verify(otp, config) {
        Ok(answer) => {
            if answer.status == "OK" {
                println!("Authentication successful!");
                println!("Identity: {}", answer.identity);
            } else {
                println!("Authentication failed: {}", answer.status);
            }
        },
        Err(e) => println!("Error verifying OTP: {}", e),
    }
}

变更日志

- 0.10.0: 升级到 tokio 1.1 和 reqwest 0.11
- 0.9.2: (已撤回) 依赖更新
- 0.9.1: 设置HTTP代理(基本认证可选)
- 0.9.0: 迁移到 tokio 0.2 和 reqwest 0.10
- 0.9.0-alpha.1: 迁移到 futures 0.3.0-alpha.19
- 0.8: 将 sync 和 async 模块重命名为 sync_verifier 和 async_verifier,以避免使用保留关键字 async

安装

在项目目录中运行以下Cargo命令:

cargo add yubico

或者在Cargo.toml中添加以下行:

yubico = "0.11.0"

1 回复

Rust YubiKey安全认证库yubico的使用指南

介绍

yubico是一个Rust库,用于与YubiKey硬件安全设备交互,支持硬件密钥管理和双因素身份验证(2FA)。它提供了与YubiKey设备通信的接口,可以用于生成OTP(一次性密码)、管理PIV功能等安全操作。

主要功能

  • YubiKey OTP验证
  • PIV(智能卡)功能管理
  • HMAC-SHA1挑战/响应
  • 设备状态检测和管理

使用方法

添加依赖

Cargo.toml中添加:

[dependencies]
yubico = "0.10"

基本示例:验证YubiKey OTP

use yubico::config::{Config, Slot};
use yubico::verify;

fn main() {
    let config = Config::default()
        .set_client_id("CLIENT_ID")  // 从Yubico获取
        .set_key("API_KEY")          // 从Yubico获取
        .set_api_hosts(vec!["api.yubico.com".into()]);

    let otp = "ccccccbcgklhfvftjfnhfchvthvuitvkllkcudkic"; // 从YubiKey获取的OTP
    
    match verify(otp, config) {
        Ok(answer) => println!("验证成功: {:?}", answer),
        Err(e) => println!("验证失败: {:?}", e),
    }
}

使用PIV功能管理密钥

use yubico::piv::{AlgorithmId, SlotId, YubiKey};
use yubico::management::Device;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 查找连接的YubiKey
    let mut yk = YubiKey::open()?;
    
    // 生成新密钥对
    yk.generate(
        AlgorithmId::Rsa2048,
        SlotId::Authentication,
        None, // 可选PIN策略
    )?;
    
    // 导出公钥
    let public_key = yk.fetch_certificate(SlotId::Authentication)?;
    println!("公钥: {:?}", public_key);
    
    Ok(())
}

HMAC-SHA1挑战/响应示例

use yubico::hmacmode::{Config, Slot};
use yubico::configure;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 配置HMAC-SHA1
    let config = Config::default()
        .set_vendor_id(0x1050)
        .set_product_id(0x0030)
        .set_variable_size(true)
        .set_challenge("my_challenge".to_string())
        .set_slot(Slot::Slot2);
    
    // 连接到YubiKey
    let mut device = configure::find_yubikey()?;
    
    // 发送挑战并获取响应
    let result = configure::challenge_response_hmac(&mut device, &config)?;
    println!("HMAC响应: {:?}", result);
    
    Ok(())
}

高级用法

枚举所有连接的YubiKey设备

use yubico::manager::get_yubikeys;

fn main() {
    match get_yubikeys() {
        Ok(devices) => {
            println!("找到 {} 个YubiKey设备:", devices.len());
            for (i, device) in devices.iter().enumerate() {
                println!("{}: {:?}", i+1, device);
            }
        }
        Err(e) => println!("错误: {:?}", e),
    }
}

双因素认证集成示例

use yubico::config::Config;
use yubico::verify;

struct User {
    username: String,
    password: String,
    yubikey_id: Option<String>,
}

fn two_factor_auth(user: &User, otp: Option<&str>) -> bool {
    // 第一步:验证用户名和密码
    if user.username != "admin" || user.password != "secure123" {
        return false;
    }
    
    // 第二步:如果用户有YubiKey,验证OTP
    if let Some(id) = &user.yubikey_id {
        if let Some(otp_code) = otp {
            let config = Config::default()
                .set_client_id("CLIENT_ID")
                .set_key("API_KEY");
            
            return verify(otp_code, config).is_ok();
        }
        return false;
    }
    
    true // 没有YubiKey的用户只需要用户名/密码
}

fn main() {
    let user_with_yubikey = User {
        username: "admin".to_string(),
        password: "secure123".to_string(),
        yubikey_id: Some("ccccccbcgklh".to_string()),
    };
    
    let otp = "ccccccbcgklhfvftjfnhfchvthvuitvkllkcudkic";
    println!("认证结果: {}", two_factor_auth(&user_with_yubikey, Some(otp)));
}

完整示例:YubiKey综合使用

use yubico::{
    config::Config,
    verify,
    piv::{AlgorithmId, SlotId, YubiKey},
    hmacmode::{Config as HmacConfig, Slot},
    configure,
    manager::get_yubikeys
};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    // 1. 枚举所有连接的YubiKey设备
    println!("=== 枚举YubiKey设备 ===");
    let devices = get_yubikeys()?;
    println!("找到 {} 个YubiKey设备:", devices.len());
    for (i, device) in devices.iter().enumerate() {
        println!("{}: {:?}", i+1, device);
    }

    // 2. OTP验证示例
    println!("\n=== OTP验证示例 ===");
    let otp_config = Config::default()
        .set_client_id("CLIENT_ID")
        .set_key("API_KEY");
    
    let otp = "ccccccbcgklhfvftjfnhfchvthvuitvkllkcudkic";
    match verify(otp, otp_config) {
        Ok(answer) => println!("OTP验证成功: {:?}", answer),
        Err(e) => println!("OTP验证失败: {:?}", e),
    }

    // 3. PIV功能管理
    println!("\n=== PIV功能管理 ===");
    let mut yk = YubiKey::open()?;
    
    // 生成RSA2048密钥对
    yk.generate(AlgorithmId::Rsa2048, SlotId::Authentication, None)?;
    
    // 获取证书
    let cert = yk.fetch_certificate(SlotId::Authentication)?;
    println!("认证槽证书: {:?}", cert);

    // 4. HMAC-SHA1挑战/响应
    println!("\n=== HMAC-SHA1挑战/响应 ===");
    let hmac_config = HmacConfig::default()
        .set_vendor_id(0x1050)
        .set_product_id(0x0030)
        .set_variable_size(true)
        .set_challenge("secure_challenge".to_string())
        .set_slot(Slot::Slot2);
    
    let mut device = configure::find_yubikey()?;
    let hmac_result = configure::challenge_response_hmac(&mut device, &hmac_config)?;
    println!("HMAC响应: {:?}", hmac_result);

    Ok(())
}

注意事项

  1. 使用OTP验证功能需要从Yubico获取API密钥
  2. 某些功能需要YubiKey设备支持特定功能
  3. 生产环境中应考虑错误处理和重试机制
  4. 密钥管理操作需要适当的权限和PIN码

通过这个库,Rust开发者可以轻松地将YubiKey硬件安全功能集成到他们的应用程序中,增强安全性并支持双因素认证。

回到顶部