feat: CTAP/FIDO cert
This commit is contained in:
@@ -4,7 +4,6 @@ use authenticator::authenticatorservice::AuthenticatorService;
|
||||
use authenticator::statecallback::StateCallback;
|
||||
use authenticator::RegisterFlags;
|
||||
use std::sync::mpsc::channel;
|
||||
use rust_util::XResult;
|
||||
use crate::fido;
|
||||
use crate::digest;
|
||||
use crate::fido::U2fV2Challenge;
|
||||
@@ -28,7 +27,8 @@ impl Command for CommandImpl {
|
||||
};
|
||||
|
||||
let u2fv2_challenge = U2fV2Challenge::new_random(app_id);
|
||||
let chall_bytes = digest::sha256(&u2fv2_challenge.to_json());
|
||||
let u2fv2_challenge_str = u2fv2_challenge.to_json();
|
||||
let chall_bytes = digest::sha256(&u2fv2_challenge_str);
|
||||
|
||||
let app_bytes = digest::sha256(app_id);
|
||||
|
||||
@@ -61,47 +61,45 @@ impl Command for CommandImpl {
|
||||
|
||||
success!("Device info: {}", &device_info);
|
||||
success!("Register result: {}", base64::encode(®ister_data));
|
||||
let credential = u2f_get_key_handle_from_register_response(®ister_data).unwrap();
|
||||
success!("Key handle: {}", base64::encode(&credential));
|
||||
success!("Key handle: {}", hex::encode(&credential));
|
||||
|
||||
let client_data = &u2fv2_challenge_str;
|
||||
let rr = match u2f::register::parse_registration(app_id.to_string(), client_data.as_bytes().to_vec(), register_data) {
|
||||
Ok(rr) => rr,
|
||||
Err(e) => return simple_error!("Parse registration data failed: {}", e),
|
||||
};
|
||||
if let Some(cert) = rr.attestation_cert {
|
||||
success!("Certificate: {}", fido::to_pem(&cert, "CERTIFICATE", 64));
|
||||
}
|
||||
if let Some(device_name) = rr.device_name {
|
||||
success!("Device name: {}", device_name);
|
||||
}
|
||||
success!("Public key: {}", hex::encode(rr.pub_key));
|
||||
success!("Key handle: {}", hex::encode(rr.key_handle));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// U2F raw message format specification (version 20170411) section 4.3
|
||||
// In case of success we need to send back the following reply
|
||||
// (excluding ISO7816 success code)
|
||||
// +------+--------------------+---------------------+------------+------------+------+
|
||||
// + 0x05 | User pub key (65B) | key handle len (1B) | key handle | X.509 Cert | Sign |
|
||||
// +------+--------------------+---------------------+------------+------------+------+
|
||||
//
|
||||
// Where Sign is an ECDSA signature over the following structure:
|
||||
// +------+-------------------+-----------------+------------+--------------------+
|
||||
// + 0x00 | application (32B) | challenge (32B) | key handle | User pub key (65B) |
|
||||
// +------+-------------------+-----------------+------------+--------------------+
|
||||
// see https://github.com/google/OpenSK/blob/stable/src/ctap/ctap1.rs
|
||||
fn u2f_get_key_handle_from_register_response(register_response: &[u8]) -> XResult<Vec<u8>> {
|
||||
if register_response[0] != 0x05 {
|
||||
return simple_error!("Reserved byte not set correctly");
|
||||
}
|
||||
|
||||
let key_handle_len = register_response[66] as usize;
|
||||
let mut public_key = register_response.to_owned();
|
||||
let mut key_handle = public_key.split_off(67);
|
||||
let _attestation = key_handle.split_off(key_handle_len);
|
||||
|
||||
Ok(key_handle)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let app_id = "https://webencrypt.org";
|
||||
let client_data = base64::decode("eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6ImFHVnNiRzlmZDI5eWJHUSIsIm9yaWdpbiI6Imh0dHBzOi8vd2ViZW5jcnlwdC5vcmciLCJjcm9zc09yaWdpbiI6ZmFsc2V9").unwrap();
|
||||
let register_data = base64::decode("BQSpAR+aliPCpz2u8c84Mv13bAYUcJnT9OgiXkCX9CTR/xhWqbJwoL9l6WRqvqwtG77NMvkDexcTKf9Mtf5+V1NCQKYfXWCP+IL2Lfbyng7mX0GV/etsHqlIiiaoEQo5g0Zetn+JimnLx5f259OZlEsvzB7Qs6swN5WRy57FRqREOPcwggE0MIHboAMCAQICCiBzHdQQUIQZ+ZgwCgYIKoZIzj0EAwIwFTETMBEGA1UEAxMKVTJGIElzc3VlcjAaFwswMDAxMDEwMDAwWhcLMDAwMTAxMDAwMFowFTETMBEGA1UEAxMKVTJGIERldmljZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCvum43LiwAMJacjIFh7SCIrl1e1ltYXeK50v2HWDRZ9pw38HSPmx2SjT+2hTY1YMVagbgXimYrb8+WWlZ6j9bqjFzAVMBMGCysGAQQBguUcAgEBBAQDAgUgMAoGCCqGSM49BAMCA0gAMEUCIQDBo6aOLxanIUYnBX9iu3KMngPnobpi0EZSTkVtLC8/cwIgC1945RGqGBKfbyNtkhMifZK05n7fU+gW37Bdnci5D94wRQIhAJHR1EsN/+Fb+74FyxSjBMaoD6p2edlqGPYEb4SiXwccAiAM48XFf/sWsgzS2YU4EeObztVLErUb1JaA2qHJtTUoig==").unwrap();
|
||||
let r = u2f::register::parse_registration(app_id.to_string(), client_data, register_data);
|
||||
let rr = r.unwrap();
|
||||
println!("{}", hex::encode(rr.pub_key));
|
||||
println!("{}", hex::encode(rr.attestation_cert.unwrap()));
|
||||
println!("{}", hex::encode(rr.key_handle));
|
||||
}
|
||||
// // U2F raw message format specification (version 20170411) section 4.3
|
||||
// // In case of success we need to send back the following reply
|
||||
// // (excluding ISO7816 success code)
|
||||
// // +------+--------------------+---------------------+------------+------------+------+
|
||||
// // + 0x05 | User pub key (65B) | key handle len (1B) | key handle | X.509 Cert | Sign |
|
||||
// // +------+--------------------+---------------------+------------+------------+------+
|
||||
// //
|
||||
// // Where Sign is an ECDSA signature over the following structure:
|
||||
// // +------+-------------------+-----------------+------------+--------------------+
|
||||
// // + 0x00 | application (32B) | challenge (32B) | key handle | User pub key (65B) |
|
||||
// // +------+-------------------+-----------------+------------+--------------------+
|
||||
// // see https://github.com/google/OpenSK/blob/stable/src/ctap/ctap1.rs
|
||||
// fn u2f_get_key_handle_from_register_response(register_response: &[u8]) -> XResult<Vec<u8>> {
|
||||
// if register_response[0] != 0x05 {
|
||||
// return simple_error!("Reserved byte not set correctly");
|
||||
// }
|
||||
//
|
||||
// let key_handle_len = register_response[66] as usize;
|
||||
// let mut public_key = register_response.to_owned();
|
||||
// let mut key_handle = public_key.split_off(67);
|
||||
// let _attestation = key_handle.split_off(key_handle_len);
|
||||
//
|
||||
// Ok(key_handle)
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user