feat: v1.1.16

This commit is contained in:
2022-04-12 22:45:28 +08:00
parent 2f0d4d6e8a
commit 20754c119e
5 changed files with 60 additions and 35 deletions

59
Cargo.lock generated
View File

@@ -97,7 +97,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8b7511298d5b7784b40b092d9e9dcd3a627a5707e4b5e507931ab0d44eeebf" checksum = "db8b7511298d5b7784b40b092d9e9dcd3a627a5707e4b5e507931ab0d44eeebf"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
"synstructure", "synstructure",
] ]
@@ -109,7 +109,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
] ]
@@ -166,7 +166,7 @@ dependencies = [
"cc", "cc",
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"miniz_oxide", "miniz_oxide 0.4.4",
"object", "object",
"rustc-demangle", "rustc-demangle",
] ]
@@ -202,7 +202,7 @@ dependencies = [
"lazycell", "lazycell",
"peeking_take_while", "peeking_take_while",
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"regex", "regex",
"rustc-hash", "rustc-hash",
"shlex", "shlex",
@@ -248,7 +248,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b04ce3d2372d05d1ef4ea3fdf427da6ae3c17ca06d688a107b5344836276bc3" checksum = "7b04ce3d2372d05d1ef4ea3fdf427da6ae3c17ca06d688a107b5344836276bc3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
] ]
@@ -384,7 +384,7 @@ dependencies = [
[[package]] [[package]]
name = "card-cli" name = "card-cli"
version = "1.1.15" version = "1.1.16"
dependencies = [ dependencies = [
"authenticator", "authenticator",
"base64 0.13.0", "base64 0.13.0",
@@ -580,7 +580,7 @@ version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
dependencies = [ dependencies = [
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
] ]
@@ -734,7 +734,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
] ]
@@ -827,14 +827,14 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.22" version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"crc32fast", "crc32fast",
"libc", "libc",
"miniz_oxide", "miniz_oxide 0.5.1",
] ]
[[package]] [[package]]
@@ -923,7 +923,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
] ]
@@ -1316,6 +1316,15 @@ dependencies = [
"autocfg 1.1.0", "autocfg 1.1.0",
] ]
[[package]]
name = "miniz_oxide"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082"
dependencies = [
"adler",
]
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.8.2" version = "0.8.2"
@@ -1844,9 +1853,9 @@ checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.17" version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -2160,7 +2169,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
] ]
@@ -2394,7 +2403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"unicode-xid", "unicode-xid",
] ]
@@ -2405,7 +2414,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
"unicode-xid", "unicode-xid",
] ]
@@ -2485,7 +2494,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
] ]
@@ -2568,7 +2577,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
] ]
@@ -2714,7 +2723,7 @@ dependencies = [
"lazy_static", "lazy_static",
"log", "log",
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@@ -2725,7 +2734,7 @@ version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5"
dependencies = [ dependencies = [
"quote 1.0.17", "quote 1.0.18",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
] ]
@@ -2736,7 +2745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
@@ -2885,9 +2894,9 @@ dependencies = [
[[package]] [[package]]
name = "xxhash-rust" name = "xxhash-rust"
version = "0.8.4" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83a16b7b403377d61184bb601d8349a4ff2c4cec08a305d004f710b7eaafef24" checksum = "074914ea4eec286eb8d1fd745768504f420a1f7b7919185682a4a267bed7d2e7"
[[package]] [[package]]
name = "yubico_manager" name = "yubico_manager"
@@ -2955,7 +2964,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.17", "quote 1.0.18",
"syn", "syn",
"synstructure", "synstructure",
] ]

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "card-cli" name = "card-cli"
version = "1.1.15" version = "1.1.16"
authors = ["Hatter Jiang <jht5945@gmail.com>"] authors = ["Hatter Jiang <jht5945@gmail.com>"]
edition = "2018" edition = "2018"

View File

