feat: add pgp card admin
This commit is contained in:
25
src/cmd_pgpcardadmin.rs
Normal file
25
src/cmd_pgpcardadmin.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||||
|
use rust_util::util_clap::{Command, CommandError};
|
||||||
|
|
||||||
|
pub struct CommandImpl;
|
||||||
|
|
||||||
|
impl Command for CommandImpl {
|
||||||
|
fn name(&self) -> &str { "pgp-card-admin" }
|
||||||
|
|
||||||
|
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||||
|
SubCommand::with_name(self.name()).about("OpenPGP Card Admin subcommand")
|
||||||
|
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("12345678").help("OpenPGP card admin pin"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||||
|
let pin = opt_value_result!(sub_arg_matches.value_of("pin"), "Pass must be assigned");
|
||||||
|
if pin.len() < 8 { return simple_error!("Admin pin length:{}, must >= 8!", pin.len()); }
|
||||||
|
|
||||||
|
let _card_admin = crate::pgpcardutil::get_card_admin(pin)?;
|
||||||
|
|
||||||
|
information!("Admin pin verify success!");
|
||||||
|
// card_admin.get_aid()
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ impl Command for CommandImpl {
|
|||||||
|
|
||||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||||
SubCommand::with_name(self.name()).about("OpenPGP Card Decrypt subcommand")
|
SubCommand::with_name(self.name()).about("OpenPGP Card Decrypt subcommand")
|
||||||
.arg(Arg::with_name("pass").short("p").long("pass").takes_value(true).default_value("123456").help("OpenPGP card password"))
|
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("123456").help("OpenPGP card user pin"))
|
||||||
.arg(Arg::with_name("cipher").short("c").long("cipher").takes_value(true).help("Cipher text HEX"))
|
.arg(Arg::with_name("cipher").short("c").long("cipher").takes_value(true).help("Cipher text HEX"))
|
||||||
.arg(Arg::with_name("cipher-base64").short("b").long("cipher-base64").takes_value(true).help("Cipher text base64"))
|
.arg(Arg::with_name("cipher-base64").short("b").long("cipher-base64").takes_value(true).help("Cipher text base64"))
|
||||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||||
@@ -19,12 +19,11 @@ impl Command for CommandImpl {
|
|||||||
|
|
||||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||||
let json_output = sub_arg_matches.is_present("json");
|
let json_output = sub_arg_matches.is_present("json");
|
||||||
if json_output {
|
if json_output { rust_util::util_msg::set_logger_std_out(false); }
|
||||||
rust_util::util_msg::set_logger_std_out(false);
|
|
||||||
}
|
let pin = opt_value_result!(sub_arg_matches.value_of("pin"), "User pin must be assigned");
|
||||||
let pass_opt = sub_arg_matches.value_of("pass");
|
if pin.len() < 6 { return simple_error!("User pin length:{}, must >= 6!", pin.len()); }
|
||||||
let pass = opt_value_result!(pass_opt, "Pass must be assigned");
|
|
||||||
if pass.len() < 6 { return simple_error!("Pass length:{}, must >= 6!", pass.len()); }
|
|
||||||
let cipher = sub_arg_matches.value_of("cipher");
|
let cipher = sub_arg_matches.value_of("cipher");
|
||||||
let cipher_base64 = sub_arg_matches.value_of("cipher-base64");
|
let cipher_base64 = sub_arg_matches.value_of("cipher-base64");
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@ impl Command for CommandImpl {
|
|||||||
return simple_error!("cipher or cipher-base64 must assign one");
|
return simple_error!("cipher or cipher-base64 must assign one");
|
||||||
};
|
};
|
||||||
|
|
||||||
let user = crate::pgpcardutil::get_card_user_sw1_82(pass)?;
|
let user = crate::pgpcardutil::get_card_user_sw1_82(pin)?;
|
||||||
let text = user.decrypt(DecryptMe::RSA(&cipher_bytes))?;
|
let text = user.decrypt(DecryptMe::RSA(&cipher_bytes))?;
|
||||||
success!("Clear text HEX: {}", hex::encode(&text));
|
success!("Clear text HEX: {}", hex::encode(&text));
|
||||||
success!("Clear text base64: {}", base64::encode(&text));
|
success!("Clear text base64: {}", base64::encode(&text));
|
||||||
|
|||||||
@@ -71,12 +71,12 @@ impl Command for CommandImpl {
|
|||||||
println!("{}", serde_json::to_string_pretty(&json).unwrap());
|
println!("{}", serde_json::to_string_pretty(&json).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(pass) = std::env::var("PASS") {
|
if let Ok(pin) = std::env::var("PASS") {
|
||||||
if let Ok(list) = OpenPGPCard::list_cards() {
|
if let Ok(list) = OpenPGPCard::list_cards() {
|
||||||
// pw1_81 for signature
|
// pw1_81 for signature
|
||||||
// openssl dgst -sha256 -verify aa -signature sig LICENSE
|
// openssl dgst -sha256 -verify aa -signature sig LICENSE
|
||||||
for card in list {
|
for card in list {
|
||||||
match card.verify_pw1_81(&pass) {
|
match card.verify_pw1_81(&pin) {
|
||||||
Result::Ok(user) => {
|
Result::Ok(user) => {
|
||||||
let h = hex::decode("8f25018489d6fe0dec34a352314c38dc146247b7de65735790f4398a92afa84b").unwrap();
|
let h = hex::decode("8f25018489d6fe0dec34a352314c38dc146247b7de65735790f4398a92afa84b").unwrap();
|
||||||
let mut hh = [0_u8; 0x20];
|
let mut hh = [0_u8; 0x20];
|
||||||
@@ -95,7 +95,7 @@ impl Command for CommandImpl {
|
|||||||
// pw1_82 for encryption
|
// pw1_82 for encryption
|
||||||
// PKCSv1.5
|
// PKCSv1.5
|
||||||
for card in list {
|
for card in list {
|
||||||
match card.verify_pw1_82(&pass) {
|
match card.verify_pw1_82(&pin) {
|
||||||
Result::Ok(user) => {
|
Result::Ok(user) => {
|
||||||
let e = hex::decode("705d2af390174706c42de8361c4cb7a4684e06216305d6da70cab9248fa1abb9fac2b4c004187a53b9ed2b7f8ab75b20a54a12e6be672a742504b38d07b192f1f815285b6605b06a1a86d97f14ffcf41a9b3463ff3d8b2afe63e53aeb43048fef358639e5589fab8000d0805fe9145b5457cb5f7f91243b25181d1c7853b384a3bba45143a5ceeb2612463e51fbce52154e20726e6cf58f0317ebdf92613a10aec2b34224b0ffd1333c475cab473cf66aa895700e6681d20d12ddc897e0731226d4dc6bc9bd2e4aca02dba49175a35e45f9f3b56973a0381c777dac73a7eb8a04bfde45d3c19f44f740a193439da6829bf4beba90529c3017bddbd64aacbad92d3632260d5b6a7b5565fd852f17cff031fbdc2700d6acc2dedaaad307aaf7bb2de8f2b02faf84d94fa046e4ce487480918a54ca4672e1388deae8881436f454e65263a4984003495031126b4488ab27c6f4555f16bdd0fe2b9132443bbf49aa9c19864c4b1b917914e9c070a0327e52cf3b536e218a56ec97e12979e5981977e008eb9180d02da322c1a019fa535d77b67912039bc699b291d950714367d1c4a4a41edc86b1ab99d101da75a61c762fee28f8a004fb7656800623ac95d88c1978f18a1d286916cdab9c9f0f91d500cffdc8cb2853011a352bfa5f1fcd4a59720004153fb644afef083909c6a537ebc24255c1284ecf665a8cb7212672051e8b4").unwrap();
|
let e = hex::decode("705d2af390174706c42de8361c4cb7a4684e06216305d6da70cab9248fa1abb9fac2b4c004187a53b9ed2b7f8ab75b20a54a12e6be672a742504b38d07b192f1f815285b6605b06a1a86d97f14ffcf41a9b3463ff3d8b2afe63e53aeb43048fef358639e5589fab8000d0805fe9145b5457cb5f7f91243b25181d1c7853b384a3bba45143a5ceeb2612463e51fbce52154e20726e6cf58f0317ebdf92613a10aec2b34224b0ffd1333c475cab473cf66aa895700e6681d20d12ddc897e0731226d4dc6bc9bd2e4aca02dba49175a35e45f9f3b56973a0381c777dac73a7eb8a04bfde45d3c19f44f740a193439da6829bf4beba90529c3017bddbd64aacbad92d3632260d5b6a7b5565fd852f17cff031fbdc2700d6acc2dedaaad307aaf7bb2de8f2b02faf84d94fa046e4ce487480918a54ca4672e1388deae8881436f454e65263a4984003495031126b4488ab27c6f4555f16bdd0fe2b9132443bbf49aa9c19864c4b1b917914e9c070a0327e52cf3b536e218a56ec97e12979e5981977e008eb9180d02da322c1a019fa535d77b67912039bc699b291d950714367d1c4a4a41edc86b1ab99d101da75a61c762fee28f8a004fb7656800623ac95d88c1978f18a1d286916cdab9c9f0f91d500cffdc8cb2853011a352bfa5f1fcd4a59720004153fb644afef083909c6a537ebc24255c1284ecf665a8cb7212672051e8b4").unwrap();
|
||||||
println!(":::: {}", e.len());
|
println!(":::: {}", e.len());
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ impl Command for CommandImpl {
|
|||||||
|
|
||||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||||
SubCommand::with_name(self.name()).about("OpenPGP Card Sign subcommand")
|
SubCommand::with_name(self.name()).about("OpenPGP Card Sign subcommand")
|
||||||
.arg(Arg::with_name("pass").short("p").long("pass").takes_value(true).default_value("123456").help("OpenPGP card password"))
|
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("123456").help("OpenPGP card user pin"))
|
||||||
.arg(Arg::with_name("sha256").short("2").long("sha256").takes_value(true).help("Digest SHA256 HEX"))
|
.arg(Arg::with_name("sha256").short("2").long("sha256").takes_value(true).help("Digest SHA256 HEX"))
|
||||||
.arg(Arg::with_name("sha384").short("3").long("sha384").takes_value(true).help("Digest SHA384 HEX"))
|
.arg(Arg::with_name("sha384").short("3").long("sha384").takes_value(true).help("Digest SHA384 HEX"))
|
||||||
.arg(Arg::with_name("sha512").short("5").long("sha512").takes_value(true).help("Digest SHA512 HEX"))
|
.arg(Arg::with_name("sha512").short("5").long("sha512").takes_value(true).help("Digest SHA512 HEX"))
|
||||||
@@ -24,11 +24,10 @@ impl Command for CommandImpl {
|
|||||||
if json_output {
|
if json_output {
|
||||||
rust_util::util_msg::set_logger_std_out(false);
|
rust_util::util_msg::set_logger_std_out(false);
|
||||||
}
|
}
|
||||||
let pass = sub_arg_matches.value_of("pass");
|
let pin_opt = sub_arg_matches.value_of("pin");
|
||||||
let pass = match pass {
|
let pin = opt_value_result!(pin_opt, "User pin must be assigned");
|
||||||
Some(p) => p,
|
if pin.len() < 6 { return simple_error!("User pin length:{}, must >= 6!", pin.len()); }
|
||||||
None => return simple_error!("Pass must be assigned"),
|
|
||||||
};
|
|
||||||
let sha256 = sub_arg_matches.value_of("sha256");
|
let sha256 = sub_arg_matches.value_of("sha256");
|
||||||
let sha384 = sub_arg_matches.value_of("sha384");
|
let sha384 = sub_arg_matches.value_of("sha384");
|
||||||
let sha512 = sub_arg_matches.value_of("sha512");
|
let sha512 = sub_arg_matches.value_of("sha512");
|
||||||
@@ -39,7 +38,7 @@ impl Command for CommandImpl {
|
|||||||
|
|
||||||
let mut json = BTreeMap::new();
|
let mut json = BTreeMap::new();
|
||||||
if let Some(sha256) = sha256 {
|
if let Some(sha256) = sha256 {
|
||||||
let user = crate::pgpcardutil::get_card_user_sw1_81(pass)?;
|
let user = crate::pgpcardutil::get_card_user_sw1_81(pin)?;
|
||||||
let sha256_hex = opt_result!(hex::decode(sha256.trim()), "Decode sha256 failed: {}");
|
let sha256_hex = opt_result!(hex::decode(sha256.trim()), "Decode sha256 failed: {}");
|
||||||
let sha256_hex = copy_sha256(&sha256_hex)?;
|
let sha256_hex = copy_sha256(&sha256_hex)?;
|
||||||
let sig = user.signature_for_hash(Hash::SHA256(sha256_hex))?;
|
let sig = user.signature_for_hash(Hash::SHA256(sha256_hex))?;
|
||||||
@@ -53,7 +52,7 @@ impl Command for CommandImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(sha384) = sha384 {
|
if let Some(sha384) = sha384 {
|
||||||
let user = crate::pgpcardutil::get_card_user_sw1_81(pass)?;
|
let user = crate::pgpcardutil::get_card_user_sw1_81(pin)?;
|
||||||
let sha384_hex = opt_result!(hex::decode(sha384.trim()), "Decode sha384 failed: {}");
|
let sha384_hex = opt_result!(hex::decode(sha384.trim()), "Decode sha384 failed: {}");
|
||||||
let sha384_hex = copy_sha384(&sha384_hex)?;
|
let sha384_hex = copy_sha384(&sha384_hex)?;
|
||||||
let sig = user.signature_for_hash(Hash::SHA384(sha384_hex))?;
|
let sig = user.signature_for_hash(Hash::SHA384(sha384_hex))?;
|
||||||
@@ -67,7 +66,7 @@ impl Command for CommandImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(sha512) = sha512 {
|
if let Some(sha512) = sha512 {
|
||||||
let user = crate::pgpcardutil::get_card_user_sw1_81(pass)?;
|
let user = crate::pgpcardutil::get_card_user_sw1_81(pin)?;
|
||||||
let sha512_hex = opt_result!(hex::decode(sha512.trim()), "Decode sha512 failed: {}");
|
let sha512_hex = opt_result!(hex::decode(sha512.trim()), "Decode sha512 failed: {}");
|
||||||
let sha512_hex = copy_sha512(&sha512_hex)?;
|
let sha512_hex = copy_sha512(&sha512_hex)?;
|
||||||
let sig = user.signature_for_hash(Hash::SHA512(sha512_hex))?;
|
let sig = user.signature_for_hash(Hash::SHA512(sha512_hex))?;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ impl Command for CommandImpl {
|
|||||||
|
|
||||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||||
SubCommand::with_name(self.name()).about("PIV Sign subcommand")
|
SubCommand::with_name(self.name()).about("PIV Sign subcommand")
|
||||||
.arg(Arg::with_name("pass").short("p").long("pass").takes_value(true).default_value("123456").help("OpenPGP card password"))
|
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("123456").help("OpenPGP card user pin"))
|
||||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,11 +22,10 @@ impl Command for CommandImpl {
|
|||||||
rust_util::util_msg::set_logger_std_out(false);
|
rust_util::util_msg::set_logger_std_out(false);
|
||||||
}
|
}
|
||||||
warning!("This feature is not complete");
|
warning!("This feature is not complete");
|
||||||
let pass_opt = sub_arg_matches.value_of("pass");
|
let pin = opt_value_result!(sub_arg_matches.value_of("pin"), "User pin must be assigned");
|
||||||
let pass = opt_value_result!(pass_opt, "Pass must be assigned");
|
|
||||||
|
|
||||||
let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}");
|
let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}");
|
||||||
opt_result!(yk.verify_pin(pass.as_bytes()), "YubiKey verify pin failed: {}");
|
opt_result!(yk.verify_pin(pin.as_bytes()), "YubiKey verify pin failed: {}");
|
||||||
let raw_in = [1_u8; 256];
|
let raw_in = [1_u8; 256];
|
||||||
let sign_result = yubikey::piv::sign_data(&mut yk, &raw_in, AlgorithmId::Rsa2048, SlotId::Signature);
|
let sign_result = yubikey::piv::sign_data(&mut yk, &raw_in, AlgorithmId::Rsa2048, SlotId::Signature);
|
||||||
let sign = opt_result!(sign_result, "Sign data failed: {}");
|
let sign = opt_result!(sign_result, "Sign data failed: {}");
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ mod cmd_u2fregister;
|
|||||||
mod cmd_u2fsign;
|
mod cmd_u2fsign;
|
||||||
mod cmd_pgp;
|
mod cmd_pgp;
|
||||||
mod pgpcardutil;
|
mod pgpcardutil;
|
||||||
|
mod cmd_pgpcardadmin;
|
||||||
mod cmd_pgpcardlist;
|
mod cmd_pgpcardlist;
|
||||||
mod cmd_pgpcardsign;
|
mod cmd_pgpcardsign;
|
||||||
mod cmd_pgpcarddecrypt;
|
mod cmd_pgpcarddecrypt;
|
||||||
@@ -41,6 +42,7 @@ fn inner_main() -> CommandError {
|
|||||||
Box::new(cmd_chall::CommandImpl),
|
Box::new(cmd_chall::CommandImpl),
|
||||||
Box::new(cmd_challconfig::CommandImpl),
|
Box::new(cmd_challconfig::CommandImpl),
|
||||||
Box::new(cmd_pgp::CommandImpl),
|
Box::new(cmd_pgp::CommandImpl),
|
||||||
|
Box::new(cmd_pgpcardadmin::CommandImpl),
|
||||||
Box::new(cmd_pgpcardlist::CommandImpl),
|
Box::new(cmd_pgpcardlist::CommandImpl),
|
||||||
Box::new(cmd_pgpcardsign::CommandImpl),
|
Box::new(cmd_pgpcardsign::CommandImpl),
|
||||||
Box::new(cmd_pgpcarddecrypt::CommandImpl),
|
Box::new(cmd_pgpcarddecrypt::CommandImpl),
|
||||||
|
|||||||
@@ -1,37 +1,43 @@
|
|||||||
use openpgp_card::{OpenPGPCard, OpenPGPCardUser};
|
use openpgp_card::{OpenPGPCard, OpenPGPCardAdmin, OpenPGPCardUser};
|
||||||
use rust_util::XResult;
|
use rust_util::XResult;
|
||||||
|
|
||||||
pub fn get_card_user_sw1_81(pass: &str) -> XResult<OpenPGPCardUser> {
|
pub fn get_card_user_sw1_81(pin: &str) -> XResult<OpenPGPCardUser> {
|
||||||
match OpenPGPCard::list_cards() {
|
// pw1_81 for signature
|
||||||
Ok(list) => {
|
// openssl dgst -sha256 -verify aa -signature sig LICENSE
|
||||||
// pw1_81 for signature
|
get_card_user(|open_pgp_card: OpenPGPCard| open_pgp_card.verify_pw1_81(pin), "pw1_81")
|
||||||
// openssl dgst -sha256 -verify aa -signature sig LICENSE
|
}
|
||||||
if list.is_empty() {
|
|
||||||
return simple_error!("Cannot find any card");
|
pub fn get_card_user_sw1_82(pin: &str) -> XResult<OpenPGPCardUser> {
|
||||||
}
|
// pw1_82 for decrypt
|
||||||
match list.into_iter().next().unwrap().verify_pw1_81(pass) {
|
// PKCSv1.5
|
||||||
Result::Ok(user) => Ok(user),
|
get_card_user(|open_pgp_card: OpenPGPCard| open_pgp_card.verify_pw1_82(pin), "pw1_82")
|
||||||
Result::Err(_) => simple_error!("Verify pw1_81 OpenPGP card failed"),
|
}
|
||||||
}
|
|
||||||
}
|
pub fn get_card_admin(pin: &str) -> XResult<OpenPGPCardAdmin> {
|
||||||
Err(e) => simple_error!("Read OpenPGP card failed: {}", e),
|
let card = get_card()?;
|
||||||
|
match card.verify_pw3(pin) {
|
||||||
|
Result::Ok(admin) => Ok(admin),
|
||||||
|
Result::Err(_) => simple_error!("Verify pw3 OpenPGP card failed"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_card_user_sw1_82(pass: &str) -> XResult<OpenPGPCardUser> {
|
fn get_card_user(process_fn: impl Fn(OpenPGPCard) -> Result<OpenPGPCardUser, OpenPGPCard>, tag: &str) -> XResult<OpenPGPCardUser> {
|
||||||
match OpenPGPCard::list_cards() {
|
let card = get_card()?;
|
||||||
Ok(list) => {
|
match process_fn(card) {
|
||||||
// pw1_82 for decrypt
|
Result::Ok(user) => Ok(user),
|
||||||
// PKCSv1.5
|
Result::Err(_) => simple_error!("Verify {} OpenPGP card failed", tag),
|
||||||
if list.is_empty() {
|
|
||||||
return simple_error!("Cannot find any card");
|
|
||||||
}
|
|
||||||
match list.into_iter().next().unwrap().verify_pw1_82(pass) {
|
|
||||||
Result::Ok(user) => Ok(user),
|
|
||||||
Result::Err(_) => simple_error!("Verify pw1_82 OpenPGP card failed"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => simple_error!("Read OpenPGP card failed: {}", e),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_card() -> XResult<OpenPGPCard> {
|
||||||
|
let card_list = opt_result!(OpenPGPCard::list_cards(),
|
||||||
|
"Read OpenPGP card list failed: {}");
|
||||||
|
if card_list.is_empty() {
|
||||||
|
return simple_error!("Cannot find any card");
|
||||||
|
}
|
||||||
|
if card_list.len() > 0 {
|
||||||
|
warning!("Find {} OpenPGP cards, will use first card", card_list.len());
|
||||||
|
}
|
||||||
|
Ok(opt_value_result!(card_list.into_iter().next(), "Get first card failed"))
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user