Merge branch 'add-more-examples' into 'main'
Add decrypt and detach-sign examples See merge request hkos/openpgp-card!1
This commit is contained in:
commit
40c52c7f3a
5 changed files with 169 additions and 0 deletions
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
|
"openpgp-card-apps",
|
||||||
"openpgp-card",
|
"openpgp-card",
|
||||||
"openpgp-card-sequoia",
|
"openpgp-card-sequoia",
|
||||||
"pcsc",
|
"pcsc",
|
||||||
|
|
25
openpgp-card-apps/Cargo.toml
Normal file
25
openpgp-card-apps/Cargo.toml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# SPDX-FileCopyrightText: 2021 Wiktor Kwapisiewicz <wiktor@metacode.biz>
|
||||||
|
# SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "openpgp-card-apps"
|
||||||
|
description = "Examples and demos of apps utilizing openpgp-card-sequoia"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = ["Wiktor Kwapisiewicz <wiktor@metacode.biz>"]
|
||||||
|
edition = "2018"
|
||||||
|
repository = "https://gitlab.com/hkos/openpgp-card"
|
||||||
|
documentation = "https://docs.rs/crate/openpgp-card-apps"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
sequoia-openpgp = "1.3"
|
||||||
|
nettle = "7"
|
||||||
|
openpgp-card = { path = "../openpgp-card", version = "0.0.4" }
|
||||||
|
openpgp-card-pcsc = { path = "../pcsc", version = "0.0.4" }
|
||||||
|
openpgp-card-scdc = { path = "../scdc", version = "0.0.2" }
|
||||||
|
openpgp-card-sequoia = { path = "../openpgp-card-sequoia", version = "0.0.3" }
|
||||||
|
chrono = "0.4"
|
||||||
|
anyhow = "1"
|
||||||
|
thiserror = "1"
|
||||||
|
env_logger = "0.8"
|
||||||
|
log = "0.4"
|
43
openpgp-card-apps/README.md
Normal file
43
openpgp-card-apps/README.md
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2021 Wiktor Kwapisiewicz <wiktor@metacode.biz>
|
||||||
|
SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
-->
|
||||||
|
|
||||||
|
**OpenPGP card usage with Sequoia PGP: Example apps**
|
||||||
|
|
||||||
|
*Small GnuPG replacements*
|
||||||
|
|
||||||
|
This crate can be used to decrypt OpenPGP data and to sign data
|
||||||
|
producing OpenPGP data.
|
||||||
|
|
||||||
|
First export the certificate that holds keys stored on the card:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gpg --export --armor $KEYID > cert.asc
|
||||||
|
```
|
||||||
|
|
||||||
|
Then create a test data, encrypted with GnuPG (as an example):
|
||||||
|
|
||||||
|
```
|
||||||
|
$ echo example data | gpg -ear $KEYID > encrypted.asc
|
||||||
|
```
|
||||||
|
|
||||||
|
And put the card PIN in a file called `pin`.
|
||||||
|
|
||||||
|
And then use the crate for decryption:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cargo run --example decrypt $CARD_ID pin cert.asc < encrypted.asc
|
||||||
|
```
|
||||||
|
|
||||||
|
The `$CARD_ID` holds card ident that can be printed using `cargo
|
||||||
|
run`. It's a string that looks like `0006:12345678`. Remember that if
|
||||||
|
the GnuPG agent is holding an exclusive access to the card it will not
|
||||||
|
show up. Unplugging and plugging the card again will relinquish
|
||||||
|
GnuPG's agent's hold on the card.
|
||||||
|
|
||||||
|
Signing works the same way:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ echo data to be signed | cargo run --example detach-sign $CARD_ID pin cert.asc > signature.asc
|
||||||
|
```
|
46
openpgp-card-apps/src/bin/decrypt.rs
Normal file
46
openpgp-card-apps/src/bin/decrypt.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 Wiktor Kwapisiewicz <wiktor@metacode.biz>
|
||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
use openpgp_card_pcsc::PcscClient;
|
||||||
|
|
||||||
|
use openpgp_card_sequoia::card::Open;
|
||||||
|
|
||||||
|
use openpgp::parse::{stream::DecryptorBuilder, Parse};
|
||||||
|
use openpgp::policy::StandardPolicy;
|
||||||
|
use openpgp::Cert;
|
||||||
|
use sequoia_openpgp as openpgp;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let args = std::env::args().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if args.len() < 3 {
|
||||||
|
eprintln!("Usage: decrypt card-ident pin-file cert-file");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let card_ident = &args[0];
|
||||||
|
let pin_file = &args[1];
|
||||||
|
let cert_file = &args[2];
|
||||||
|
|
||||||
|
let mut open = Open::open_card(PcscClient::open_by_ident(&card_ident)?)?;
|
||||||
|
|
||||||
|
let pin = std::fs::read_to_string(pin_file)?;
|
||||||
|
|
||||||
|
open.verify_user(&pin)?;
|
||||||
|
|
||||||
|
let mut user = open.user_card().unwrap();
|
||||||
|
|
||||||
|
let p = StandardPolicy::new();
|
||||||
|
let cert = Cert::from_file(cert_file)?;
|
||||||
|
let d = user.decryptor(&cert, &p)?;
|
||||||
|
let stdin = std::io::stdin();
|
||||||
|
|
||||||
|
let mut stdout = std::io::stdout();
|
||||||
|
|
||||||
|
let db = DecryptorBuilder::from_reader(stdin)?;
|
||||||
|
let mut decryptor = db.with_policy(&p, None, d)?;
|
||||||
|
|
||||||
|
std::io::copy(&mut decryptor, &mut stdout)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
54
openpgp-card-apps/src/bin/detach-sign.rs
Normal file
54
openpgp-card-apps/src/bin/detach-sign.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 Wiktor Kwapisiewicz <wiktor@metacode.biz>
|
||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
use openpgp_card_pcsc::PcscClient;
|
||||||
|
|
||||||
|
use openpgp_card_sequoia::card::Open;
|
||||||
|
|
||||||
|
use openpgp::parse::Parse;
|
||||||
|
use openpgp::policy::StandardPolicy;
|
||||||
|
use openpgp::serialize::stream::{Armorer, Message, Signer};
|
||||||
|
use openpgp::Cert;
|
||||||
|
use sequoia_openpgp as openpgp;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let args = std::env::args().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if args.len() < 3 {
|
||||||
|
eprintln!("Usage: detach-sign card-ident pin-file cert-file");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let test_card_ident = &args[0];
|
||||||
|
let pin_file = &args[1];
|
||||||
|
let cert_file = &args[2];
|
||||||
|
|
||||||
|
let mut open =
|
||||||
|
Open::open_card(PcscClient::open_by_ident(&test_card_ident)?)?;
|
||||||
|
|
||||||
|
let pin = std::fs::read_to_string(pin_file)?;
|
||||||
|
|
||||||
|
open.verify_user_for_signing(&pin)?;
|
||||||
|
|
||||||
|
let mut user = open.signing_card().unwrap();
|
||||||
|
|
||||||
|
let p = StandardPolicy::new();
|
||||||
|
let cert = Cert::from_file(cert_file)?;
|
||||||
|
let s = user.signer(&cert, &p)?;
|
||||||
|
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
|
||||||
|
let message = Message::new(stdout);
|
||||||
|
|
||||||
|
let message = Armorer::new(message).build()?;
|
||||||
|
|
||||||
|
let signer = Signer::new(message, s);
|
||||||
|
|
||||||
|
let mut signer = signer.detached().build()?;
|
||||||
|
|
||||||
|
std::io::copy(&mut std::io::stdin(), &mut signer)?;
|
||||||
|
|
||||||
|
signer.finalize()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in a new issue