feat: pgp decrypt
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
|
test.txt
|
||||||
|
enc.txt
|
||||||
|
enc_key.pem
|
||||||
test_key.asc
|
test_key.asc
|
||||||
.idea/
|
.idea/
|
||||||
# ---> Rust
|
# ---> Rust
|
||||||
|
|||||||
34
README.md
34
README.md
@@ -2,6 +2,40 @@
|
|||||||
|
|
||||||
A cli using https://github.com/mozilla/authenticator-rs
|
A cli using https://github.com/mozilla/authenticator-rs
|
||||||
|
|
||||||
|
|
||||||
|
# PGP
|
||||||
|
|
||||||
|
## decrypt text
|
||||||
|
|
||||||
|
sample public key
|
||||||
|
```
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApUM8M+QRMUw0dIvXISFx
|
||||||
|
43j4h9CK38Y9HD6kPcc3Z0dCGPiFy7Ze0OQebPWHyUZ2YmqsdyzFuOQuV9P2pxxj
|
||||||
|
/WLIgRqZV8Jk8tWhtAjOOvm0MTc2rg+EJHfa+zhX4eFEMsj4DvQBMJDXiKnpXTM/
|
||||||
|
j7oMKpIUQHqfXBwsEJHLmHZTLeEBEYKcZXTAmuu3WdxK5jvEc02Xt2hZ1fBs0M9e
|
||||||
|
/2EMe3t69aH4/rabiBjF2h9Jde15wrJMxXaCCWJqYhbBS0CJ3BdjkAqOIpcqPXva
|
||||||
|
xiJN1pNpK8ejA9Q4Nmx7pxnvfv+hCPkWXZS3r/BWZ9lFZc8uErQEbB4gLgko8jOl
|
||||||
|
fQF7cYqtZEs69qY8nnIUBsqZYfAp+bQd2xCFSbEZAl+OrtGzfVjD9YFMPy02+xRg
|
||||||
|
v2N3KT3KHHvuU7WxrvffrshP2fwDuG2MBlmcq1suAKxA0cYPSyajceEqw/3ogSp7
|
||||||
|
7SYx41rT8EWLmTvU0CHzCsuf/O7sDWZRfxatAzWhBBhnKCPqzizpOQOqm8XhCt74
|
||||||
|
FfnabPpHM9XUjoQIPrTssyS3eWqynzJiAqez6v2LK2fhL7IkcLtvt5p59Y+KY4I6
|
||||||
|
YQ09iUh7lKJHRhkgTomUurJHieVHMWFGIHofEC+nU6pGIUh0P7Nr0Gz45GJTwWGd
|
||||||
|
hW53WfImja+b5kwwyqUikyMCAwEAAQ==
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
```
|
||||||
|
|
||||||
|
encrypt
|
||||||
|
```
|
||||||
|
openssl rsautl -encrypt -pubin -inkey enc_key.pem -in test.txt -out enc.txt -pkcs
|
||||||
|
```
|
||||||
|
|
||||||
|
decrypt
|
||||||
|
```
|
||||||
|
$ cargo r -- pgp-card-decrypt -c $(cat enc.txt | xxd -ps -c 11111)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Awesome webauthn:
|
Awesome webauthn:
|
||||||
* https://github.com/herrjemand/awesome-webauthn
|
* https://github.com/herrjemand/awesome-webauthn
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ impl Command for CommandImpl {
|
|||||||
|
|
||||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||||
SubCommand::with_name(self.name()).about("Yubikey challenge-response hmac")
|
SubCommand::with_name(self.name()).about("Yubikey challenge-response hmac")
|
||||||
.arg(Arg::with_name("challenge").long("challenge").takes_value(true).help("Challenge"))
|
.arg(Arg::with_name("challenge").short("c").long("challenge").takes_value(true).help("Challenge"))
|
||||||
.arg(Arg::with_name("challenge-hex").long("challenge-hex").takes_value(true).help("Challenge HEX"))
|
.arg(Arg::with_name("challenge-hex").short("x").long("challenge-hex").takes_value(true).help("Challenge HEX"))
|
||||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ impl Command for CommandImpl {
|
|||||||
|
|
||||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||||
SubCommand::with_name(self.name()).about("Yubikey challenge-response hmac config")
|
SubCommand::with_name(self.name()).about("Yubikey challenge-response hmac config")
|
||||||
.arg(Arg::with_name("secret").long("secret").takes_value(true).help("Secret"))
|
.arg(Arg::with_name("secret").short("s").long("secret").takes_value(true).help("Secret"))
|
||||||
.arg(Arg::with_name("secret-hex").long("secret-hex").takes_value(true).help("Secret HEX"))
|
.arg(Arg::with_name("secret-hex").short("x").long("secret-hex").takes_value(true).help("Secret HEX"))
|
||||||
.arg(Arg::with_name("yes-config-chall").long("yes-config-chall").help("Config chall key"))
|
.arg(Arg::with_name("yes-config-chall").long("yes-config-chall").help("Config chall key"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ mod pgp;
|
|||||||
mod pgpcardutil;
|
mod pgpcardutil;
|
||||||
mod pgpcardlist;
|
mod pgpcardlist;
|
||||||
mod pgpcardsign;
|
mod pgpcardsign;
|
||||||
|
mod pgpcarddecrypt;
|
||||||
mod piv;
|
mod piv;
|
||||||
mod chall;
|
mod chall;
|
||||||
mod challconfig;
|
mod challconfig;
|
||||||
@@ -32,6 +33,7 @@ fn inner_main() -> CommandError {
|
|||||||
Box::new(pgp::CommandImpl),
|
Box::new(pgp::CommandImpl),
|
||||||
Box::new(pgpcardlist::CommandImpl),
|
Box::new(pgpcardlist::CommandImpl),
|
||||||
Box::new(pgpcardsign::CommandImpl),
|
Box::new(pgpcardsign::CommandImpl),
|
||||||
|
Box::new(pgpcarddecrypt::CommandImpl),
|
||||||
Box::new(piv::CommandImpl),
|
Box::new(piv::CommandImpl),
|
||||||
Box::new(chall::CommandImpl),
|
Box::new(chall::CommandImpl),
|
||||||
Box::new(challconfig::CommandImpl),
|
Box::new(challconfig::CommandImpl),
|
||||||
|
|||||||
@@ -18,7 +18,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 List subcommand")
|
SubCommand::with_name(self.name()).about("OpenPGP Card List subcommand")
|
||||||
.arg(Arg::with_name("in").long("in").takes_value(true).help("File input"))
|
.arg(Arg::with_name("in").short("i").long("in").takes_value(true).help("File input"))
|
||||||
.arg(Arg::with_name("detail").long("detail").help("Detail output"))
|
.arg(Arg::with_name("detail").long("detail").help("Detail output"))
|
||||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||||
}
|
}
|
||||||
|
|||||||
61
src/pgpcarddecrypt.rs
Normal file
61
src/pgpcarddecrypt.rs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
use clap::{ArgMatches, SubCommand, App, Arg};
|
||||||
|
use crate::cmd::{Command, CommandError};
|
||||||
|
use openpgp_card::DecryptMe;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
pub struct CommandImpl;
|
||||||
|
|
||||||
|
impl Command for CommandImpl {
|
||||||
|
fn name(&self) -> &str { "pgp-card-decrypt" }
|
||||||
|
|
||||||
|
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||||
|
SubCommand::with_name(self.name()).about("OpenPGP Card List subcommand")
|
||||||
|
.arg(Arg::with_name("pass").short("p").long("pass").takes_value(true).default_value("123456").help("OpenPGP card password"))
|
||||||
|
.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("json").long("json").help("JSON output"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||||
|
let json_output = sub_arg_matches.is_present("json");
|
||||||
|
if json_output {
|
||||||
|
rust_util::util_msg::set_logger_std_out(false);
|
||||||
|
}
|
||||||
|
let pass = sub_arg_matches.value_of("pass");
|
||||||
|
let pass = match pass {
|
||||||
|
Some(p) => p,
|
||||||
|
None => return simple_error!("Pass must be assigned"),
|
||||||
|
};
|
||||||
|
let cipher = sub_arg_matches.value_of("cipher");
|
||||||
|
let cipher_base64 = sub_arg_matches.value_of("cipher-base64");
|
||||||
|
|
||||||
|
let mut json = BTreeMap::<&'_ str, String>::new();
|
||||||
|
|
||||||
|
let cipher_bytes = if let Some(cipher) = cipher {
|
||||||
|
opt_result!(hex::decode(cipher), "Decode cipher failed: {}")
|
||||||
|
} else if let Some(cipher_base64) = cipher_base64 {
|
||||||
|
opt_result!(base64::decode(cipher_base64), "Decode cipher-base64 failed: {}")
|
||||||
|
} else {
|
||||||
|
return simple_error!("cipher or cipher-base64 must assign one");
|
||||||
|
};
|
||||||
|
|
||||||
|
let user = crate::pgpcardutil::get_card_user_sw1_82(pass)?;
|
||||||
|
let text = user.decrypt(DecryptMe::RSA(&cipher_bytes))?;
|
||||||
|
success!("Clear text HEX: {}", hex::encode(&text));
|
||||||
|
success!("Clear text base64: {}", base64::encode(&text));
|
||||||
|
success!("Clear text UTF-8: {}", String::from_utf8_lossy(&text));
|
||||||
|
if json_output {
|
||||||
|
json.insert("cipher_hex", hex::encode(&cipher_bytes));
|
||||||
|
json.insert("cipher_base64", base64::encode(&cipher_bytes));
|
||||||
|
json.insert("text_hex", hex::encode(&text));
|
||||||
|
json.insert("text_utf8", String::from_utf8_lossy(&text).to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if json_output {
|
||||||
|
println!("{}", serde_json::to_string_pretty(&json).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,10 +11,10 @@ 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 List subcommand")
|
SubCommand::with_name(self.name()).about("OpenPGP Card List subcommand")
|
||||||
.arg(Arg::with_name("pass").long("pass").takes_value(true).default_value("123456").help("OpenPGP card password"))
|
.arg(Arg::with_name("pass").short("p").long("pass").takes_value(true).default_value("123456").help("OpenPGP card password"))
|
||||||
.arg(Arg::with_name("sha256").long("sha256").takes_value(true).help("Digest SHA256"))
|
.arg(Arg::with_name("sha256").short("2").long("sha256").takes_value(true).help("Digest SHA256 HEX"))
|
||||||
.arg(Arg::with_name("sha384").long("sha384").takes_value(true).help("Digest SHA384"))
|
.arg(Arg::with_name("sha384").short("3").long("sha384").takes_value(true).help("Digest SHA384 HEX"))
|
||||||
.arg(Arg::with_name("sha512").long("sha512").takes_value(true).help("Digest SHA512"))
|
.arg(Arg::with_name("sha512").short("5").long("sha512").takes_value(true).help("Digest SHA512 HEX"))
|
||||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,3 +18,20 @@ pub fn get_card_user_sw1_81(pass: &str) -> XResult<OpenPGPCardUser> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_card_user_sw1_82(pass: &str) -> XResult<OpenPGPCardUser> {
|
||||||
|
match OpenPGPCard::list_cards() {
|
||||||
|
Ok(list) => {
|
||||||
|
// pw1_82 for decrypt
|
||||||
|
// PKCSv1.5
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ impl Command for CommandImpl {
|
|||||||
|
|
||||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||||
SubCommand::with_name(self.name()).about("Register subcommand")
|
SubCommand::with_name(self.name()).about("Register subcommand")
|
||||||
.arg(Arg::with_name("app-id").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").long("timeout").default_value("10").help("Timeout in seconds"))
|
.arg(Arg::with_name("timeout").short("t").long("timeout").default_value("10").help("Timeout in seconds"))
|
||||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ impl Command for CommandImpl {
|
|||||||
fn name(&self) -> &str { "sign" }
|
fn name(&self) -> &str { "sign" }
|
||||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||||
SubCommand::with_name(self.name()).about("Sign subcommand")
|
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("app-id").short("a").long("app-id").default_value("https://example.com").help("App id"))
|
||||||
.arg(Arg::with_name("timeout").long("timeout").default_value("10").help("Timeout in seconds"))
|
.arg(Arg::with_name("timeout").short("t").long("timeout").default_value("10").help("Timeout in seconds"))
|
||||||
.arg(Arg::with_name("key-handle").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"))
|
||||||
}
|
}
|
||||||
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 app_id = sub_arg_matches.value_of("app-id").unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user