@@ -26,6 +26,7 @@ impl Command for CommandImpl {
.arg(Arg::with_name("app-id").short("a").long("app-id").default_value("https://example.com").help("App id")) .arg(Arg::with_name("app-id").short("a").long("app-id").default_value("https://example.com").help("App id"))
.arg(Arg::with_name("timeout").short("t").long("timeout").default_value("30").help("Timeout in seconds")) .arg(Arg::with_name("timeout").short("t").long("timeout").default_value("30").help("Timeout in seconds"))
.arg(Arg::with_name("challenge").long("challenge").takes_value(true).help("Challenge HEX")) .arg(Arg::with_name("challenge").long("challenge").takes_value(true).help("Challenge HEX"))
.arg(Arg::with_name("challenge-with-timestamp-prefix").long("challenge-with-timestamp-prefix").help("Challenge with timestamp prefix"))
.arg(Arg::with_name("json").long("json").help("JSON output")) .arg(Arg::with_name("json").long("json").help("JSON output"))
} }
@@ -39,7 +40,9 @@ impl Command for CommandImpl {
Err(e) => return simple_error!("Timeout should be a number: {}", e), Err(e) => return simple_error!("Timeout should be a number: {}", e),
}; };
let u2fv2_challenge = U2fV2Challenge::new_challenge(sub_arg_matches.value_of("challenge"), app_id)?; let challenge_hex = sub_arg_matches.value_of("challenge");
let challenge_with_timestamp_prefix = sub_arg_matches.is_present("challenge-with-timestamp-prefix");
let u2fv2_challenge = U2fV2Challenge::new_challenge(challenge_hex, app_id, challenge_with_timestamp_prefix)?;
let u2fv2_challenge_str = u2fv2_challenge.to_json(); let u2fv2_challenge_str = u2fv2_challenge.to_json();
let chall_bytes = digest::sha256(&u2fv2_challenge_str); let chall_bytes = digest::sha256(&u2fv2_challenge_str);

View File

