From 6a66c3a5a639d5b02e89cceaa28039023453526f Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Fri, 2 Jul 2021 00:12:31 +0800 Subject: [PATCH] feat: sign works --- Cargo.lock | 7 ++++ Cargo.toml | 1 + src/register.rs | 5 +-- src/sign.rs | 92 +++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 101 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04b6ca5..e10d001 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,6 +185,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "itoa" version = "0.4.7" @@ -554,6 +560,7 @@ dependencies = [ "authenticator", "base64", "clap", + "hex", "rand 0.8.4", "rust_util", "serde", diff --git a/Cargo.toml b/Cargo.toml index e18a57f..f09276e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,4 @@ rand = "0.8" base64 = "0.13" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +hex = "0.4" diff --git a/src/register.rs b/src/register.rs index 9a4ad8e..79c83d3 100644 --- a/src/register.rs +++ b/src/register.rs @@ -4,7 +4,7 @@ use authenticator::authenticatorservice::AuthenticatorService; use authenticator::statecallback::StateCallback; use authenticator::{RegisterFlags, StatusUpdate}; use sha2::{Digest, Sha256}; -use std::sync::mpsc::{channel, RecvError}; +use std::sync::mpsc::channel; use std::thread; use rust_util::XResult; use rand::Rng; @@ -85,7 +85,7 @@ impl Command for CommandImpl { Ok(StatusUpdate::Success { dev_info }) => { debugging!("STATUS: success using device: {}", dev_info); } - Err(RecvError) => { + Err(_recv_error) => { debugging!("STATUS: end"); return; } @@ -116,6 +116,7 @@ impl Command for CommandImpl { success!("Device info: {}", &device_info); let credential = u2f_get_key_handle_from_register_response(®ister_data).unwrap(); success!("Key handle: {}", base64::encode(&credential)); + success!("Key handle: {}", hex::encode(&credential)); Ok(()) } diff --git a/src/sign.rs b/src/sign.rs index f5e9436..4c5c67d 100644 --- a/src/sign.rs +++ b/src/sign.rs @@ -1,5 +1,11 @@ -use clap::{ArgMatches, SubCommand, App}; +use clap::{ArgMatches, SubCommand, App, Arg}; use crate::cmd::{Command, CommandError}; +use authenticator::{KeyHandle, AuthenticatorTransports, SignFlags, StatusUpdate}; +use std::sync::mpsc::channel; +use authenticator::statecallback::StateCallback; +use authenticator::authenticatorservice::AuthenticatorService; +use sha2::{Sha256, Digest}; +use std::thread; pub struct CommandImpl; @@ -7,8 +13,90 @@ impl Command for CommandImpl { fn name(&self) -> &str { "sign" } fn subcommand<'a>(&self) -> App<'a, 'a> { SubCommand::with_name(self.name()).about("Sign subcommand") + .arg(Arg::with_name("app-id").long("app-id").default_value("https://example.com").help("App id")) + .arg(Arg::with_name("key-handle").long("key-handle").takes_value(true).help("Key handle")) } - fn run(&self, _arg_matches: &ArgMatches, _sub_arg_matches: &ArgMatches) -> CommandError { + fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { + let app_id = sub_arg_matches.value_of("app-id").unwrap(); + let key_handle = opt_value_result!( sub_arg_matches.value_of("key-handle"), "Key handle is required"); + + // opt_result!(hex::decode(key_handle),"{}", ""); + let credential = match hex::decode(key_handle) { + Ok(c) => c, + Err(e) => return simple_error!("Key handle decode failed: {}", e), + }; + let key_handle = KeyHandle { + credential, + transports: AuthenticatorTransports::empty(), + }; + + let flags = SignFlags::empty(); + let (sign_tx, sign_rx) = channel(); + + let callback = StateCallback::new(Box::new(move |rv| { + sign_tx.send(rv).unwrap(); + })); + + let mut manager = AuthenticatorService::new()?; + manager.add_u2f_usb_hid_platform_transports(); + + let timeout_ms = 10000; + + // let u2fv2_challenge = U2fV2Challenge::new_random(app_id); + let challenge_str = "aaaa".to_owned();// serde_json::to_string(&u2fv2_challenge).unwrap(); + + let mut challenge = Sha256::default(); + Digest::update(&mut challenge, challenge_str.as_bytes()); + let chall_bytes = challenge.finalize().to_vec(); + + let mut application = Sha256::default(); + // application.update(app_id.as_bytes()); + Digest::update(&mut application, app_id.as_bytes()); + let app_bytes = application.finalize().to_vec(); + + let (status_tx, status_rx) = channel::(); + thread::spawn(move || loop { + match status_rx.recv() { + Ok(StatusUpdate::DeviceAvailable { dev_info }) => { + debugging!("STATUS: device available: {}", dev_info) + } + Ok(StatusUpdate::DeviceUnavailable { dev_info }) => { + debugging!("STATUS: device unavailable: {}", dev_info) + } + Ok(StatusUpdate::Success { dev_info }) => { + debugging!("STATUS: success using device: {}", dev_info); + } + Err(_recv_error) => { + debugging!("STATUS: end"); + return; + } + } + }); + + information!("Start sign..."); + if let Err(e) = manager.sign( + flags, + timeout_ms, + chall_bytes, + vec![app_bytes], + vec![key_handle], + status_tx, + callback, + ) { + panic!("Couldn't register: {:?}", e); + } + + let sign_result = sign_rx + .recv() + .expect("Problem receiving, unable to continue"); + let (_, handle_used, sign_data, device_info) = sign_result.expect("Sign failed"); + + println!("Sign result: {}", base64::encode(&sign_data)); + println!("Key handle used: {}", base64::encode(&handle_used)); + println!("Key handle used: {}", hex::encode(&handle_used)); + println!("Device info: {}", &device_info); + println!("Done."); + Ok(()) } } \ No newline at end of file