15 unstable releases (5 breaking)

0.6.1 Jun 29, 2019
0.5.1 Jan 13, 2019
0.4.2 Nov 17, 2018
0.4.0 Jun 28, 2018
0.1.1 Dec 2, 2016

#6 in Authentication

Download history 84/week @ 2019-04-15 56/week @ 2019-04-22 93/week @ 2019-04-29 101/week @ 2019-05-06 105/week @ 2019-05-13 138/week @ 2019-05-20 127/week @ 2019-05-27 85/week @ 2019-06-03 63/week @ 2019-06-10 146/week @ 2019-06-17 253/week @ 2019-06-24 194/week @ 2019-07-01 129/week @ 2019-07-08 76/week @ 2019-07-15 77/week @ 2019-07-22

473 downloads per month

MIT/Apache

55KB
1.5K SLoC

Yubico   Build Status Latest Version MIT licensed Apache-2.0 licensed

Enables integration with the Yubico validation platform, so you can use Yubikey's one-time-password in your Rust application, allowing a user to authenticate via Yubikey.


Current features

Usage

Add this to your Cargo.toml

[dependencies]
yubico = "0.6"

The following are a list of Cargo features that can be enabled or disabled:

  • online (enabled by default): Provides TLS support via Reqwest to connect over HTTPS in order to validate OTP against the yubico/custom servers. On Linux, it will use OpenSSL 1.1.
  • online-tokio (enabled by default): Provides integration to Tokio using futures.
  • usb (enabled by default): Provides USB support via libusb. It can safely be disabled when using the library to do only OTP with servers.

You can enable or disable them using the example below:

[dependencies.yubico]
version = "0.6"
# don't include the default features (online)
default-features = false
# cherry-pick individual features
features = []

Request your api key.

OTP with Default Servers

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),
   }
}

OTP with custom API servers

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),
   }
}

Configure Yubikey (HMAC-SHA1 mode)

Note, please read about the initial configuration Alternatively you can configure the yubikey with the official Yubikey Personalization GUI.

extern crate rand;
extern crate yubico;

use yubico::{Yubico};
use yubico::config::{Config, Command};
use yubico::configure::{ DeviceModeConfig };
use yubico::hmacmode::{ HmacKey };
use rand::{thread_rng, Rng};
use rand::distributions::{Alphanumeric};

fn main() {
   let mut yubi = Yubico::new();

   if let Ok(device) = yubi.find_yubikey() {
       println!("Vendor ID: {:?} Product ID {:?}", device.vendor_id, device.product_id);

       let config = Config::default()
           .set_vendor_id(device.vendor_id)
           .set_product_id(device.product_id)
           .set_command(Command::Configuration2);

        let mut rng = thread_rng();

        // Secret must have 20 bytes
        // Used rand here, but you can set your own secret: let secret: &[u8; 20] = b"my_awesome_secret_20";
        let secret: String = rng.sample_iter(&Alphanumeric).take(20).collect();
        let hmac_key: HmacKey = HmacKey::from_slice(secret.as_bytes());

        let mut device_config = DeviceModeConfig::default();
        device_config.challenge_response_hmac(&hmac_key, false, false);

        if let Err(err) = yubi.write_config(config, &mut device_config) {
            println!("{:?}", err);
        } else {
            println!("Device configured");
        }

   } else {
       println!("Yubikey not found");
   }
}

Example Challenge-Response (HMAC-SHA1 mode)

Configure the yubikey with Yubikey Personalization GUI

extern crate hex;
extern crate yubico;

use std::ops::Deref;
use yubico::{Yubico};
use yubico::config::{Config, Slot, Mode};

fn main() {
   let mut yubi = Yubico::new();

   if let Ok(device) = yubi.find_yubikey() {
       println!("Vendor ID: {:?} Product ID {:?}", device.vendor_id, device.product_id);

       let config = Config::default()
           .set_vendor_id(device.vendor_id)
           .set_product_id(device.product_id)
           .set_variable_size(true)
           .set_mode(Mode::Sha1)
           .set_slot(Slot::Slot2);

       // Challenge can not be greater than 64 bytes
       let challenge = String::from("mychallenge");
       // In HMAC Mode, the result will always be the SAME for the SAME provided challenge
       let hmac_result= yubi.challenge_response_hmac(challenge.as_bytes(), config).unwrap();

       // Just for debug, lets check the hex
       let v: &[u8] = hmac_result.deref();
       let hex_string = hex::encode(v);

       println!("{}", hex_string);

   } else {
       println!("Yubikey not found");
   }
}

Dependencies

~2.2–5MB
~106K SLoC