@@ -28,6 +28,7 @@ impl Command for CommandImpl {
.arg(Arg::with_name("timeout").short("t").long("timeout").default_value("30").help("Timeout in seconds")) .arg(Arg::with_name("timeout").short("t").long("timeout").default_value("30").help("Timeout in seconds"))
.arg(Arg::with_name("public-key-hex").long("public-key-hex").takes_value(true).help("Public key hex")) .arg(Arg::with_name("public-key-hex").long("public-key-hex").takes_value(true).help("Public key hex"))
.arg(Arg::with_name("challenge").long("challenge").takes_value(true).help("Challenge HEX")) .arg(Arg::with_name("challenge").long("challenge").takes_value(true).help("Challenge HEX"))
.arg(Arg::with_name("challenge-with-timestamp-prefix").long("challenge-with-timestamp-prefix").help("Challenge with timestamp prefix"))
.arg(Arg::with_name("key-handle").short("k").long("key-handle").takes_value(true).multiple(true).help("Key handle")) .arg(Arg::with_name("key-handle").short("k").long("key-handle").takes_value(true).multiple(true).help("Key handle"))
.arg(Arg::with_name("json").long("json").help("JSON output")) .arg(Arg::with_name("json").long("json").help("JSON output"))
} }
@@ -63,8 +64,9 @@ impl Command for CommandImpl {
sign_tx.send(rv).unwrap(); sign_tx.send(rv).unwrap();
})); }));
let challenge_hex = sub_arg_matches.value_of("challenge");
let u2fv2_challenge = U2fV2Challenge::new_challenge(sub_arg_matches.value_of("challenge"), app_id)?; let challenge_with_timestamp_prefix = sub_arg_matches.is_present("challenge-with-timestamp-prefix");
let u2fv2_challenge = U2fV2Challenge::new_challenge(challenge_hex, app_id, challenge_with_timestamp_prefix)?;
let u2fv2_challenge_str = u2fv2_challenge.to_json(); let u2fv2_challenge_str = u2fv2_challenge.to_json();
let chall_bytes = digest::sha256(&u2fv2_challenge_str); let chall_bytes = digest::sha256(&u2fv2_challenge_str);
@@ -99,6 +101,8 @@ impl Command for CommandImpl {
let client_data = u2fv2_challenge_str.as_bytes().to_vec(); let client_data = u2fv2_challenge_str.as_bytes().to_vec();
let app_id_hash = sha256(app_id.as_bytes()); let app_id_hash = sha256(app_id.as_bytes());
let client_data_hash = sha256(&client_data[..]); let client_data_hash = sha256(&client_data[..]);
let counter_u32 = u32::from_be_bytes([counter[0], counter[1], counter[2], counter[3]]);
// application (32B) + user presence (1B) + counter (4B) + client data hash (32B)
let mut signed_message = Vec::with_capacity(128); let mut signed_message = Vec::with_capacity(128);
signed_message.extend_from_slice(&app_id_hash); signed_message.extend_from_slice(&app_id_hash);
signed_message.push(*user_presence_flag); signed_message.push(*user_presence_flag);
@@ -117,15 +121,18 @@ impl Command for CommandImpl {
json.insert("signed_message", hex::encode(&signed_message)); json.insert("signed_message", hex::encode(&signed_message));
json.insert("key_handle", hex::encode(&handle_used)); json.insert("key_handle", hex::encode(&handle_used));
json.insert("sign_data", hex::encode(&sign_data)); json.insert("sign_data", hex::encode(&sign_data));
json.insert("user_presence_flag", format!("{}", *user_presence_flag));
json.insert("counter", format!("{}", counter_u32));
} else { } else {
information!("Sign challenge: {}", u2fv2_challenge_str); information!("Sign challenge: {}", u2fv2_challenge_str);
information!("Sign challenge base64: {}", base64::encode(&u2fv2_challenge_str)); information!("Sign challenge base64: {}", base64::encode(&u2fv2_challenge_str));
information!("Sign result : {}", base64::encode(&sign_data)); information!("Sign result : {}", base64::encode(&sign_data));
information!("- presence : {}", user_presence_flag); information!("- presence : {}", user_presence_flag);
information!("- counter : {}", u32::from_be_bytes([counter[0], counter[1], counter[2], counter[3]])); information!("- counter : {}", counter_u32);
information!("- signature: {}", hex::encode(&signature)); information!("- signature: {}", hex::encode(&signature));
// success!("Key handle used: {}", base64::encode(&handle_used)); // success!("Key handle used: {}", base64::encode(&handle_used));
information!("Key handle: {}", hex::encode(&handle_used)); information!("Key handle: {}", hex::encode(&handle_used));
information!("Signed message: {}", hex::encode(&signed_message));
} }
if let Some(public_key_hex) = sub_arg_matches.value_of("public-key-hex") { if let Some(public_key_hex) = sub_arg_matches.value_of("public-key-hex") {
@@ -134,8 +141,6 @@ impl Command for CommandImpl {
json.insert("pub_key", hex::encode(&public_key)); json.insert("pub_key", hex::encode(&public_key));
} else { } else {
information!("Public key: {}", hex::encode(&public_key)); information!("Public key: {}", hex::encode(&public_key));
information!("Signed message: {}", hex::encode(&signed_message));
let authorization_result = u2f::authorization::parse_sign_response( let authorization_result = u2f::authorization::parse_sign_response(
app_id.to_string(), app_id.to_string(),
client_data, client_data,

View File

@@ -1,6 +1,7 @@
use std::fmt; use std::fmt;
use std::sync::mpsc::{channel, Sender}; use std::sync::mpsc::{channel, Sender};
use std::thread; use std::thread;
use std::time::SystemTime;
use authenticator::{RegisterResult, StatusUpdate}; use authenticator::{RegisterResult, StatusUpdate};
use base64::URL_SAFE_NO_PAD; use base64::URL_SAFE_NO_PAD;
@@ -95,9 +96,9 @@ pub struct U2fV2Challenge {
} }
impl U2fV2Challenge { impl U2fV2Challenge {
pub fn new_challenge(challenge_hex: Option<&str>, app_id: &str) -> XResult<U2fV2Challenge> { pub fn new_challenge(challenge_hex: Option<&str>, app_id: &str, with_time_stamp_prefix: bool) -> XResult<U2fV2Challenge> {
Ok(match challenge_hex { Ok(match challenge_hex {
None => U2fV2Challenge::new_random(app_id), None => U2fV2Challenge::new_random(app_id, with_time_stamp_prefix),
Some(challenge_hex) => { Some(challenge_hex) => {
let challenge_bytes = opt_result!(hex::decode(challenge_hex), "Decode challenge hex failed: {}"); let challenge_bytes = opt_result!(hex::decode(challenge_hex), "Decode challenge hex failed: {}");
let challenge = base64::encode_config(&challenge_bytes, base64::URL_SAFE_NO_PAD); let challenge = base64::encode_config(&challenge_bytes, base64::URL_SAFE_NO_PAD);
@@ -106,13 +107,20 @@ impl U2fV2Challenge {
}) })
} }
pub fn new_random<S>(app_id: S) -> Self where S: Into<String> { pub fn new_random<S>(app_id: S, with_time_stamp_prefix: bool) -> Self where S: Into<String> {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let mut rand_bytes = [0_u8; 32]; let mut rand_bytes = [0_u8; 32];
for c in &mut rand_bytes { for c in &mut rand_bytes {
let b: u8 = rng.gen(); let b: u8 = rng.gen();
*c = b; *c = b;
} }
if with_time_stamp_prefix {
let timestamp = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis() as u64;
let timestamp_be_bytes = timestamp.to_be_bytes();
for i in 0..8 {
rand_bytes[i] = timestamp_be_bytes[i];
}
}
let challenge = base64::encode_config(&rand_bytes, URL_SAFE_NO_PAD); let challenge = base64::encode_config(&rand_bytes, URL_SAFE_NO_PAD);
Self::new(challenge, app_id) Self::new(challenge, app_id)