Compare commits
No commits in common. "main" and "ryansquared/keyfork-mnemonic-refactors" have entirely different histories.
main
...
ryansquare
131
CHANGELOG.md
131
CHANGELOG.md
|
@ -1,134 +1,3 @@
|
||||||
# Keyfork v0.2.4
|
|
||||||
|
|
||||||
This release includes a lot of "maintenance" changes, without any changes in
|
|
||||||
end-user functionality.
|
|
||||||
|
|
||||||
### Changes in keyfork:
|
|
||||||
|
|
||||||
The most significant change in this release is the reorganization of some of
|
|
||||||
the subcommands, where they would be better as enum-traits, such as `keyfork
|
|
||||||
derive` and `keyfork wizard`.
|
|
||||||
|
|
||||||
```
|
|
||||||
b254ba7 cleanup post-merge
|
|
||||||
58d3c34 Merge branch 'main' into ryansquared/staging-since-latest
|
|
||||||
35f57fc Merge branch 'ryansquared/keyfork-mnemonic-refactors'
|
|
||||||
a2eb5fd bump dependencies with listed vulnerabilities (not affected)
|
|
||||||
5219c5a keyfork: enum-trait-ify choose-your-own commands
|
|
||||||
b26f296 keyfork-derive-path-data: move all pathcrafting here
|
|
||||||
35ab5e6 keyfork-mnemonic-util => keyfork-mnemonic
|
|
||||||
f5627e5 keyfork-mnemonic-util: impl try_from_slice and from_array
|
|
||||||
02e5b54 keyfork-mnemonic-util::generate_seed: return const size array
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changes in keyfork-derive-openpgp:
|
|
||||||
|
|
||||||
```
|
|
||||||
b254ba7 cleanup post-merge
|
|
||||||
35f57fc Merge branch 'ryansquared/keyfork-mnemonic-refactors'
|
|
||||||
a2eb5fd bump dependencies with listed vulnerabilities (not affected)
|
|
||||||
b26f296 keyfork-derive-path-data: move all pathcrafting here
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changes in keyfork-derive-path-data:
|
|
||||||
|
|
||||||
This change now centralizes all special Keyfork paths. This means crates should
|
|
||||||
no longer be required to implement their own path parsing logic.
|
|
||||||
|
|
||||||
```
|
|
||||||
b26f296 keyfork-derive-path-data: move all pathcrafting here
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changes in keyfork-derive-util:
|
|
||||||
|
|
||||||
```
|
|
||||||
35ab5e6 keyfork-mnemonic-util => keyfork-mnemonic
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changes in keyfork-mnemonic:
|
|
||||||
|
|
||||||
`keyfork-mnemonic-util` has finally been renamed to `keyfork-mnemonic`. The
|
|
||||||
method names `as_bytes() => as_slice()`, `to_bytes() => to_vec()`, and
|
|
||||||
`into_bytes() => into_vec()`, and the function names
|
|
||||||
`from_bytes() => try_from_slice()` and
|
|
||||||
`from_nonstandard_bytes() => from_array()`, have been implemented to more
|
|
||||||
closely represent the native types they are representing. Additionally,
|
|
||||||
`Mnemonic::generate_seed()` has been modified to return a constant size array;
|
|
||||||
this is a breaking change, but should have minimal impact.
|
|
||||||
|
|
||||||
```
|
|
||||||
35ab5e6 keyfork-mnemonic-util => keyfork-mnemonic
|
|
||||||
3ee81b6 keyfork-mnemonic-util: impl as_slice to_vec into_vec
|
|
||||||
f5627e5 keyfork-mnemonic-util: impl try_from_slice and from_array
|
|
||||||
02e5b54 keyfork-mnemonic-util::generate_seed: return const size array
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changes in keyfork-prompt:
|
|
||||||
|
|
||||||
```
|
|
||||||
35ab5e6 keyfork-mnemonic-util => keyfork-mnemonic
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changes in keyfork-shard:
|
|
||||||
|
|
||||||
```
|
|
||||||
58d3c34 Merge branch 'main' into ryansquared/staging-since-latest
|
|
||||||
35ab5e6 keyfork-mnemonic-util => keyfork-mnemonic
|
|
||||||
f5627e5 keyfork-mnemonic-util: impl try_from_slice and from_array
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changes in keyforkd:
|
|
||||||
|
|
||||||
```
|
|
||||||
35ab5e6 keyfork-mnemonic-util => keyfork-mnemonic
|
|
||||||
02e5b54 keyfork-mnemonic-util::generate_seed: return const size array
|
|
||||||
536e6da keyforkd{,-client}: lots of documentationings
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changes in keyforkd-client:
|
|
||||||
|
|
||||||
```
|
|
||||||
536e6da keyforkd{,-client}: lots of documentationings
|
|
||||||
```
|
|
||||||
|
|
||||||
# Keyfork v0.2.3
|
|
||||||
|
|
||||||
This release includes a bugfix for the wizard where the wizard was too strict
|
|
||||||
about when keys were "alive".
|
|
||||||
|
|
||||||
### Changes in keyfork:
|
|
||||||
|
|
||||||
```
|
|
||||||
dd4354f keyfork: bump keyfork-shard
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changes in keyfork-shard:
|
|
||||||
|
|
||||||
```
|
|
||||||
ba64db8 update Cargo.toml and Cargo.lock
|
|
||||||
fa84a2a keyfork-shard: Be less strict about keys
|
|
||||||
```
|
|
||||||
|
|
||||||
# Keyfork v0.2.2
|
|
||||||
|
|
||||||
This release adds a new wizard, intended to be used at DEFCON 32.
|
|
||||||
|
|
||||||
### Changes in keyfork:
|
|
||||||
|
|
||||||
```
|
|
||||||
8d40d26 keyfork: add `bottoms-up` wizard
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changes in keyfork-derive-openpgp:
|
|
||||||
|
|
||||||
This change also includes a minor change, allowing the derivation path for
|
|
||||||
`keyfork-derive-openpg` to derive further than two paths, which was useful in
|
|
||||||
the testing of the wizard.
|
|
||||||
|
|
||||||
```
|
|
||||||
8d40d26 keyfork: add `bottoms-up` wizard
|
|
||||||
```
|
|
||||||
|
|
||||||
# Keyfork v0.2.1
|
# Keyfork v0.2.1
|
||||||
|
|
||||||
This release contains an emergency bugfix for Keyfork Shard, which previously
|
This release contains an emergency bugfix for Keyfork Shard, which previously
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
51
Cargo.toml
51
Cargo.toml
|
@ -25,57 +25,6 @@ members = [
|
||||||
"crates/util/smex",
|
"crates/util/smex",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
|
||||||
|
|
||||||
# Keyfork dependencies
|
|
||||||
keyforkd = { version = "0.1.1", path = "crates/daemon/keyforkd", registry = "distrust", default-features = false }
|
|
||||||
keyforkd-client = { version = "0.2.0", path = "crates/daemon/keyforkd-client", registry = "distrust", default-features = false }
|
|
||||||
keyforkd-models = { version = "0.2.0", path = "crates/daemon/keyforkd-models", registry = "distrust", default-features = false }
|
|
||||||
keyfork-derive-key = { version = "0.1.1", path = "crates/derive/keyfork-derive-key", registry = "distrust", default-features = false }
|
|
||||||
keyfork-derive-openpgp = { version = "0.1.2", path = "crates/derive/keyfork-derive-openpgp", registry = "distrust", default-features = false }
|
|
||||||
keyfork-derive-path-data = { version = "0.1.1", path = "crates/derive/keyfork-derive-path-data", registry = "distrust", default-features = false }
|
|
||||||
keyfork-derive-util = { version = "0.2.0", path = "crates/derive/keyfork-derive-util", registry = "distrust", default-features = false }
|
|
||||||
keyfork-shard = { version = "0.2.2", path = "crates/keyfork-shard", registry = "distrust", default-features = false }
|
|
||||||
keyfork-qrcode = { version = "0.1.1", path = "crates/qrcode/keyfork-qrcode", registry = "distrust", default-features = false }
|
|
||||||
keyfork-zbar = { version = "0.1.0", path = "crates/qrcode/keyfork-zbar", registry = "distrust", default-features = false }
|
|
||||||
keyfork-zbar-sys = { version = "0.1.0", path = "crates/qrcode/keyfork-zbar-sys", registry = "distrust", default-features = false }
|
|
||||||
keyfork-bin = { version = "0.1.0", path = "crates/util/keyfork-bin", registry = "distrust", default-features = false }
|
|
||||||
keyfork-bug = { version = "0.1.0", path = "crates/util/keyfork-bug", registry = "distrust", default-features = false }
|
|
||||||
keyfork-crossterm = { version = "0.27.1", path = "crates/util/keyfork-crossterm", registry = "distrust", default-features = false }
|
|
||||||
keyfork-entropy = { version = "0.1.1", path = "crates/util/keyfork-entropy", registry = "distrust", default-features = false }
|
|
||||||
keyfork-frame = { version = "0.1.0", path = "crates/util/keyfork-frame", registry = "distrust", default-features = false }
|
|
||||||
keyfork-mnemonic = { version = "0.4.0", path = "crates/util/keyfork-mnemonic", registry = "distrust", default-features = false }
|
|
||||||
keyfork-prompt = { version = "0.1.1", path = "crates/util/keyfork-prompt", registry = "distrust", default-features = false }
|
|
||||||
keyfork-slip10-test-data = { version = "0.1.0", path = "crates/util/keyfork-slip10-test-data", registry = "distrust", default-features = false }
|
|
||||||
smex = { version = "0.1.0", path = "crates/util/smex", registry = "distrust", default-features = false }
|
|
||||||
|
|
||||||
# External dependencies
|
|
||||||
|
|
||||||
# Cryptography
|
|
||||||
ed25519-dalek = "2.1.1"
|
|
||||||
hmac = "0.12.1"
|
|
||||||
k256 = { version = "0.13.3", default-features = false, features = ["std"] }
|
|
||||||
sha2 = "0.10.8"
|
|
||||||
|
|
||||||
# OpenPGP
|
|
||||||
card-backend-pcsc = "0.5.0"
|
|
||||||
openpgp-card = { version = "0.4.1" }
|
|
||||||
openpgp-card-sequoia = { version = "0.2.0", default-features = false }
|
|
||||||
sequoia-openpgp = { version = "1.21.2", default-features = false, features = ["compression"] }
|
|
||||||
|
|
||||||
# Serialization
|
|
||||||
bincode = "1.3.3"
|
|
||||||
serde = { version= "1.0.195", features = ["derive"] }
|
|
||||||
serde_json = "1.0.111"
|
|
||||||
|
|
||||||
# Misc.
|
|
||||||
anyhow = "1.0.79"
|
|
||||||
hex-literal = "0.4.1"
|
|
||||||
image = { version = "0.25.2", default-features = false }
|
|
||||||
thiserror = "1.0.56"
|
|
||||||
tokio = "1.35.1"
|
|
||||||
v4l = "0.14.0"
|
|
||||||
|
|
||||||
[profile.dev.package.keyfork-qrcode]
|
[profile.dev.package.keyfork-qrcode]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
debug = true
|
debug = true
|
||||||
|
|
92
bacon.toml
92
bacon.toml
|
@ -1,92 +0,0 @@
|
||||||
# This is a configuration file for the bacon tool
|
|
||||||
#
|
|
||||||
# Bacon repository: https://github.com/Canop/bacon
|
|
||||||
# Complete help on configuration: https://dystroy.org/bacon/config/
|
|
||||||
# You can also check bacon's own bacon.toml file
|
|
||||||
# as an example: https://github.com/Canop/bacon/blob/main/bacon.toml
|
|
||||||
|
|
||||||
default_job = "check"
|
|
||||||
|
|
||||||
[jobs.check]
|
|
||||||
command = ["cargo", "check", "--color", "always"]
|
|
||||||
need_stdout = false
|
|
||||||
|
|
||||||
[jobs.check-all]
|
|
||||||
command = ["cargo", "check", "--all-targets", "--color", "always"]
|
|
||||||
need_stdout = false
|
|
||||||
|
|
||||||
[jobs.clippy]
|
|
||||||
command = [
|
|
||||||
"cargo", "clippy",
|
|
||||||
"--all-targets",
|
|
||||||
"--color", "always",
|
|
||||||
]
|
|
||||||
need_stdout = false
|
|
||||||
|
|
||||||
[jobs.clippy-unwrap]
|
|
||||||
command = [
|
|
||||||
"cargo", "clippy",
|
|
||||||
"--lib",
|
|
||||||
"--color", "always",
|
|
||||||
"--",
|
|
||||||
"-W",
|
|
||||||
"clippy::unwrap_used",
|
|
||||||
"-W",
|
|
||||||
"clippy::expect_used",
|
|
||||||
]
|
|
||||||
need_stdout = false
|
|
||||||
|
|
||||||
# This job lets you run
|
|
||||||
# - all tests: bacon test
|
|
||||||
# - a specific test: bacon test -- config::test_default_files
|
|
||||||
# - the tests of a package: bacon test -- -- -p config
|
|
||||||
[jobs.test]
|
|
||||||
command = [
|
|
||||||
"cargo", "test", "--color", "always",
|
|
||||||
"--", "--color", "always", # see https://github.com/Canop/bacon/issues/124
|
|
||||||
]
|
|
||||||
need_stdout = true
|
|
||||||
|
|
||||||
[jobs.doc]
|
|
||||||
command = ["cargo", "doc", "--color", "always", "--no-deps"]
|
|
||||||
need_stdout = false
|
|
||||||
|
|
||||||
# If the doc compiles, then it opens in your browser and bacon switches
|
|
||||||
# to the previous job
|
|
||||||
[jobs.doc-open]
|
|
||||||
command = ["cargo", "doc", "--color", "always", "--no-deps", "--open"]
|
|
||||||
need_stdout = false
|
|
||||||
on_success = "back" # so that we don't open the browser at each change
|
|
||||||
|
|
||||||
# You can run your application and have the result displayed in bacon,
|
|
||||||
# *if* it makes sense for this crate.
|
|
||||||
# Don't forget the `--color always` part or the errors won't be
|
|
||||||
# properly parsed.
|
|
||||||
# If your program never stops (eg a server), you may set `background`
|
|
||||||
# to false to have the cargo run output immediately displayed instead
|
|
||||||
# of waiting for program's end.
|
|
||||||
[jobs.run]
|
|
||||||
command = [
|
|
||||||
"cargo", "run",
|
|
||||||
"--color", "always",
|
|
||||||
# put launch parameters for your program behind a `--` separator
|
|
||||||
]
|
|
||||||
need_stdout = true
|
|
||||||
allow_warnings = true
|
|
||||||
background = true
|
|
||||||
|
|
||||||
# This parameterized job runs the example of your choice, as soon
|
|
||||||
# as the code compiles.
|
|
||||||
# Call it as
|
|
||||||
# bacon ex -- my-example
|
|
||||||
[jobs.ex]
|
|
||||||
command = ["cargo", "run", "--color", "always", "--example"]
|
|
||||||
need_stdout = true
|
|
||||||
allow_warnings = true
|
|
||||||
|
|
||||||
# You may define here keybindings that would be specific to
|
|
||||||
# a project, for example a shortcut to launch a specific job.
|
|
||||||
# Shortcuts to internal functions (scrolling, toggling, etc.)
|
|
||||||
# should go in your personal global prefs.toml file instead.
|
|
||||||
[keybindings]
|
|
||||||
# alt-m = "job:my-job"
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "keyforkd-client"
|
name = "keyforkd-client"
|
||||||
version = "0.2.1"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
@ -12,14 +12,14 @@ ed25519 = ["keyfork-derive-util/ed25519", "ed25519-dalek"]
|
||||||
secp256k1 = ["keyfork-derive-util/secp256k1", "k256"]
|
secp256k1 = ["keyfork-derive-util/secp256k1", "k256"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-derive-util = { workspace = true, default-features = false }
|
keyfork-derive-util = { version = "0.2.0", path = "../../derive/keyfork-derive-util", default-features = false, registry = "distrust" }
|
||||||
keyfork-frame = { workspace = true }
|
keyfork-frame = { version = "0.1.0", path = "../../util/keyfork-frame", registry = "distrust" }
|
||||||
keyforkd-models = { workspace = true }
|
keyforkd-models = { version = "0.2.0", path = "../keyforkd-models", registry = "distrust" }
|
||||||
bincode = { workspace = true }
|
bincode = "1.3.3"
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.49"
|
||||||
k256 = { workspace = true, default-features = false, features = ["std"], optional = true }
|
k256 = { version = "0.13.3", optional = true }
|
||||||
ed25519-dalek = { workspace = true, optional = true }
|
ed25519-dalek = { version = "2.1.1", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
keyfork-slip10-test-data = { workspace = true }
|
keyfork-slip10-test-data = { path = "../../util/keyfork-slip10-test-data", registry = "distrust" }
|
||||||
keyforkd = { workspace = true }
|
keyforkd = { path = "../keyforkd", registry = "distrust" }
|
||||||
|
|
|
@ -11,7 +11,7 @@ fn secp256k1_test_suite() {
|
||||||
|
|
||||||
let tests = test_data()
|
let tests = test_data()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.remove("secp256k1")
|
.remove(&"secp256k1".to_string())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for seed_test in tests {
|
for seed_test in tests {
|
||||||
|
@ -70,7 +70,7 @@ fn secp256k1_test_suite() {
|
||||||
fn ed25519_test_suite() {
|
fn ed25519_test_suite() {
|
||||||
use ed25519_dalek::SigningKey;
|
use ed25519_dalek::SigningKey;
|
||||||
|
|
||||||
let tests = test_data().unwrap().remove("ed25519").unwrap();
|
let tests = test_data().unwrap().remove(&"ed25519".to_string()).unwrap();
|
||||||
|
|
||||||
for seed_test in tests {
|
for seed_test in tests {
|
||||||
let seed = seed_test.seed;
|
let seed = seed_test.seed;
|
||||||
|
|
|
@ -7,6 +7,6 @@ license = "MIT"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-derive-util = { workspace = true, default-features = false }
|
keyfork-derive-util = { version = "0.2.0", path = "../../derive/keyfork-derive-util", default-features = false, registry = "distrust" }
|
||||||
serde = { workspace = true }
|
serde = { version = "1.0.190", features = ["derive"] }
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.50"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "keyforkd"
|
name = "keyforkd"
|
||||||
version = "0.1.2"
|
version = "0.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
|
|
||||||
|
@ -12,28 +12,28 @@ tracing = ["tower/tracing", "tokio/tracing", "dep:tracing", "dep:tracing-subscri
|
||||||
multithread = ["tokio/rt-multi-thread"]
|
multithread = ["tokio/rt-multi-thread"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-bug = { workspace = true }
|
keyfork-bug = { version = "0.1.0", path = "../../util/keyfork-bug", registry = "distrust" }
|
||||||
keyfork-derive-util = { workspace = true }
|
keyfork-derive-util = { version = "0.2.0", path = "../../derive/keyfork-derive-util", registry = "distrust" }
|
||||||
keyfork-frame = { workspace = true, features = ["async"] }
|
keyfork-frame = { version = "0.1.0", path = "../../util/keyfork-frame", features = ["async"], registry = "distrust" }
|
||||||
keyfork-mnemonic = { workspace = true }
|
keyfork-mnemonic = { version = "0.3.0", path = "../../util/keyfork-mnemonic", registry = "distrust" }
|
||||||
keyfork-derive-path-data = { workspace = true }
|
keyfork-derive-path-data = { version = "0.1.0", path = "../../derive/keyfork-derive-path-data", registry = "distrust" }
|
||||||
keyforkd-models = { workspace = true }
|
keyforkd-models = { version = "0.2.0", path = "../keyforkd-models", registry = "distrust" }
|
||||||
|
|
||||||
# Not personally audited
|
# Not personally audited
|
||||||
bincode = { workspace = true }
|
bincode = "1.3.3"
|
||||||
|
|
||||||
# Ecosystem trust, not personally audited
|
# Ecosystem trust, not personally audited
|
||||||
tokio = { workspace = true, features = ["io-util", "macros", "rt", "io-std", "net", "fs", "signal"] }
|
tokio = { version = "1.32.0", features = ["io-util", "macros", "rt", "io-std", "net", "fs", "signal"] }
|
||||||
tracing = { version = "0.1.37", optional = true }
|
tracing = { version = "0.1.37", optional = true }
|
||||||
tracing-error = { version = "0.2.0", optional = true }
|
tracing-error = { version = "0.2.0", optional = true }
|
||||||
tracing-subscriber = { version = "0.3.17", optional = true, features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.17", optional = true, features = ["env-filter"] }
|
||||||
tower = { version = "0.4.13", features = ["tokio", "util"] }
|
tower = { version = "0.4.13", features = ["tokio", "util"] }
|
||||||
|
|
||||||
# Personally audited
|
# Personally audited
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.47"
|
||||||
serde = { workspace = true }
|
serde = { version = "1.0.186", features = ["derive"] }
|
||||||
tempfile = { version = "3.10.0", default-features = false }
|
tempfile = { version = "3.10.0", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex-literal = { workspace = true }
|
hex-literal = "0.4.1"
|
||||||
keyfork-slip10-test-data = { workspace = true }
|
keyfork-slip10-test-data = { path = "../../util/keyfork-slip10-test-data", registry = "distrust" }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Launch the Keyfork Server from using a mnemonic passed through standard input.
|
//!
|
||||||
|
|
||||||
use keyfork_mnemonic::Mnemonic;
|
use keyfork_mnemonic::Mnemonic;
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ mod tests {
|
||||||
async fn properly_derives_secp256k1() {
|
async fn properly_derives_secp256k1() {
|
||||||
let tests = test_data()
|
let tests = test_data()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.remove("secp256k1")
|
.remove(&"secp256k1".to_string())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for per_seed in tests {
|
for per_seed in tests {
|
||||||
|
@ -146,7 +146,7 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn properly_derives_ed25519() {
|
async fn properly_derives_ed25519() {
|
||||||
let tests = test_data().unwrap().remove("ed25519").unwrap();
|
let tests = test_data().unwrap().remove(&"ed25519".to_string()).unwrap();
|
||||||
|
|
||||||
for per_seed in tests {
|
for per_seed in tests {
|
||||||
let seed = &per_seed.seed;
|
let seed = &per_seed.seed;
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "keyfork-derive-age"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
license = "AGPL-3.0-only"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
keyfork-derive-util = { workspace = true, default-features = false, features = ["ed25519"] }
|
|
||||||
keyforkd-client = { workspace = true }
|
|
||||||
smex = { workspace = true }
|
|
||||||
thiserror = "1.0.48"
|
|
||||||
bech32 = "0.11.0"
|
|
||||||
keyfork-derive-path-data = { workspace = true }
|
|
||||||
ed25519-dalek = "2.1.1"
|
|
|
@ -1,69 +0,0 @@
|
||||||
use std::{env, process::ExitCode, str::FromStr};
|
|
||||||
|
|
||||||
use keyfork_derive_path_data::paths;
|
|
||||||
use keyfork_derive_util::{DerivationPath, ExtendedPrivateKey, PathError};
|
|
||||||
use keyforkd_client::Client;
|
|
||||||
|
|
||||||
use ed25519_dalek::SigningKey;
|
|
||||||
|
|
||||||
type XPrv = ExtendedPrivateKey<SigningKey>;
|
|
||||||
|
|
||||||
/// Any error that can occur while deriving a key.
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
pub enum Error {
|
|
||||||
/// The given path could not be parsed.
|
|
||||||
#[error("Could not parse the given path: {0}")]
|
|
||||||
PathFormat(#[from] PathError),
|
|
||||||
|
|
||||||
/// The request to derive data failed.
|
|
||||||
#[error("Unable to perform key derivation request: {0}")]
|
|
||||||
KeyforkdClient(#[from] keyforkd_client::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
|
||||||
|
|
||||||
fn validate(path: &str) -> Result<DerivationPath> {
|
|
||||||
let index = paths::AGE.inner().first().unwrap();
|
|
||||||
|
|
||||||
let path = DerivationPath::from_str(path)?;
|
|
||||||
assert!(
|
|
||||||
path.len() >= 2,
|
|
||||||
"Expected path of at least m/{index}/account_id'"
|
|
||||||
);
|
|
||||||
|
|
||||||
let given_index = path.iter().next().expect("checked .len() above");
|
|
||||||
assert_eq!(
|
|
||||||
index, given_index,
|
|
||||||
"Expected derivation path starting with m/{index}, got: {given_index}",
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
let mut args = env::args();
|
|
||||||
let program_name = args.next().expect("program name");
|
|
||||||
let args = args.collect::<Vec<_>>();
|
|
||||||
let path = match args.as_slice() {
|
|
||||||
[path] => validate(path)?,
|
|
||||||
_ => panic!("Usage: {program_name} path"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut client = Client::discover_socket()?;
|
|
||||||
// TODO: should this key be clamped to Curve25519 specs?
|
|
||||||
let xprv: XPrv = client.request_xprv(&path)?;
|
|
||||||
let hrp = bech32::Hrp::parse("AGE-SECRET-KEY-")?;
|
|
||||||
let age_key = bech32::encode::<bech32::Bech32>(hrp, &xprv.private_key().to_bytes())?;
|
|
||||||
println!("{}", age_key.to_uppercase());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> ExitCode {
|
|
||||||
if let Err(e) = run() {
|
|
||||||
eprintln!("Error: {e}");
|
|
||||||
ExitCode::FAILURE
|
|
||||||
} else {
|
|
||||||
ExitCode::SUCCESS
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,7 +7,7 @@ license = "AGPL-3.0-only"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-derive-util = { workspace = true }
|
keyfork-derive-util = { version = "0.2.0", path = "../keyfork-derive-util", registry = "distrust" }
|
||||||
keyforkd-client = { workspace = true }
|
keyforkd-client = { version = "0.2.0", path = "../../daemon/keyforkd-client", registry = "distrust" }
|
||||||
smex = { workspace = true }
|
smex = { version = "0.1.0", path = "../../util/smex", registry = "distrust" }
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.48"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Query the Keyfork Server to generate a hex-encoded key for a given algorithm.
|
//!
|
||||||
|
|
||||||
use std::{env, process::ExitCode, str::FromStr};
|
use std::{env, process::ExitCode, str::FromStr};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "keyfork-derive-openpgp"
|
name = "keyfork-derive-openpgp"
|
||||||
version = "0.1.3"
|
version = "0.1.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
|
|
||||||
|
@ -10,10 +10,10 @@ default = ["bin"]
|
||||||
bin = ["sequoia-openpgp/crypto-nettle"]
|
bin = ["sequoia-openpgp/crypto-nettle"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-derive-util = { workspace = true, default-features = false, features = ["ed25519"] }
|
keyfork-derive-util = { version = "0.2.0", path = "../keyfork-derive-util", default-features = false, features = ["ed25519"], registry = "distrust" }
|
||||||
keyforkd-client = { workspace = true, default-features = false, features = ["ed25519"] }
|
keyforkd-client = { version = "0.2.0", path = "../../daemon/keyforkd-client", default-features = false, features = ["ed25519"], registry = "distrust" }
|
||||||
ed25519-dalek = { workspace = true }
|
ed25519-dalek = "2.0.0"
|
||||||
sequoia-openpgp = { workspace = true }
|
sequoia-openpgp = { version = "1.17.0", default-features = false }
|
||||||
anyhow = { workspace = true }
|
anyhow = "1.0.75"
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.49"
|
||||||
keyfork-derive-path-data = { workspace = true }
|
keyfork-derive-path-data = { version = "0.1.1", path = "../keyfork-derive-path-data" }
|
||||||
|
|
|
@ -19,14 +19,8 @@ use sequoia_openpgp::{
|
||||||
Cert, Packet,
|
Cert, Packet,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: this key type is actually _not_ the extended private key, so it should be renamed
|
|
||||||
// something like Prv or PrvKey.
|
|
||||||
|
|
||||||
/// The private key type used with OpenPGP.
|
|
||||||
pub type XPrvKey = SigningKey;
|
pub type XPrvKey = SigningKey;
|
||||||
|
pub type XPrv = ExtendedPrivateKey<SigningKey>;
|
||||||
/// The extended private key type used with OpenPGP.
|
|
||||||
pub type XPrv = ExtendedPrivateKey<XPrvKey>;
|
|
||||||
|
|
||||||
/// An error occurred while creating an OpenPGP key.
|
/// An error occurred while creating an OpenPGP key.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! Query the Keyfork Servre to derive an OpenPGP Secret Key.
|
//!
|
||||||
|
|
||||||
use std::{env, process::ExitCode, str::FromStr};
|
use std::{env, process::ExitCode, str::FromStr};
|
||||||
|
|
||||||
use keyfork_derive_util::DerivationPath;
|
use keyfork_derive_util::{DerivationIndex, DerivationPath};
|
||||||
use keyfork_derive_path_data::paths;
|
use keyfork_derive_path_data::paths;
|
||||||
use keyforkd_client::Client;
|
use keyforkd_client::Client;
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
let mut w = Writer::new(std::io::stdout(), Kind::SecretKey)?;
|
let mut w = Writer::new(std::io::stdout(), Kind::SecretKey)?;
|
||||||
|
|
||||||
for packet in cert.into_packets2() {
|
for packet in cert.into_packets() {
|
||||||
packet.serialize(&mut w)?;
|
packet.serialize(&mut w)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
[package]
|
[package]
|
||||||
name = "keyfork-derive-path-data"
|
name = "keyfork-derive-path-data"
|
||||||
version = "0.1.2"
|
version = "0.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-derive-util = { workspace = true, default-features = false }
|
keyfork-derive-util = { version = "0.2.0", path = "../keyfork-derive-util", default-features = false, registry = "distrust" }
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
|
|
|
@ -6,7 +6,6 @@ use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use keyfork_derive_util::{DerivationIndex, DerivationPath};
|
use keyfork_derive_util::{DerivationIndex, DerivationPath};
|
||||||
|
|
||||||
/// All common paths for key derivation.
|
|
||||||
pub mod paths {
|
pub mod paths {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "keyfork-derive-util"
|
name = "keyfork-derive-util"
|
||||||
version = "0.2.1"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
@ -12,25 +12,25 @@ secp256k1 = ["k256"]
|
||||||
ed25519 = ["ed25519-dalek"]
|
ed25519 = ["ed25519-dalek"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-mnemonic = { workspace = true }
|
keyfork-mnemonic = { version = "0.3.0", path = "../../util/keyfork-mnemonic", registry = "distrust" }
|
||||||
keyfork-bug = { workspace = true }
|
keyfork-bug = { version = "0.1.0", path = "../../util/keyfork-bug", registry = "distrust" }
|
||||||
|
|
||||||
# Included in Rust
|
# Included in Rust
|
||||||
digest = "0.10.7"
|
digest = "0.10.7"
|
||||||
sha2 = { workspace = true }
|
sha2 = "0.10.7"
|
||||||
|
|
||||||
# Rust-Crypto ecosystem, not personally audited
|
# Rust-Crypto ecosystem, not personally audited
|
||||||
ripemd = "0.1.3"
|
ripemd = "0.1.3"
|
||||||
hmac = { workspace = true, features = ["std"] }
|
hmac = { version = "0.12.1", features = ["std"] }
|
||||||
|
|
||||||
# Personally audited
|
# Personally audited
|
||||||
serde = { workspace = true }
|
serde = { version = "1.0.186", features = ["derive"] }
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.47"
|
||||||
|
|
||||||
# Optional, not personally audited
|
# Optional, not personally audited
|
||||||
k256 = { workspace = true, default-features = false, features = ["std", "arithmetic"], optional = true }
|
k256 = { version = "0.13.1", default-features = false, features = ["std", "arithmetic"], optional = true }
|
||||||
ed25519-dalek = { workspace = true, optional = true }
|
ed25519-dalek = { version = "2.0.0", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex-literal = { workspace = true }
|
hex-literal = "0.4.1"
|
||||||
keyfork-slip10-test-data = { workspace = true }
|
keyfork-slip10-test-data = { version = "0.1.0", path = "../../util/keyfork-slip10-test-data", registry = "distrust" }
|
||||||
|
|
|
@ -41,9 +41,9 @@
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
///
|
||||||
pub mod private_key;
|
pub mod private_key;
|
||||||
#[allow(missing_docs)]
|
///
|
||||||
pub mod public_key;
|
pub mod public_key;
|
||||||
|
|
||||||
pub use {private_key::ExtendedPrivateKey, public_key::ExtendedPublicKey};
|
pub use {private_key::ExtendedPrivateKey, public_key::ExtendedPublicKey};
|
||||||
|
|
|
@ -15,7 +15,7 @@ fn secp256k1() {
|
||||||
|
|
||||||
let tests = test_data()
|
let tests = test_data()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.remove("secp256k1")
|
.remove(&"secp256k1".to_string())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for per_seed in tests {
|
for per_seed in tests {
|
||||||
|
@ -62,7 +62,7 @@ fn secp256k1() {
|
||||||
fn ed25519() {
|
fn ed25519() {
|
||||||
use ed25519_dalek::SigningKey;
|
use ed25519_dalek::SigningKey;
|
||||||
|
|
||||||
let tests = test_data().unwrap().remove("ed25519").unwrap();
|
let tests = test_data().unwrap().remove(&"ed25519".to_string()).unwrap();
|
||||||
|
|
||||||
for per_seed in tests {
|
for per_seed in tests {
|
||||||
let seed = &per_seed.seed;
|
let seed = &per_seed.seed;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "keyfork-shard"
|
name = "keyfork-shard"
|
||||||
version = "0.2.3"
|
version = "0.2.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
|
|
||||||
|
@ -14,27 +14,27 @@ openpgp-card = ["openpgp-card-sequoia", "card-backend-pcsc", "card-backend", "de
|
||||||
qrcode = ["keyfork-qrcode"]
|
qrcode = ["keyfork-qrcode"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-bug = { workspace = true }
|
keyfork-bug = { version = "0.1.0", path = "../util/keyfork-bug", registry = "distrust" }
|
||||||
keyfork-prompt = { workspace = true, default-features = false, features = ["mnemonic"] }
|
keyfork-prompt = { version = "0.1.1", path = "../util/keyfork-prompt", default-features = false, features = ["mnemonic"], registry = "distrust" }
|
||||||
keyfork-qrcode = { workspace = true, optional = true, default-features = false }
|
keyfork-qrcode = { version = "0.1.1", path = "../qrcode/keyfork-qrcode", optional = true, default-features = false, registry = "distrust" }
|
||||||
smex = { workspace = true }
|
smex = { version = "0.1.0", path = "../util/smex", registry = "distrust" }
|
||||||
|
|
||||||
sharks = "0.5.0"
|
sharks = "0.5.0"
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.50"
|
||||||
|
|
||||||
# Remote operator mode
|
# Remote operator mode
|
||||||
keyfork-mnemonic = { workspace = true }
|
keyfork-mnemonic = { version = "0.3.0", path = "../util/keyfork-mnemonic", registry = "distrust" }
|
||||||
x25519-dalek = { version = "2.0.0", features = ["getrandom"] }
|
x25519-dalek = { version = "2.0.0", features = ["getrandom"] }
|
||||||
aes-gcm = { version = "0.10.3", features = ["std"] }
|
aes-gcm = { version = "0.10.3", features = ["std"] }
|
||||||
hkdf = { version = "0.12.4", features = ["std"] }
|
hkdf = { version = "0.12.4", features = ["std"] }
|
||||||
sha2 = { workspace = true }
|
sha2 = "0.10.8"
|
||||||
|
|
||||||
# OpenPGP
|
# OpenPGP
|
||||||
keyfork-derive-openpgp = { workspace = true, default-features = false }
|
keyfork-derive-openpgp = { version = "0.1.0", path = "../derive/keyfork-derive-openpgp", default-features = false, registry = "distrust" }
|
||||||
anyhow = { workspace = true, optional = true }
|
anyhow = { version = "1.0.79", optional = true }
|
||||||
card-backend = { version = "0.2.0", optional = true }
|
card-backend = { version = "0.2.0", optional = true }
|
||||||
card-backend-pcsc = { workspace = true, optional = true }
|
card-backend-pcsc = { version = "0.5.0", optional = true }
|
||||||
openpgp-card-sequoia = { workspace = true, optional = true }
|
openpgp-card-sequoia = { version = "0.2.0", optional = true, default-features = false }
|
||||||
openpgp-card = { workspace = true, optional = true }
|
openpgp-card = { version = "0.4.0", optional = true }
|
||||||
sequoia-openpgp = { workspace = true, optional = true }
|
sequoia-openpgp = { version = "1.17.0", optional = true, default-features = false }
|
||||||
base64 = "0.22.0"
|
base64 = "0.22.0"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Combine OpenPGP shards and output the hex-encoded secret.
|
//!
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Decrypt a single OpenPGP shard and encapsulate it for remote transport.
|
//!
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Combine OpenPGP shards using remote transport and output the hex-encoded secret.
|
//!
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Split a hex-encoded secret into OpenPGP shards
|
//!
|
||||||
|
|
||||||
use std::{env, path::PathBuf, process::ExitCode, str::FromStr};
|
use std::{env, path::PathBuf, process::ExitCode, str::FromStr};
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ use openpgp::{
|
||||||
stream::{DecryptionHelper, DecryptorBuilder, VerificationHelper},
|
stream::{DecryptionHelper, DecryptorBuilder, VerificationHelper},
|
||||||
Parse,
|
Parse,
|
||||||
},
|
},
|
||||||
policy::{NullPolicy, StandardPolicy, Policy},
|
policy::{NullPolicy, Policy, StandardPolicy},
|
||||||
serialize::{
|
serialize::{
|
||||||
stream::{ArbitraryWriter, Encryptor2, LiteralWriter, Message, Recipient, Signer},
|
stream::{ArbitraryWriter, Encryptor2, LiteralWriter, Message, Recipient, Signer},
|
||||||
Marshal,
|
Marshal,
|
||||||
|
@ -77,10 +77,6 @@ pub enum Error {
|
||||||
/// An IO error occurred.
|
/// An IO error occurred.
|
||||||
#[error("IO error: {0}")]
|
#[error("IO error: {0}")]
|
||||||
Io(#[source] std::io::Error),
|
Io(#[source] std::io::Error),
|
||||||
|
|
||||||
/// No valid keys were found for the given recipient.
|
|
||||||
#[error("No valid keys were found for the recipient {0}")]
|
|
||||||
NoValidKeys(KeyID),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
@ -185,7 +181,7 @@ impl EncryptedMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encoding and decoding shards using OpenPGP.
|
///
|
||||||
pub struct OpenPGP<P: PromptHandler> {
|
pub struct OpenPGP<P: PromptHandler> {
|
||||||
p: PhantomData<P>,
|
p: PhantomData<P>,
|
||||||
}
|
}
|
||||||
|
@ -243,13 +239,6 @@ impl<P: PromptHandler> OpenPGP<P> {
|
||||||
certs.insert(certfp, cert);
|
certs.insert(certfp, cert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for cert in certs.values() {
|
|
||||||
let policy = StandardPolicy::new();
|
|
||||||
let valid_cert = cert.with_policy(&policy, None).map_err(Error::Sequoia)?;
|
|
||||||
if get_encryption_keys(&valid_cert).next().is_none() {
|
|
||||||
return Err(Error::NoValidKeys(valid_cert.keyid()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(certs.into_values().collect())
|
Ok(certs.into_values().collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -588,8 +577,7 @@ fn get_encryption_keys<'a>(
|
||||||
openpgp::packet::key::UnspecifiedRole,
|
openpgp::packet::key::UnspecifiedRole,
|
||||||
> {
|
> {
|
||||||
cert.keys()
|
cert.keys()
|
||||||
// NOTE: this causes complications on Airgap systems
|
.alive()
|
||||||
// .alive()
|
|
||||||
.revoked(false)
|
.revoked(false)
|
||||||
.supported()
|
.supported()
|
||||||
.for_storage_encryption()
|
.for_storage_encryption()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "keyfork"
|
name = "keyfork"
|
||||||
version = "0.2.4"
|
version = "0.2.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
|
|
||||||
|
@ -23,25 +23,25 @@ sequoia-crypto-backend-openssl = ["sequoia-openpgp/crypto-openssl"]
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-bin = { workspace = true }
|
keyfork-bin = { version = "0.1.0", path = "../util/keyfork-bin", registry = "distrust" }
|
||||||
keyforkd = { workspace = true, features = ["tracing"] }
|
keyforkd = { version = "0.1.0", path = "../daemon/keyforkd", features = ["tracing"], registry = "distrust" }
|
||||||
keyforkd-client = { workspace = true, default-features = false, features = ["ed25519"] }
|
keyforkd-client = { version = "0.2.0", path = "../daemon/keyforkd-client", default-features = false, features = ["ed25519"], registry = "distrust" }
|
||||||
keyfork-derive-util = { workspace = true, default-features = true }
|
keyfork-derive-openpgp = { version = "0.1.1", path = "../derive/keyfork-derive-openpgp", registry = "distrust" }
|
||||||
keyfork-derive-openpgp = { workspace = true }
|
keyfork-derive-util = { version = "0.2.0", path = "../derive/keyfork-derive-util", default-features = false, features = ["ed25519"], registry = "distrust" }
|
||||||
keyfork-derive-path-data = { workspace = true }
|
keyfork-entropy = { version = "0.1.0", path = "../util/keyfork-entropy", registry = "distrust" }
|
||||||
keyfork-entropy = { workspace = true }
|
keyfork-mnemonic = { version = "0.3.0", path = "../util/keyfork-mnemonic", registry = "distrust" }
|
||||||
keyfork-mnemonic = { workspace = true }
|
keyfork-prompt = { version = "0.1.0", path = "../util/keyfork-prompt", registry = "distrust" }
|
||||||
keyfork-prompt = { workspace = true }
|
keyfork-qrcode = { version = "0.1.0", path = "../qrcode/keyfork-qrcode", default-features = false, registry = "distrust" }
|
||||||
keyfork-qrcode = { workspace = true, default-features = false }
|
keyfork-shard = { version = "0.2.0", path = "../keyfork-shard", default-features = false, features = ["openpgp", "openpgp-card", "qrcode"], registry = "distrust" }
|
||||||
keyfork-shard = { workspace = true, default-features = false, features = ["openpgp", "openpgp-card", "qrcode"] }
|
smex = { version = "0.1.0", path = "../util/smex", registry = "distrust" }
|
||||||
smex = { workspace = true }
|
|
||||||
|
|
||||||
clap = { version = "4.4.2", features = ["derive", "env", "wrap_help"] }
|
clap = { version = "4.4.2", features = ["derive", "env", "wrap_help"] }
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.48"
|
||||||
serde = { workspace = true }
|
serde = { version = "1.0.192", features = ["derive"] }
|
||||||
tokio = { workspace = true, features = ["rt-multi-thread"] }
|
tokio = { version = "1.35.1", default-features = false, features = ["rt-multi-thread"] }
|
||||||
card-backend-pcsc = { workspace = true }
|
card-backend-pcsc = "0.5.0"
|
||||||
openpgp-card-sequoia = { workspace = true }
|
openpgp-card-sequoia = { version = "0.2.0", default-features = false }
|
||||||
openpgp-card = { workspace = true }
|
openpgp-card = "0.4.1"
|
||||||
clap_complete = { version = "4.4.6", optional = true }
|
clap_complete = { version = "4.4.6", optional = true }
|
||||||
sequoia-openpgp = { workspace = true }
|
sequoia-openpgp = { version = "1.17.0", default-features = false, features = ["compression"] }
|
||||||
|
keyfork-derive-path-data = { version = "0.1.1", path = "../derive/keyfork-derive-path-data" }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::Keyfork;
|
use super::Keyfork;
|
||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
|
||||||
use keyfork_derive_openpgp::{
|
use keyfork_derive_openpgp::{
|
||||||
openpgp::{
|
openpgp::{
|
||||||
|
@ -10,7 +10,7 @@ use keyfork_derive_openpgp::{
|
||||||
},
|
},
|
||||||
XPrvKey,
|
XPrvKey,
|
||||||
};
|
};
|
||||||
use keyfork_derive_util::DerivationIndex;
|
use keyfork_derive_util::{DerivationIndex, DerivationPath};
|
||||||
use keyfork_derive_path_data::paths;
|
use keyfork_derive_path_data::paths;
|
||||||
use keyforkd_client::Client;
|
use keyforkd_client::Client;
|
||||||
|
|
||||||
|
@ -28,25 +28,16 @@ pub enum DeriveSubcommands {
|
||||||
/// It is recommended to use the default expiration of one day and to change the expiration
|
/// It is recommended to use the default expiration of one day and to change the expiration
|
||||||
/// using an external utility, to ensure the Certify key is usable.
|
/// using an external utility, to ensure the Certify key is usable.
|
||||||
#[command(name = "openpgp")]
|
#[command(name = "openpgp")]
|
||||||
OpenPGP(OpenPGP)
|
OpenPGP {
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Args, Clone, Debug)]
|
|
||||||
pub struct OpenPGP {
|
|
||||||
/// Default User ID for the certificate, using the OpenPGP User ID format.
|
/// Default User ID for the certificate, using the OpenPGP User ID format.
|
||||||
user_id: String,
|
user_id: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeriveSubcommands {
|
impl DeriveSubcommands {
|
||||||
fn handle(&self, account: DerivationIndex) -> Result<()> {
|
fn handle(&self, account: DerivationIndex) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
DeriveSubcommands::OpenPGP(opgp) => opgp.handle(account),
|
DeriveSubcommands::OpenPGP { user_id } => {
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OpenPGP {
|
|
||||||
pub fn handle(&self, account: DerivationIndex) -> Result<()> {
|
|
||||||
let path = paths::OPENPGP.clone().chain_push(account);
|
let path = paths::OPENPGP.clone().chain_push(account);
|
||||||
// TODO: should this be customizable?
|
// TODO: should this be customizable?
|
||||||
let subkeys = vec![
|
let subkeys = vec![
|
||||||
|
@ -58,16 +49,19 @@ impl OpenPGP {
|
||||||
KeyFlags::empty().set_authentication(),
|
KeyFlags::empty().set_authentication(),
|
||||||
];
|
];
|
||||||
let xprv = Client::discover_socket()?.request_xprv::<XPrvKey>(&path)?;
|
let xprv = Client::discover_socket()?.request_xprv::<XPrvKey>(&path)?;
|
||||||
let default_userid = UserID::from(self.user_id.as_str());
|
let default_userid = UserID::from(user_id.as_str());
|
||||||
let cert = keyfork_derive_openpgp::derive(xprv, &subkeys, &default_userid)?;
|
let cert = keyfork_derive_openpgp::derive(xprv, &subkeys, &default_userid)?;
|
||||||
|
|
||||||
let mut w = Writer::new(std::io::stdout(), Kind::SecretKey)?;
|
let mut w = Writer::new(std::io::stdout(), Kind::SecretKey)?;
|
||||||
|
|
||||||
for packet in cert.into_packets2() {
|
for packet in cert.into_packets() {
|
||||||
packet.serialize(&mut w)?;
|
packet.serialize(&mut w)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
w.finalize()?;
|
w.finalize()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
use super::Keyfork;
|
use super::Keyfork;
|
||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use std::{collections::HashSet, fs::File, io::IsTerminal, path::PathBuf};
|
use std::{
|
||||||
|
collections::HashSet,
|
||||||
|
fs::File,
|
||||||
|
io::IsTerminal,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
use card_backend_pcsc::PcscBackend;
|
use card_backend_pcsc::PcscBackend;
|
||||||
use openpgp_card_sequoia::{state::Open, types::KeyType, Card};
|
use openpgp_card_sequoia::{state::Open, types::KeyType, Card};
|
||||||
|
@ -17,7 +22,7 @@ use keyfork_derive_openpgp::{
|
||||||
XPrv,
|
XPrv,
|
||||||
};
|
};
|
||||||
use keyfork_derive_path_data::paths;
|
use keyfork_derive_path_data::paths;
|
||||||
use keyfork_derive_util::DerivationIndex;
|
use keyfork_derive_util::{DerivationIndex, DerivationPath};
|
||||||
use keyfork_mnemonic::Mnemonic;
|
use keyfork_mnemonic::Mnemonic;
|
||||||
use keyfork_prompt::{
|
use keyfork_prompt::{
|
||||||
default_terminal,
|
default_terminal,
|
||||||
|
@ -103,82 +108,18 @@ fn factory_reset_current_card(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Clone, Debug)]
|
fn generate_shard_secret(
|
||||||
pub enum WizardSubcommands {
|
|
||||||
GenerateShardSecret(GenerateShardSecret),
|
|
||||||
BottomsUp(BottomsUp),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a 256 bit secret and shard the secret to smart cards.
|
|
||||||
///
|
|
||||||
/// Smart cards will need to be plugged in periodically during the wizard, where they will be
|
|
||||||
/// factory reset and provisioned to `m/pgp'/shrd'/<share index>`. The secret can then be recovered
|
|
||||||
/// with `keyfork recover shard` or `keyfork recover remote-shard`. The share file will be printed
|
|
||||||
/// to standard output.
|
|
||||||
#[derive(Args, Clone, Debug)]
|
|
||||||
pub struct GenerateShardSecret {
|
|
||||||
/// The minimum amount of keys required to decrypt the secret.
|
|
||||||
#[arg(long)]
|
|
||||||
threshold: u8,
|
threshold: u8,
|
||||||
|
|
||||||
/// The maximum amount of shards.
|
|
||||||
#[arg(long)]
|
|
||||||
max: u8,
|
max: u8,
|
||||||
|
|
||||||
/// The amount of smart cards to provision per-shard.
|
|
||||||
#[arg(long, default_value = "1")]
|
|
||||||
keys_per_shard: u8,
|
keys_per_shard: u8,
|
||||||
|
output_file: &Option<PathBuf>,
|
||||||
/// The file to write the generated shard file to.
|
) -> Result<()> {
|
||||||
#[arg(long)]
|
|
||||||
output: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a 256 bit secret and shard the secret to previously known OpenPGP certificates,
|
|
||||||
/// deriving the default OpenPGP certificate for the secret.
|
|
||||||
///
|
|
||||||
/// This command was purpose-built for DEFCON and is not intended to be used normally, as it
|
|
||||||
/// implies keys used for sharding have been generated by a custom source.
|
|
||||||
#[derive(Args, Clone, Debug)]
|
|
||||||
pub struct BottomsUp {
|
|
||||||
/// The location of OpenPGP certificates to use when sharding.
|
|
||||||
key_discovery: PathBuf,
|
|
||||||
|
|
||||||
/// The minimum amount of keys required to decrypt the secret.
|
|
||||||
#[arg(long)]
|
|
||||||
threshold: u8,
|
|
||||||
|
|
||||||
/// The file to write the generated shard file to.
|
|
||||||
#[arg(long)]
|
|
||||||
output_shardfile: PathBuf,
|
|
||||||
|
|
||||||
/// The file to write the generated OpenPGP certificate to.
|
|
||||||
#[arg(long)]
|
|
||||||
output_cert: PathBuf,
|
|
||||||
|
|
||||||
/// The User ID for the generated OpenPGP certificate.
|
|
||||||
#[arg(long, default_value = "Disaster Recovery")]
|
|
||||||
user_id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WizardSubcommands {
|
|
||||||
// dispatch
|
|
||||||
fn handle(&self) -> Result<()> {
|
|
||||||
match self {
|
|
||||||
WizardSubcommands::GenerateShardSecret(gss) => gss.handle(),
|
|
||||||
WizardSubcommands::BottomsUp(bu) => bu.handle(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GenerateShardSecret {
|
|
||||||
fn handle(&self) -> Result<()> {
|
|
||||||
let seed = keyfork_entropy::generate_entropy_of_const_size::<{ 256 / 8 }>()?;
|
let seed = keyfork_entropy::generate_entropy_of_const_size::<{ 256 / 8 }>()?;
|
||||||
let mut pm = default_terminal()?;
|
let mut pm = default_terminal()?;
|
||||||
let mut certs = vec![];
|
let mut certs = vec![];
|
||||||
let mut seen_cards: HashSet<String> = HashSet::new();
|
let mut seen_cards: HashSet<String> = HashSet::new();
|
||||||
let stdout = std::io::stdout();
|
let stdout = std::io::stdout();
|
||||||
if self.output.is_none() {
|
if output_file.is_none() {
|
||||||
assert!(
|
assert!(
|
||||||
!stdout.is_terminal(),
|
!stdout.is_terminal(),
|
||||||
"not printing shard to terminal, redirect output"
|
"not printing shard to terminal, redirect output"
|
||||||
|
@ -196,9 +137,9 @@ impl GenerateShardSecret {
|
||||||
}
|
}
|
||||||
.to_fn();
|
.to_fn();
|
||||||
|
|
||||||
for index in 0..self.max {
|
for index in 0..max {
|
||||||
let cert = derive_key(seed, index)?;
|
let cert = derive_key(seed, index)?;
|
||||||
for i in 0..self.keys_per_shard {
|
for i in 0..keys_per_shard {
|
||||||
pm.prompt_message(Message::Text(format!(
|
pm.prompt_message(Message::Text(format!(
|
||||||
"Please remove all keys and insert key #{} for user #{}",
|
"Please remove all keys and insert key #{} for user #{}",
|
||||||
(i as u16) + 1,
|
(i as u16) + 1,
|
||||||
|
@ -236,12 +177,12 @@ impl GenerateShardSecret {
|
||||||
|
|
||||||
let opgp = OpenPGP::<DefaultTerminal>::new();
|
let opgp = OpenPGP::<DefaultTerminal>::new();
|
||||||
|
|
||||||
if let Some(output_file) = self.output.as_ref() {
|
if let Some(output_file) = output_file {
|
||||||
let output = File::create(output_file)?;
|
let output = File::create(output_file)?;
|
||||||
opgp.shard_and_encrypt(self.threshold, certs.len() as u8, &seed, &certs[..], output)?;
|
opgp.shard_and_encrypt(threshold, certs.len() as u8, &seed, &certs[..], output)?;
|
||||||
} else {
|
} else {
|
||||||
opgp.shard_and_encrypt(
|
opgp.shard_and_encrypt(
|
||||||
self.threshold,
|
threshold,
|
||||||
certs.len() as u8,
|
certs.len() as u8,
|
||||||
&seed,
|
&seed,
|
||||||
&certs[..],
|
&certs[..],
|
||||||
|
@ -249,11 +190,15 @@ impl GenerateShardSecret {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BottomsUp {
|
fn bottoms_up(
|
||||||
fn handle(&self) -> Result<()> {
|
key_discovery: &Path,
|
||||||
|
threshold: u8,
|
||||||
|
output_shardfile: &Path,
|
||||||
|
output_cert: &Path,
|
||||||
|
user_id: &str,
|
||||||
|
) -> Result<()> {
|
||||||
let entropy = keyfork_entropy::generate_entropy_of_const_size::<{ 256 / 8 }>()?;
|
let entropy = keyfork_entropy::generate_entropy_of_const_size::<{ 256 / 8 }>()?;
|
||||||
let mnemonic = Mnemonic::from_array(entropy);
|
let mnemonic = Mnemonic::from_array(entropy);
|
||||||
let seed = mnemonic.generate_seed(None);
|
let seed = mnemonic.generate_seed(None);
|
||||||
|
@ -274,26 +219,104 @@ impl BottomsUp {
|
||||||
let xprv = XPrv::new(seed)
|
let xprv = XPrv::new(seed)
|
||||||
.expect("could not construct master key from seed")
|
.expect("could not construct master key from seed")
|
||||||
.derive_path(&path)?;
|
.derive_path(&path)?;
|
||||||
let userid = UserID::from(self.user_id.as_str());
|
let userid = UserID::from(user_id);
|
||||||
|
|
||||||
let cert = keyfork_derive_openpgp::derive(xprv, &subkeys, &userid)?;
|
let cert = keyfork_derive_openpgp::derive(xprv, &subkeys, &userid)?;
|
||||||
let certfile = File::create(&self.output_cert)?;
|
let certfile = File::create(output_cert)?;
|
||||||
let mut w = Writer::new(certfile, Kind::PublicKey)?;
|
let mut w = Writer::new(certfile, Kind::PublicKey)?;
|
||||||
cert.serialize(&mut w)?;
|
cert.serialize(&mut w)?;
|
||||||
w.finalize()?;
|
w.finalize()?;
|
||||||
|
|
||||||
let opgp = OpenPGP::<DefaultTerminal>::new();
|
let opgp = OpenPGP::<DefaultTerminal>::new();
|
||||||
let certs = OpenPGP::<DefaultTerminal>::discover_certs(&self.key_discovery)?;
|
let certs = OpenPGP::<DefaultTerminal>::discover_certs(key_discovery)?;
|
||||||
|
|
||||||
let shardfile = File::create(&self.output_shardfile)?;
|
let shardfile = File::create(output_shardfile)?;
|
||||||
opgp.shard_and_encrypt(
|
opgp.shard_and_encrypt(
|
||||||
self.threshold,
|
threshold,
|
||||||
certs.len() as u8,
|
certs.len() as u8,
|
||||||
&entropy,
|
&entropy,
|
||||||
&certs[..],
|
&certs[..],
|
||||||
shardfile,
|
shardfile,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand, Clone, Debug)]
|
||||||
|
pub enum WizardSubcommands {
|
||||||
|
/// Create a 256 bit secret and shard the secret to smart cards.
|
||||||
|
///
|
||||||
|
/// Smart cards will need to be plugged in periodically during the wizard, where they will be factory reset and
|
||||||
|
/// provisioned to `m/pgp'/shrd'/<share index>`. The secret can then be recovered with `keyfork recover shard` or
|
||||||
|
/// `keyfork recover remote-shard`. The share file will be printed to standard output.
|
||||||
|
GenerateShardSecret {
|
||||||
|
/// The minimum amount of keys required to decrypt the secret.
|
||||||
|
#[arg(long)]
|
||||||
|
threshold: u8,
|
||||||
|
|
||||||
|
/// The maximum amount of shards.
|
||||||
|
#[arg(long)]
|
||||||
|
max: u8,
|
||||||
|
|
||||||
|
/// The amount of smart cards to provision per-shard.
|
||||||
|
#[arg(long, default_value = "1")]
|
||||||
|
keys_per_shard: u8,
|
||||||
|
|
||||||
|
/// The file to write the generated shard file to.
|
||||||
|
#[arg(long)]
|
||||||
|
output: Option<PathBuf>,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Create a 256 bit secret and shard the secret to previously known OpenPGP certificates,
|
||||||
|
/// deriving the default OpenPGP certificate for the secret.
|
||||||
|
///
|
||||||
|
/// This command was purpose-built for DEFCON and is not intended to be used normally, as it
|
||||||
|
/// implies keys used for sharding have been generated by a custom source.
|
||||||
|
BottomsUp {
|
||||||
|
/// The location of OpenPGP certificates to use when sharding.
|
||||||
|
key_discovery: PathBuf,
|
||||||
|
|
||||||
|
/// The minimum amount of keys required to decrypt the secret.
|
||||||
|
#[arg(long)]
|
||||||
|
threshold: u8,
|
||||||
|
|
||||||
|
/// The file to write the generated shard file to.
|
||||||
|
#[arg(long)]
|
||||||
|
output_shardfile: PathBuf,
|
||||||
|
|
||||||
|
/// The file to write the generated OpenPGP certificate to.
|
||||||
|
#[arg(long)]
|
||||||
|
output_cert: PathBuf,
|
||||||
|
|
||||||
|
/// The User ID for the generated OpenPGP certificate.
|
||||||
|
#[arg(long, default_value = "Disaster Recovery")]
|
||||||
|
user_id: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WizardSubcommands {
|
||||||
|
fn handle(&self) -> Result<()> {
|
||||||
|
match self {
|
||||||
|
WizardSubcommands::GenerateShardSecret {
|
||||||
|
threshold,
|
||||||
|
max,
|
||||||
|
keys_per_shard,
|
||||||
|
output,
|
||||||
|
} => generate_shard_secret(*threshold, *max, *keys_per_shard, output),
|
||||||
|
WizardSubcommands::BottomsUp {
|
||||||
|
key_discovery,
|
||||||
|
threshold,
|
||||||
|
output_shardfile,
|
||||||
|
output_cert,
|
||||||
|
user_id,
|
||||||
|
} => bottoms_up(
|
||||||
|
key_discovery,
|
||||||
|
*threshold,
|
||||||
|
output_shardfile,
|
||||||
|
output_cert,
|
||||||
|
user_id,
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,9 @@ decode-backend-rqrr = ["dep:rqrr"]
|
||||||
decode-backend-zbar = ["dep:keyfork-zbar"]
|
decode-backend-zbar = ["dep:keyfork-zbar"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-bug = { workspace = true }
|
keyfork-bug = { version = "0.1.0", path = "../../util/keyfork-bug", registry = "distrust" }
|
||||||
keyfork-zbar = { workspace = true, optional = true }
|
keyfork-zbar = { version = "0.1.0", path = "../keyfork-zbar", optional = true, registry = "distrust" }
|
||||||
image = { workspace = true, default-features = false, features = ["jpeg"] }
|
image = { version = "0.24.7", default-features = false, features = ["jpeg"] }
|
||||||
rqrr = { version = "0.7.0", optional = true }
|
rqrr = { version = "0.6.0", optional = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.56"
|
||||||
v4l = { workspace = true }
|
v4l = "0.14.0"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![allow(missing_docs)]
|
//!
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use keyfork_bug as bug;
|
use keyfork_bug as bug;
|
||||||
|
|
||||||
use image::ImageReader;
|
use image::io::Reader as ImageReader;
|
||||||
use std::{
|
use std::{
|
||||||
io::{Cursor, Write},
|
io::{Cursor, Write},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
|
@ -103,11 +103,6 @@ pub fn qrencode(
|
||||||
const VIDEO_FORMAT_READ_ERROR: &str = "Failed to read video device format";
|
const VIDEO_FORMAT_READ_ERROR: &str = "Failed to read video device format";
|
||||||
|
|
||||||
/// Continuously scan the `index`-th camera for a QR code.
|
/// Continuously scan the `index`-th camera for a QR code.
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// The function may return an error if the hardware is unable to scan video or if an image could
|
|
||||||
/// not be decoded.
|
|
||||||
#[cfg(feature = "decode-backend-rqrr")]
|
#[cfg(feature = "decode-backend-rqrr")]
|
||||||
pub fn scan_camera(timeout: Duration, index: usize) -> Result<Option<String>, QRCodeScanError> {
|
pub fn scan_camera(timeout: Duration, index: usize) -> Result<Option<String>, QRCodeScanError> {
|
||||||
let device = Device::new(index)?;
|
let device = Device::new(index)?;
|
||||||
|
@ -138,11 +133,6 @@ pub fn scan_camera(timeout: Duration, index: usize) -> Result<Option<String>, QR
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Continuously scan the `index`-th camera for a QR code.
|
/// Continuously scan the `index`-th camera for a QR code.
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// The function may return an error if the hardware is unable to scan video or if an image could
|
|
||||||
/// not be decoded.
|
|
||||||
#[cfg(feature = "decode-backend-zbar")]
|
#[cfg(feature = "decode-backend-zbar")]
|
||||||
pub fn scan_camera(timeout: Duration, index: usize) -> Result<Option<String>, QRCodeScanError> {
|
pub fn scan_camera(timeout: Duration, index: usize) -> Result<Option<String>, QRCodeScanError> {
|
||||||
let device = Device::new(index)?;
|
let device = Device::new(index)?;
|
||||||
|
|
|
@ -13,9 +13,9 @@ bin = ["image"]
|
||||||
image = ["dep:image"]
|
image = ["dep:image"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-zbar-sys = { workspace = true }
|
keyfork-zbar-sys = { version = "0.1.0", path = "../keyfork-zbar-sys", registry = "distrust" }
|
||||||
image = { workspace = true, default-features = false, optional = true }
|
image = { version = "0.24.7", default-features = false, optional = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.56"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
v4l = { workspace = true }
|
v4l = "0.14.0"
|
||||||
|
|
|
@ -33,7 +33,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.decode()?,
|
.decode()?,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(symbol) = scanner.scan_image(&image).first() {
|
if let Some(symbol) = scanner.scan_image(&image).get(0) {
|
||||||
println!("{}", String::from_utf8_lossy(symbol.data()));
|
println!("{}", String::from_utf8_lossy(symbol.data()));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! A Symbol represents some form of encoded data.
|
//!
|
||||||
|
|
||||||
use super::sys;
|
use super::sys;
|
||||||
|
|
||||||
|
|
|
@ -9,4 +9,4 @@ license = "MIT"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = "1.0.79"
|
||||||
|
|
|
@ -55,16 +55,16 @@ crossterm_winapi = { version = "0.9.1", optional = true }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
signal-hook = { version = "0.3.17", optional = true }
|
signal-hook = { version = "0.3.17", optional = true }
|
||||||
filedescriptor = { version = "0.8", optional = true }
|
filedescriptor = { version = "0.8", optional = true }
|
||||||
mio = { version = "1.0", features = ["os-poll"], optional = true }
|
mio = { version = "0.8", features = ["os-poll"], optional = true }
|
||||||
signal-hook-mio = { version = "0.2.3", features = ["support-v1_0"], optional = true }
|
signal-hook-mio = { version = "0.2.3", features = ["support-v0_8"], optional = true }
|
||||||
|
|
||||||
# Dev dependencies (examples, ...)
|
# Dev dependencies (examples, ...)
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { workspace = true, features = ["full"] }
|
tokio = { version = "1.25", features = ["full"] }
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
futures-timer = "3.0"
|
futures-timer = "3.0"
|
||||||
async-std = "1.12"
|
async-std = "1.12"
|
||||||
serde_json = { workspace = true }
|
serde_json = "1.0"
|
||||||
serial_test = "2.0.0"
|
serial_test = "2.0.0"
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![allow(missing_docs)]
|
//!
|
||||||
|
|
||||||
use keyfork_crossterm::{
|
use keyfork_crossterm::{
|
||||||
execute,
|
execute,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{collections::VecDeque, io, time::Duration};
|
use std::{collections::VecDeque, io, time::Duration};
|
||||||
|
|
||||||
use mio::{unix::SourceFd, Events, Interest, Poll, Token};
|
use mio::{unix::SourceFd, Events, Interest, Poll, Token};
|
||||||
use signal_hook_mio::v1_0::Signals;
|
use signal_hook_mio::v0_8::Signals;
|
||||||
|
|
||||||
#[cfg(feature = "event-stream")]
|
#[cfg(feature = "event-stream")]
|
||||||
use crate::event::sys::Waker;
|
use crate::event::sys::Waker;
|
||||||
|
|
|
@ -11,5 +11,5 @@ default = ["bin"]
|
||||||
bin = ["smex"]
|
bin = ["smex"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-bug = { workspace = true }
|
keyfork-bug = { version = "0.1.0", path = "../keyfork-bug", registry = "distrust" }
|
||||||
smex = { workspace = true, optional = true }
|
smex = { version = "0.1.0", path = "../smex", optional = true, registry = "distrust" }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Generate entropy of a given size, encoded as hex.
|
//!
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let bit_size: usize = std::env::args()
|
let bit_size: usize = std::env::args()
|
||||||
|
|
|
@ -12,13 +12,13 @@ async = ["dep:tokio"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Included in Rust
|
# Included in Rust
|
||||||
sha2 = { workspace = true }
|
sha2 = "0.10.7"
|
||||||
|
|
||||||
# Personally audited
|
# Personally audited
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.47"
|
||||||
|
|
||||||
# Optional, not personally audited
|
# Optional, not personally audited
|
||||||
tokio = { workspace = true, optional = true, features = ["io-util"] }
|
tokio = { version = "1.32.0", optional = true, features = ["io-util"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
insta = "1.31.0"
|
insta = "1.31.0"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "keyfork-mnemonic"
|
name = "keyfork-mnemonic"
|
||||||
version = "0.4.0"
|
version = "0.3.0"
|
||||||
description = "Utilities to generate and manage seeds based on BIP-0039 mnemonics."
|
description = "Utilities to generate and manage seeds based on BIP-0039 mnemonics."
|
||||||
repository = "https://git.distrust.co/public/keyfork"
|
repository = "https://git.distrust.co/public/keyfork"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
@ -11,14 +11,14 @@ default = ["bin"]
|
||||||
bin = ["smex"]
|
bin = ["smex"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
smex = { workspace = true, optional = true }
|
smex = { version = "0.1.0", path = "../smex", optional = true, registry = "distrust" }
|
||||||
keyfork-bug = { workspace = true }
|
keyfork-bug = { version = "0.1.0", path = "../keyfork-bug", registry = "distrust" }
|
||||||
|
|
||||||
sha2 = { workspace = true }
|
sha2 = "0.10.7"
|
||||||
hmac = { workspace = true }
|
hmac = "0.12.1"
|
||||||
pbkdf2 = "0.12.2"
|
pbkdf2 = "0.12.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bip39 = "2.0.0"
|
bip39 = "2.0.0"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
serde_json = { workspace = true }
|
serde_json = "1.0.105"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Generate a mnemonic from hex-encoded input.
|
//!
|
||||||
|
|
||||||
use keyfork_mnemonic::Mnemonic;
|
use keyfork_mnemonic::Mnemonic;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "keyfork-prompt"
|
name = "keyfork-prompt"
|
||||||
version = "0.1.2"
|
version = "0.1.1"
|
||||||
description = "Prompt management utilities for Keyfork"
|
description = "Prompt management utilities for Keyfork"
|
||||||
repository = "https://git.distrust.co/public/keyfork"
|
repository = "https://git.distrust.co/public/keyfork"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
@ -13,7 +13,7 @@ default = ["mnemonic"]
|
||||||
mnemonic = ["keyfork-mnemonic"]
|
mnemonic = ["keyfork-mnemonic"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
keyfork-bug = { workspace = true }
|
keyfork-bug = { version = "0.1.0", path = "../keyfork-bug", registry = "distrust" }
|
||||||
keyfork-crossterm = { workspace = true, default-features = false, features = ["use-dev-tty", "events", "bracketed-paste"] }
|
keyfork-crossterm = { version = "0.27.1", path = "../keyfork-crossterm", default-features = false, features = ["use-dev-tty", "events", "bracketed-paste"], registry = "distrust" }
|
||||||
keyfork-mnemonic = { workspace = true, optional = true }
|
keyfork-mnemonic = { version = "0.3.0", path = "../keyfork-mnemonic", optional = true, registry = "distrust" }
|
||||||
thiserror = { workspace = true }
|
thiserror = "1.0.51"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![allow(missing_docs)]
|
//!
|
||||||
|
|
||||||
use std::io::{stdin, stdout};
|
use std::io::{stdin, stdout};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
//! A terminal prompt handler.
|
|
||||||
//!
|
|
||||||
//! This prompt handler uses a raw terminal device to read inputs and uses ANSI escape codes to
|
|
||||||
//! provide formatting for prompts. Because of these reasons, it is not intended to be
|
|
||||||
//! machine-readable.
|
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Borrow,
|
borrow::Borrow,
|
||||||
io::{stderr, stdin, BufRead, BufReader, Read, Stderr, Stdin, Write},
|
io::{stderr, stdin, BufRead, BufReader, Read, Stderr, Stdin, Write},
|
||||||
|
|
|
@ -5,4 +5,4 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
smex = { workspace = true }
|
smex = { version = "0.1.0", path = "../smex", registry = "distrust" }
|
||||||
|
|
104
deny.toml
104
deny.toml
|
@ -11,9 +11,6 @@
|
||||||
|
|
||||||
# Root options
|
# Root options
|
||||||
|
|
||||||
# The graph table configures how the dependency graph is constructed and thus
|
|
||||||
# which crates the checks are performed against
|
|
||||||
[graph]
|
|
||||||
# If 1 or more target triples (and optionally, target_features) are specified,
|
# If 1 or more target triples (and optionally, target_features) are specified,
|
||||||
# only the specified targets will be checked when running `cargo deny check`.
|
# only the specified targets will be checked when running `cargo deny check`.
|
||||||
# This means, if a particular package is only ever used as a target specific
|
# This means, if a particular package is only ever used as a target specific
|
||||||
|
@ -25,7 +22,7 @@
|
||||||
targets = [
|
targets = [
|
||||||
# The triple can be any string, but only the target triples built in to
|
# The triple can be any string, but only the target triples built in to
|
||||||
# rustc (as of 1.40) can be checked against actual config expressions
|
# rustc (as of 1.40) can be checked against actual config expressions
|
||||||
#"x86_64-unknown-linux-musl",
|
#{ triple = "x86_64-unknown-linux-musl" },
|
||||||
# You can also specify which target_features you promise are enabled for a
|
# You can also specify which target_features you promise are enabled for a
|
||||||
# particular target. target_features are currently not validated against
|
# particular target. target_features are currently not validated against
|
||||||
# the actual valid features supported by the target architecture.
|
# the actual valid features supported by the target architecture.
|
||||||
|
@ -49,9 +46,6 @@ no-default-features = false
|
||||||
# If set, these feature will be enabled when collecting metadata. If `--features`
|
# If set, these feature will be enabled when collecting metadata. If `--features`
|
||||||
# is specified on the cmd line they will take precedence over this option.
|
# is specified on the cmd line they will take precedence over this option.
|
||||||
#features = []
|
#features = []
|
||||||
|
|
||||||
# The output table provides options for how/if diagnostics are outputted
|
|
||||||
[output]
|
|
||||||
# When outputting inclusion graphs in diagnostics that include features, this
|
# When outputting inclusion graphs in diagnostics that include features, this
|
||||||
# option can be used to specify the depth at which feature edges will be added.
|
# option can be used to specify the depth at which feature edges will be added.
|
||||||
# This option is included since the graphs can be quite large and the addition
|
# This option is included since the graphs can be quite large and the addition
|
||||||
|
@ -63,20 +57,38 @@ feature-depth = 1
|
||||||
# More documentation for the advisories section can be found here:
|
# More documentation for the advisories section can be found here:
|
||||||
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
|
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
|
||||||
[advisories]
|
[advisories]
|
||||||
# The path where the advisory databases are cloned/fetched into
|
# The path where the advisory database is cloned/fetched into
|
||||||
#db-path = "$CARGO_HOME/advisory-dbs"
|
db-path = "~/.cargo/advisory-db"
|
||||||
# The url(s) of the advisory databases to use
|
# The url(s) of the advisory databases to use
|
||||||
#db-urls = ["https://github.com/rustsec/advisory-db"]
|
db-urls = ["https://github.com/rustsec/advisory-db"]
|
||||||
|
# The lint level for security vulnerabilities
|
||||||
|
vulnerability = "deny"
|
||||||
|
# The lint level for unmaintained crates
|
||||||
|
unmaintained = "warn"
|
||||||
|
# The lint level for crates that have been yanked from their source registry
|
||||||
|
yanked = "warn"
|
||||||
|
# The lint level for crates with security notices. Note that as of
|
||||||
|
# 2019-12-17 there are no security notice advisories in
|
||||||
|
# https://github.com/rustsec/advisory-db
|
||||||
|
notice = "warn"
|
||||||
# A list of advisory IDs to ignore. Note that ignored advisories will still
|
# A list of advisory IDs to ignore. Note that ignored advisories will still
|
||||||
# output a note when they are encountered.
|
# output a note when they are encountered.
|
||||||
ignore = [
|
ignore = [
|
||||||
#"RUSTSEC-0000-0000",
|
#"RUSTSEC-0000-0000",
|
||||||
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
|
# Not applicable, RSA is not used for crypto operations in the dep it's
|
||||||
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
|
# used for, openpgp-card
|
||||||
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" },
|
"RUSTSEC-2023-0071",
|
||||||
|
|
||||||
{ id = "RUSTSEC-2023-0071", reason = "Not applicable, vulnerable path is not used" },
|
|
||||||
]
|
]
|
||||||
|
# Threshold for security vulnerabilities, any vulnerability with a CVSS score
|
||||||
|
# lower than the range specified will be ignored. Note that ignored advisories
|
||||||
|
# will still output a note when they are encountered.
|
||||||
|
# * None - CVSS Score 0.0
|
||||||
|
# * Low - CVSS Score 0.1 - 3.9
|
||||||
|
# * Medium - CVSS Score 4.0 - 6.9
|
||||||
|
# * High - CVSS Score 7.0 - 8.9
|
||||||
|
# * Critical - CVSS Score 9.0 - 10.0
|
||||||
|
#severity-threshold =
|
||||||
|
|
||||||
# If this is true, then cargo deny will use the git executable to fetch advisory database.
|
# If this is true, then cargo deny will use the git executable to fetch advisory database.
|
||||||
# If this is false, then it uses a built-in git library.
|
# If this is false, then it uses a built-in git library.
|
||||||
# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support.
|
# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support.
|
||||||
|
@ -87,6 +99,8 @@ ignore = [
|
||||||
# More documentation for the licenses section can be found here:
|
# More documentation for the licenses section can be found here:
|
||||||
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
|
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
|
||||||
[licenses]
|
[licenses]
|
||||||
|
# The lint level for crates which do not have a detectable license
|
||||||
|
unlicensed = "deny"
|
||||||
# List of explicitly allowed licenses
|
# List of explicitly allowed licenses
|
||||||
# See https://spdx.org/licenses/ for list of possible licenses
|
# See https://spdx.org/licenses/ for list of possible licenses
|
||||||
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
||||||
|
@ -99,9 +113,30 @@ allow = [
|
||||||
"Unicode-DFS-2016",
|
"Unicode-DFS-2016",
|
||||||
"LGPL-2.0",
|
"LGPL-2.0",
|
||||||
"LGPL-3.0",
|
"LGPL-3.0",
|
||||||
"Unicode-3.0",
|
#"Apache-2.0 WITH LLVM-exception",
|
||||||
]
|
]
|
||||||
|
# List of explicitly disallowed licenses
|
||||||
|
# See https://spdx.org/licenses/ for list of possible licenses
|
||||||
|
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
||||||
|
deny = [
|
||||||
|
#"Nokia",
|
||||||
|
]
|
||||||
|
# Lint level for licenses considered copyleft
|
||||||
|
copyleft = "warn"
|
||||||
|
# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
|
||||||
|
# * both - The license will be approved if it is both OSI-approved *AND* FSF
|
||||||
|
# * either - The license will be approved if it is either OSI-approved *OR* FSF
|
||||||
|
# * osi - The license will be approved if it is OSI approved
|
||||||
|
# * fsf - The license will be approved if it is FSF Free
|
||||||
|
# * osi-only - The license will be approved if it is OSI-approved *AND NOT* FSF
|
||||||
|
# * fsf-only - The license will be approved if it is FSF *AND NOT* OSI-approved
|
||||||
|
# * neither - This predicate is ignored and the default lint level is used
|
||||||
|
allow-osi-fsf-free = "neither"
|
||||||
|
# Lint level used when no other predicates are matched
|
||||||
|
# 1. License isn't in the allow or deny lists
|
||||||
|
# 2. License isn't copyleft
|
||||||
|
# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither"
|
||||||
|
default = "deny"
|
||||||
# The confidence threshold for detecting a license from license text.
|
# The confidence threshold for detecting a license from license text.
|
||||||
# The higher the value, the more closely the license text must be to the
|
# The higher the value, the more closely the license text must be to the
|
||||||
# canonical license text of a valid SPDX license file.
|
# canonical license text of a valid SPDX license file.
|
||||||
|
@ -112,7 +147,7 @@ confidence-threshold = 0.8
|
||||||
exceptions = [
|
exceptions = [
|
||||||
# Each entry is the crate and version constraint, and its specific allow
|
# Each entry is the crate and version constraint, and its specific allow
|
||||||
# list
|
# list
|
||||||
#{ allow = ["Zlib"], crate = "adler32" },
|
#{ allow = ["Zlib"], name = "adler32", version = "*" },
|
||||||
{ allow = ["BSL-1.0"], name = "xxhash-rust", version = "*" },
|
{ allow = ["BSL-1.0"], name = "xxhash-rust", version = "*" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -120,8 +155,10 @@ exceptions = [
|
||||||
# adding a clarification entry for it allows you to manually specify the
|
# adding a clarification entry for it allows you to manually specify the
|
||||||
# licensing information
|
# licensing information
|
||||||
#[[licenses.clarify]]
|
#[[licenses.clarify]]
|
||||||
# The package spec the clarification applies to
|
# The name of the crate the clarification applies to
|
||||||
#crate = "ring"
|
#name = "ring"
|
||||||
|
# The optional version constraint for the crate
|
||||||
|
#version = "*"
|
||||||
# The SPDX expression for the license requirements of the crate
|
# The SPDX expression for the license requirements of the crate
|
||||||
#expression = "MIT AND ISC AND OpenSSL"
|
#expression = "MIT AND ISC AND OpenSSL"
|
||||||
# One or more files in the crate's source used as the "source of truth" for
|
# One or more files in the crate's source used as the "source of truth" for
|
||||||
|
@ -130,8 +167,8 @@ exceptions = [
|
||||||
# and the crate will be checked normally, which may produce warnings or errors
|
# and the crate will be checked normally, which may produce warnings or errors
|
||||||
# depending on the rest of your configuration
|
# depending on the rest of your configuration
|
||||||
#license-files = [
|
#license-files = [
|
||||||
# Each entry is a crate relative path, and the (opaque) hash of its contents
|
# Each entry is a crate relative path, and the (opaque) hash of its contents
|
||||||
#{ path = "LICENSE", hash = 0xbd0eed23 }
|
#{ path = "LICENSE", hash = 0xbd0eed23 }
|
||||||
#]
|
#]
|
||||||
|
|
||||||
[licenses.private]
|
[licenses.private]
|
||||||
|
@ -171,24 +208,25 @@ workspace-default-features = "allow"
|
||||||
external-default-features = "allow"
|
external-default-features = "allow"
|
||||||
# List of crates that are allowed. Use with care!
|
# List of crates that are allowed. Use with care!
|
||||||
allow = [
|
allow = [
|
||||||
#"ansi_term@0.11.0",
|
#{ name = "ansi_term", version = "=0.11.0" },
|
||||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" },
|
|
||||||
]
|
]
|
||||||
# List of crates to deny
|
# List of crates to deny
|
||||||
deny = [
|
deny = [
|
||||||
#"ansi_term@0.11.0",
|
# Each entry the name of a crate and a version range. If version is
|
||||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" },
|
# not specified, all versions will be matched.
|
||||||
|
#{ name = "ansi_term", version = "=0.11.0" },
|
||||||
|
#
|
||||||
# Wrapper crates can optionally be specified to allow the crate when it
|
# Wrapper crates can optionally be specified to allow the crate when it
|
||||||
# is a direct dependency of the otherwise banned crate
|
# is a direct dependency of the otherwise banned crate
|
||||||
#{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] },
|
#{ name = "ansi_term", version = "=0.11.0", wrappers = [] },
|
||||||
{ name = "serde", version = ">1.0.171, <1.0.184", reason = "ships with prebuilt binaries" }
|
{ name = "serde", version = ">1.0.171, <1.0.184" }
|
||||||
]
|
]
|
||||||
|
|
||||||
# List of features to allow/deny
|
# List of features to allow/deny
|
||||||
# Each entry the name of a crate and a version range. If version is
|
# Each entry the name of a crate and a version range. If version is
|
||||||
# not specified, all versions will be matched.
|
# not specified, all versions will be matched.
|
||||||
#[[bans.features]]
|
#[[bans.features]]
|
||||||
#crate = "reqwest"
|
#name = "reqwest"
|
||||||
# Features to not allow
|
# Features to not allow
|
||||||
#deny = ["json"]
|
#deny = ["json"]
|
||||||
# Features to allow
|
# Features to allow
|
||||||
|
@ -209,18 +247,14 @@ deny = [
|
||||||
|
|
||||||
# Certain crates/versions that will be skipped when doing duplicate detection.
|
# Certain crates/versions that will be skipped when doing duplicate detection.
|
||||||
skip = [
|
skip = [
|
||||||
#"ansi_term@0.11.0",
|
#{ name = "ansi_term", version = "=0.11.0" },
|
||||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" },
|
|
||||||
]
|
]
|
||||||
# Similarly to `skip` allows you to skip certain crates during duplicate
|
# Similarly to `skip` allows you to skip certain crates during duplicate
|
||||||
# detection. Unlike skip, it also includes the entire tree of transitive
|
# detection. Unlike skip, it also includes the entire tree of transitive
|
||||||
# dependencies starting at the specified crate, up to a certain depth, which is
|
# dependencies starting at the specified crate, up to a certain depth, which is
|
||||||
# by default infinite.
|
# by default infinite.
|
||||||
skip-tree = [
|
skip-tree = [
|
||||||
{ name = "windows-sys" },
|
#{ name = "ansi_term", version = "=0.11.0", depth = 20 },
|
||||||
{ name = "windows-targets" },
|
|
||||||
#"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies
|
|
||||||
#{ crate = "ansi_term@0.11.0", depth = 20 },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# This section is considered when running `cargo deny check sources`.
|
# This section is considered when running `cargo deny check sources`.
|
||||||
|
|
|
@ -3,13 +3,12 @@ set -o pipefail
|
||||||
|
|
||||||
LAST_REF="$1"
|
LAST_REF="$1"
|
||||||
CURRENT_REF="${2:-HEAD}"
|
CURRENT_REF="${2:-HEAD}"
|
||||||
IGNORE="${3:-ABCDEFG}"
|
|
||||||
|
|
||||||
cargo metadata --format-version=1 | \
|
cargo metadata --format-version=1 | \
|
||||||
jq -r '.packages[] | select(.source == null) | .name + " " + .manifest_path' | \
|
jq -r '.packages[] | select(.source == null) | .name + " " + .manifest_path' | \
|
||||||
while read crate manifest_path; do
|
while read crate manifest_path; do
|
||||||
crate_path="$(dirname $manifest_path)"
|
crate_path="$(dirname $manifest_path)"
|
||||||
git_log="$(git log --format='%h %s' "$LAST_REF".."$CURRENT_REF" "$crate_path" | { grep -v "$IGNORE" || true; })"
|
git_log="$(git log --format='%h %s' "$LAST_REF"..HEAD "$crate_path")"
|
||||||
if test ! -z "$git_log"; then
|
if test ! -z "$git_log"; then
|
||||||
echo "### Changes in $crate:"
|
echo "### Changes in $crate:"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
|
@ -10,7 +10,7 @@ cargo metadata --format-version=1 | jq -r '.packages[] | select(.source == null)
|
||||||
|
|
||||||
while read crate manifest_path version <&3; do
|
while read crate manifest_path version <&3; do
|
||||||
crate_path="$(dirname $manifest_path)"
|
crate_path="$(dirname $manifest_path)"
|
||||||
git_log="$(git log --format='%h %s' "$LAST_REF".."$CURRENT_REF" "$crate_path")"
|
git_log="$(git log --format='%h %s' "$LAST_REF"..HEAD "$crate_path")"
|
||||||
git_tag="$(git tag --list "$crate-v${version}")"
|
git_tag="$(git tag --list "$crate-v${version}")"
|
||||||
if test ! -z "$git_log" -a -z "$git_tag"; then
|
if test ! -z "$git_log" -a -z "$git_tag"; then
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue