extern crate ctap_hmac as ctap; use crypto::digest::Digest; use crypto::sha2::Sha256; use ctap::extensions::{self, FidoExtensionResponseParserExt}; use ctap::{FidoAssertionRequestBuilder, FidoCredential, FidoCredentialRequestBuilder}; use hex; use std::env::args; use std::io::prelude::*; use std::io::stdin; use std::io::stdout; const RP_ID: &str = "ctap_demo"; fn main() -> ctap::FidoResult<()> { let mut devices = ctap::get_devices()?; let device_info = &mut devices.next().expect("No authenticator found"); let mut device = ctap::FidoDevice::new(device_info)?; let credential = match args().nth(1).map(|h| FidoCredential { id: hex::decode(&h).expect("Invalid credential"), public_key: None, }) { Some(cred) => cred, _ => { let mut req = FidoCredentialRequestBuilder::default() .rp_id(RP_ID) .rp_name("ctap_hmac crate") .user_name("example") .uv(false) .build() .unwrap(); assert!( &device.supports_extension::(), "Your device does not support the hmac extension" ); let hmac = extensions::HmacSecret::new(); req.with_extension(&hmac)?; dbg!(&req); println!("Authorize using your device"); let cred = req .make_credential(&mut device) .expect("Failed to request credential"); println!("Credential: {}\nNote: You can pass this credential as first argument in order to reproduce results", hex::encode(&cred.id)); cred } }; print!("Type in your message: "); stdout().flush().unwrap(); let mut message = String::new(); stdin() .read_line(&mut message) .expect("Couldn't get your message\nNote: this demo does not accept binary data"); println!("Authorize using your device"); let mut salt = [0u8; 32]; let mut digest = Sha256::new(); digest.input(&message.as_bytes()); digest.result(&mut salt); let credential = &&credential; let hmac = extensions::HmacSecret::new().for_device(&mut device, &salt, None)?; let mut request = FidoAssertionRequestBuilder::default() .rp_id(RP_ID) .credential(credential) .build() .unwrap(); request.with_extension(&hmac)?; let (_cred, auth_data) = device.get_assertion(&request)?; let (hash1, _hash2) = auth_data.parse_extension_data(&hmac)?; println!("Hash: {}", hex::encode(&hash1)); Ok(()) }