keyfork-user-guide: more additions
This commit is contained in:
parent
8809db6f7f
commit
5d5d5181b3
|
@ -1 +1,2 @@
|
||||||
target
|
target
|
||||||
|
testing_data
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{env, str::FromStr};
|
use std::{env, process::ExitCode, str::FromStr};
|
||||||
|
|
||||||
use keyfork_derive_util::{
|
use keyfork_derive_util::{
|
||||||
request::{DerivationAlgorithm, DerivationError, DerivationRequest},
|
request::{DerivationAlgorithm, DerivationError, DerivationRequest},
|
||||||
|
@ -27,7 +27,7 @@ fn validate(algo: &str, path: &str) -> Result<(DerivationAlgorithm, DerivationPa
|
||||||
Ok((algo, path))
|
Ok((algo, path))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut args = env::args();
|
let mut args = env::args();
|
||||||
let program_name = args.next().expect("program name");
|
let program_name = args.next().expect("program name");
|
||||||
let args = args.collect::<Vec<_>>();
|
let args = args.collect::<Vec<_>>();
|
||||||
|
@ -42,3 +42,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
println!("{}", smex::encode(&response.data));
|
println!("{}", smex::encode(&response.data));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() -> ExitCode {
|
||||||
|
if let Err(e) = run() {
|
||||||
|
eprintln!("Error: {e}");
|
||||||
|
ExitCode::FAILURE
|
||||||
|
} else {
|
||||||
|
ExitCode::SUCCESS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
|
||||||
env,
|
env,
|
||||||
io::{stdin, stdout},
|
io::{stdin, stdout},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
|
@ -7,30 +6,7 @@ use std::{
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
use keyfork_shard::{combine, discover_certs, openpgp::Cert, EncryptedMessage};
|
use keyfork_shard::{combine, discover_certs, parse_messages, openpgp::Cert};
|
||||||
use openpgp::{
|
|
||||||
packet::Packet,
|
|
||||||
parse::Parse,
|
|
||||||
PacketPile,
|
|
||||||
};
|
|
||||||
use sequoia_openpgp as openpgp;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
enum Error {
|
|
||||||
Usage(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for Error {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Error::Usage(program_name) => {
|
|
||||||
write!(f, "Usage: {program_name} threshold key_discovery")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for Error {}
|
|
||||||
|
|
||||||
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
|
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
|
||||||
|
|
||||||
|
@ -53,25 +29,10 @@ fn run() -> Result<()> {
|
||||||
let args = args.collect::<Vec<_>>();
|
let args = args.collect::<Vec<_>>();
|
||||||
let (threshold, cert_list) = match args.as_slice() {
|
let (threshold, cert_list) = match args.as_slice() {
|
||||||
[threshold, key_discovery] => validate(threshold, key_discovery)?,
|
[threshold, key_discovery] => validate(threshold, key_discovery)?,
|
||||||
_ => return Err(Error::Usage(program_name).into()),
|
_ => panic!("Usage: {program_name} threshold key_discovery"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let stdin = stdin();
|
let mut encrypted_messages = parse_messages(stdin())?;
|
||||||
|
|
||||||
let mut pkesks = Vec::new();
|
|
||||||
let mut encrypted_messages = VecDeque::new();
|
|
||||||
|
|
||||||
for packet in PacketPile::from_reader(stdin)?.into_children() {
|
|
||||||
match packet {
|
|
||||||
Packet::PKESK(p) => pkesks.push(p),
|
|
||||||
Packet::SEIP(s) => {
|
|
||||||
encrypted_messages.push_back(EncryptedMessage::with_swap(&mut pkesks, s));
|
|
||||||
}
|
|
||||||
s => {
|
|
||||||
panic!("Invalid variant found: {}", s.tag());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let encrypted_metadata = encrypted_messages
|
let encrypted_metadata = encrypted_messages
|
||||||
.pop_front()
|
.pop_front()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::{HashMap, VecDeque},
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
|
@ -12,7 +12,7 @@ use keyfork_derive_openpgp::derive_util::{
|
||||||
use openpgp::{
|
use openpgp::{
|
||||||
armor::{Kind, Writer},
|
armor::{Kind, Writer},
|
||||||
cert::{Cert, CertParser, ValidCert},
|
cert::{Cert, CertParser, ValidCert},
|
||||||
packet::{Tag, UserID, PKESK, SEIP},
|
packet::{Packet, Tag, UserID, PKESK, SEIP},
|
||||||
parse::{stream::DecryptorBuilder, Parse},
|
parse::{stream::DecryptorBuilder, Parse},
|
||||||
policy::{NullPolicy, Policy, StandardPolicy},
|
policy::{NullPolicy, Policy, StandardPolicy},
|
||||||
serialize::{
|
serialize::{
|
||||||
|
@ -20,7 +20,7 @@ use openpgp::{
|
||||||
Marshal,
|
Marshal,
|
||||||
},
|
},
|
||||||
types::KeyFlags,
|
types::KeyFlags,
|
||||||
KeyID,
|
KeyID, PacketPile
|
||||||
};
|
};
|
||||||
pub use sequoia_openpgp as openpgp;
|
pub use sequoia_openpgp as openpgp;
|
||||||
use sharks::{Share, Sharks};
|
use sharks::{Share, Sharks};
|
||||||
|
@ -75,24 +75,6 @@ impl EncryptedMessage {
|
||||||
message.write_all(&packet)?;
|
message.write_all(&packet)?;
|
||||||
message.finalize()?;
|
message.finalize()?;
|
||||||
|
|
||||||
/*
|
|
||||||
// TODO: only serialize the message and use provided PKESK vec
|
|
||||||
let mut pkesks = vec![];
|
|
||||||
let ppr = PacketParser::from_reader(&packets[..])?;
|
|
||||||
while let PacketParserResult::Some(mut pp) = ppr {
|
|
||||||
match pp.packet {
|
|
||||||
openpgp::Packet::PKESK(pkesk) => pkesks.push(pkesk),
|
|
||||||
openpgp::Packet::SEIP(_) => {
|
|
||||||
keyring.decrypt(&pkesks, &[], None, |algo, sk| {
|
|
||||||
// pushes packet to stack
|
|
||||||
pp.decrypt(algo, sk).is_ok()
|
|
||||||
});
|
|
||||||
},
|
|
||||||
p => panic!("Unexpected packet type: {}", p.tag()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
let mut decryptor =
|
let mut decryptor =
|
||||||
DecryptorBuilder::from_bytes(&packets)?.with_policy(policy, None, keyring)?;
|
DecryptorBuilder::from_bytes(&packets)?.with_policy(policy, None, keyring)?;
|
||||||
|
|
||||||
|
@ -124,6 +106,25 @@ pub fn discover_certs(path: impl AsRef<Path>) -> Result<Vec<Cert>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_messages(reader: impl Read + Send + Sync) -> Result<VecDeque<EncryptedMessage> >{
|
||||||
|
let mut pkesks = Vec::new();
|
||||||
|
let mut encrypted_messages = VecDeque::new();
|
||||||
|
|
||||||
|
for packet in PacketPile::from_reader(reader)?.into_children() {
|
||||||
|
match packet {
|
||||||
|
Packet::PKESK(p) => pkesks.push(p),
|
||||||
|
Packet::SEIP(s) => {
|
||||||
|
encrypted_messages.push_back(EncryptedMessage::with_swap(&mut pkesks, s));
|
||||||
|
}
|
||||||
|
s => {
|
||||||
|
panic!("Invalid variant found: {}", s.tag());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(encrypted_messages)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_encryption_keys<'a>(
|
fn get_encryption_keys<'a>(
|
||||||
cert: &'a ValidCert,
|
cert: &'a ValidCert,
|
||||||
) -> openpgp::cert::prelude::ValidKeyAmalgamationIter<
|
) -> openpgp::cert::prelude::ValidKeyAmalgamationIter<
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<!-- vim:set et sts=0 sw=2 ts=2: -->
|
<!-- vim:set et sts=0 sw=2 ts=2: -->
|
||||||
# Summary
|
# Summary
|
||||||
|
|
||||||
|
# User Guide
|
||||||
|
|
||||||
- [Installing Keyfork](./INSTALL.md)
|
- [Installing Keyfork](./INSTALL.md)
|
||||||
- [Common Usage](./usage.md)
|
- [Common Usage](./usage.md)
|
||||||
- [Binaries](./bin/index.md)
|
- [Binaries](./bin/index.md)
|
||||||
|
@ -11,4 +13,8 @@
|
||||||
- [keyfork-mnemonic-from-seed](./bin/keyfork-plumbing/mnemonic-from-seed.md)
|
- [keyfork-mnemonic-from-seed](./bin/keyfork-plumbing/mnemonic-from-seed.md)
|
||||||
- [keyfork-derive-key](./bin/keyfork-derive-key.md)
|
- [keyfork-derive-key](./bin/keyfork-derive-key.md)
|
||||||
- [keyfork-derive-openpgp](./bin/keyfork-derive-openpgp.md)
|
- [keyfork-derive-openpgp](./bin/keyfork-derive-openpgp.md)
|
||||||
- [Development Guide](./dev-guide/index.md)
|
|
||||||
|
# Developers Guide
|
||||||
|
|
||||||
|
- [Writing Binaries](./dev-guide/index.md)
|
||||||
|
- [Auditing](./dev-guide/auditing.md)
|
||||||
|
|
|
@ -18,3 +18,5 @@ the shell silently ignoring the single quotes in the derivation path.
|
||||||
|
|
||||||
Hex-encoded private key. Note that this is not the _extended_ private key, and
|
Hex-encoded private key. Note that this is not the _extended_ private key, and
|
||||||
can't be used to derive further data.
|
can't be used to derive further data.
|
||||||
|
|
||||||
|
[`keyforkd`]: ./bin/keyforkd.md
|
||||||
|
|
|
@ -28,3 +28,5 @@ the shell silently ignoring the single quotes in the derivation path.
|
||||||
## Output
|
## Output
|
||||||
|
|
||||||
OpenPGP ASCII armored key, signed to be valid for 24 hours.
|
OpenPGP ASCII armored key, signed to be valid for 24 hours.
|
||||||
|
|
||||||
|
[`keyforkd`]: ./bin/keyforkd.md
|
||||||
|
|
|
@ -12,11 +12,16 @@ requires a system be both offline and running an up-to-date kernel before
|
||||||
generating a mnemonic. However, the command may be run with the variable
|
generating a mnemonic. However, the command may be run with the variable
|
||||||
`INSECURE_HARDWARE_ALLOWED=1` to override system validation.
|
`INSECURE_HARDWARE_ALLOWED=1` to override system validation.
|
||||||
|
|
||||||
## Usage
|
## Arguments
|
||||||
|
|
||||||
```
|
`keyfork mnemonic generate --source=system --size=256`
|
||||||
% keyfork mnemonic generate
|
|
||||||
ceiling talent smooth jealous dust render hello resource ripple crucial pepper tribe noble gate shield glad slide document pulse negative spider this fancy seven
|
* `--source`: The source from where a seed is created. Can be:
|
||||||
% keyfork mnemonic generate --size 128
|
* `system`
|
||||||
sustain glory control silk gym argue jaguar citizen remember doctor depth senior
|
|
||||||
```
|
Choosing any option besides `system` will prompt the user for input:
|
||||||
|
|
||||||
|
* `playing`
|
||||||
|
* `tarot`
|
||||||
|
* `dice`
|
||||||
|
* `--size`: The size in bits for the memonic, either `128` or `256`.
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Auditing Dependencies
|
||||||
|
|
||||||
|
Dependencies must be reviewed before being added to the repository, and must
|
||||||
|
not be added for pure convenience. There are few exceptions, such as `clap` and
|
||||||
|
`thiserror`, which provide derivation macros that are used heavily throughout
|
||||||
|
`keyfork` and the codebase as a whole. Any dependency added must be reviewed at
|
||||||
|
least on a surface level to ensure no malicious actions are performed with the
|
||||||
|
data the library will be responsible for handling. For example, any use of
|
||||||
|
`std::process` in a crate providing cryptographic functions should be heavily
|
||||||
|
scrutinized, and any crate that loads arbitrary code or performs networking
|
||||||
|
requests should have an incredibly important reason for doing so.
|
||||||
|
|
||||||
|
Dependencies should be restricted such that the least amount of dead code is
|
||||||
|
enabled. For instance, a crate such as `keyfork_derive_openpgp` can only make
|
||||||
|
use of the `ed25519` algorithm, so it exports its own `derive_util` that only
|
||||||
|
includes the crates required for that library. This can then be used by
|
||||||
|
programs such as `keyfork-shard`'s OpenPGP mode or `keyfork provision openpgp`
|
||||||
|
to ensure only the required dependencies are enabled. This reduces the burden
|
||||||
|
of auditors, but it does mean we can't use projects such as [`hakari`] to
|
||||||
|
optimize full-project builds.
|
||||||
|
|
||||||
|
[`hakari`]: https://docs.rs/cargo-hakari/latest/cargo_hakari/index.html
|
|
@ -1,4 +1,4 @@
|
||||||
# Development Guide
|
# Writing Binaries
|
||||||
|
|
||||||
### Binaries - Porcelain and Plumbing
|
### Binaries - Porcelain and Plumbing
|
||||||
|
|
||||||
|
@ -13,25 +13,80 @@ Usually, only cryptographic functionality (such as `sequoia-openpgp` or
|
||||||
`dalek-ed25519`) or hardware integration libraries (such as `openpgp-card`) are
|
`dalek-ed25519`) or hardware integration libraries (such as `openpgp-card`) are
|
||||||
included.
|
included.
|
||||||
|
|
||||||
### Auditing Dependencies
|
### Writing Binaries
|
||||||
|
|
||||||
Dependencies must be reviewed before being added to the repository, and must
|
Crates can be either a library, or a library and binary, but should never be
|
||||||
not be added for pure convenience. There are few exceptions, such as `clap` and
|
just a binary. When creating a crate with a binary, the `main.rs` file should
|
||||||
`thiserror`, which provide derivation macros that are used heavily throughout
|
be designed to validate arguments, load any necessary system resources, and
|
||||||
`keyfork` and the codebase as a whole. Any dependency added must be reviewed at
|
call a separate exposed function to do the heavy lifting. The following example
|
||||||
least on a surface level to ensure no malicious actions are performed with the
|
was taken from `keyfork-shard` to demonstrate how a program can validate
|
||||||
data the library will be responsible for handling. For example, any use of
|
arguments, parse input, and stream an output.
|
||||||
`std::process` in a crate providing cryptographic functions should be heavily
|
|
||||||
scrutinized, and any crate that loads arbitrary code or performs networking
|
|
||||||
requests should have an incredibly important reason for doing so.
|
|
||||||
|
|
||||||
Dependencies should be restricted such that the least amount of dead code is
|
```rust
|
||||||
enabled. For instance, a crate such as `keyfork_derive_openpgp` can only make
|
use std::{
|
||||||
use of the `ed25519` algorithm, so it exports its own `derive_util` that only
|
collections::VecDeque,
|
||||||
includes the crates required for that library. This can then be used by
|
env,
|
||||||
programs such as `keyfork-shard`'s OpenPGP mode or `keyfork provision openpgp`
|
io::{stdin, stdout},
|
||||||
to ensure only the required dependencies are enabled. This reduces the burden
|
path::PathBuf,
|
||||||
of auditors, but it does mean we can't use projects such as [`hakari`] to
|
process::ExitCode,
|
||||||
optimize full-project builds.
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
[`hakari`]: https://docs.rs/cargo-hakari/latest/cargo_hakari/index.html
|
use keyfork_shard::openpgp::{combine, discover_certs, openpgp::Cert};
|
||||||
|
use sequoia_openpgp as openpgp;
|
||||||
|
|
||||||
|
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
|
||||||
|
|
||||||
|
fn validate(threshold: &str, key_discovery: &str) -> Result<(u8, Vec<Cert>)> {
|
||||||
|
let threshold = u8::from_str(threshold)?;
|
||||||
|
let key_discovery = PathBuf::from(key_discovery);
|
||||||
|
|
||||||
|
// Verify path exists
|
||||||
|
std::fs::metadata(&key_discovery)?;
|
||||||
|
|
||||||
|
// Load certs from path
|
||||||
|
let certs = discover_certs(key_discovery)?;
|
||||||
|
|
||||||
|
Ok((threshold, certs))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run() -> Result<()> {
|
||||||
|
let mut args = env::args();
|
||||||
|
let program_name = args.next().expect("program name");
|
||||||
|
let args = args.collect::<Vec<_>>();
|
||||||
|
let (threshold, cert_list) = match args.as_slice() {
|
||||||
|
[threshold, key_discovery] => validate(threshold, key_discovery)?,
|
||||||
|
_ => panic!("Usage: {program_name} threshold key_discovery"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let encrypted_messages = parse_messages(stdin())?;
|
||||||
|
|
||||||
|
let encrypted_metadata = encrypted_messages
|
||||||
|
.pop_front()
|
||||||
|
.expect("any pgp encrypted message");
|
||||||
|
|
||||||
|
combine(
|
||||||
|
threshold,
|
||||||
|
cert_list,
|
||||||
|
encrypted_metadata,
|
||||||
|
encrypted_messages.into(),
|
||||||
|
stdout(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> ExitCode {
|
||||||
|
let result = run();
|
||||||
|
if let Err(e) = result {
|
||||||
|
eprintln!("Error: {e}");
|
||||||
|
return ExitCode::FAILURE;
|
||||||
|
}
|
||||||
|
ExitCode::SUCCESS
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Designing binaries with this format makes it easier to load them to the Keyfork
|
||||||
|
porcelain binary, since the porcelain can call `combine()` with arguments that
|
||||||
|
it has parsed using its own configuration systems, using a `String` as a `mut
|
||||||
|
Write` as necessary.
|
||||||
|
|
Loading…
Reference in New Issue