From d434b816e076e933dd23838562f45f618e82f3f8 Mon Sep 17 00:00:00 2001 From: rcrwhyg <56500577+rcrwhyg@users.noreply.github.com> Date: Wed, 28 Aug 2024 00:10:25 +0800 Subject: [PATCH] features: support text sign, part I --- Cargo.lock | 239 ++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 +- fixtures/blake3.txt | 1 + src/cli/base64.rs | 6 +- src/cli/csv.rs | 4 +- src/cli/mod.rs | 17 ++-- src/cli/text.rs | 72 +++++++++++++ src/lib.rs | 4 +- src/main.rs | 20 +++- src/process/b64.rs | 24 ++--- src/process/mod.rs | 2 + src/process/text.rs | 85 ++++++++++++++++ src/utils.rs | 11 ++ 13 files changed, 455 insertions(+), 34 deletions(-) create mode 100644 fixtures/blake3.txt create mode 100644 src/cli/text.rs create mode 100644 src/process/text.rs create mode 100644 src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 0c9a849..a0bc8ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,6 +81,18 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "arrayref" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "autocfg" version = "1.3.0" @@ -93,6 +105,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bit-set" version = "0.5.3" @@ -108,6 +126,28 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "blake3" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -195,12 +235,43 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpufeatures" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "csv" version = "1.3.0" @@ -222,6 +293,33 @@ dependencies = [ "memchr", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "darling" version = "0.20.10" @@ -257,6 +355,16 @@ dependencies = [ "syn", ] +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "deranged" version = "0.3.11" @@ -297,6 +405,40 @@ dependencies = [ "syn", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2", + "subtle", + "zeroize", +] + [[package]] name = "either" version = "1.13.0" @@ -320,12 +462,28 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -463,6 +621,16 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -532,8 +700,10 @@ version = "0.1.0" dependencies = [ "anyhow", "base64", + "blake3", "clap", "csv", + "ed25519-dalek", "rand", "serde", "serde_json", @@ -570,12 +740,27 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + [[package]] name = "serde" version = "1.0.209" @@ -621,18 +806,54 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.75" @@ -663,6 +884,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-ident" version = "1.0.12" @@ -681,6 +908,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -855,6 +1088,12 @@ dependencies = [ "syn", ] +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + [[package]] name = "zxcvbn" version = "3.1.0" diff --git a/Cargo.toml b/Cargo.toml index 87b68e9..57d8974 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,10 +10,12 @@ license = "MIT" [dependencies] anyhow = "1.0.86" base64 = "0.22.1" +blake3 = "1.5.4" clap = { version = "4.5.16", features = ["derive"] } csv = "1.3.0" +ed25519-dalek = "2.1.1" rand = "0.8.5" serde = { version = "1.0.209", features = ["derive"] } serde_json = "1.0.127" -serde_yaml = "0.9.34" +serde_yaml = "0.9.33" zxcvbn = "3.1.0" diff --git a/fixtures/blake3.txt b/fixtures/blake3.txt new file mode 100644 index 0000000..3a8250c --- /dev/null +++ b/fixtures/blake3.txt @@ -0,0 +1 @@ +SAI5V%f$1!HvIqB+AZX2QqA-g_fEEGMY \ No newline at end of file diff --git a/src/cli/base64.rs b/src/cli/base64.rs index 6d544b7..0d271b6 100644 --- a/src/cli/base64.rs +++ b/src/cli/base64.rs @@ -2,7 +2,7 @@ use std::{fmt, str::FromStr}; use clap::Parser; -use super::verify_input_file; +use super::verify_file; #[derive(Debug, Parser)] pub enum Base64SubCommand { @@ -12,7 +12,7 @@ pub enum Base64SubCommand { #[derive(Debug, Parser)] pub struct Base64EncodeOpts { - #[arg(short, long, value_parser = verify_input_file, default_value = "-")] + #[arg(short, long, value_parser = verify_file, default_value = "-")] pub input: String, #[arg(long, value_parser = parse_base64_format, default_value = "standard")] pub format: Base64Format, @@ -20,7 +20,7 @@ pub struct Base64EncodeOpts { #[derive(Debug, Parser)] pub struct Base64DecodeOpts { - #[arg(short, long, value_parser = verify_input_file, default_value = "-")] + #[arg(short, long, value_parser = verify_file, default_value = "-")] pub input: String, #[arg(long, value_parser = parse_base64_format, default_value = "standard")] pub format: Base64Format, diff --git a/src/cli/csv.rs b/src/cli/csv.rs index 7a15563..ecee300 100644 --- a/src/cli/csv.rs +++ b/src/cli/csv.rs @@ -2,7 +2,7 @@ use std::{fmt, str::FromStr}; use clap::Parser; -use super::verify_input_file; +use super::verify_file; #[derive(Debug, Clone, Copy)] pub enum OutputFormat { @@ -12,7 +12,7 @@ pub enum OutputFormat { #[derive(Debug, Parser)] pub struct CsvOpts { - #[arg(short, long, value_parser = verify_input_file)] + #[arg(short, long, value_parser = verify_file)] pub input: String, #[arg(short, long)] diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 7e91cff..1e5c14f 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,6 +1,7 @@ mod base64; mod csv; mod genpass; +mod text; use std::path::Path; @@ -10,6 +11,7 @@ use clap::Parser; pub use self::{ base64::{Base64Format, Base64SubCommand}, csv::OutputFormat, + text::{TextSignFormat, TextSubCommand}, }; #[derive(Debug, Parser)] @@ -27,9 +29,11 @@ pub enum Subcommand { GenPass(GenPassOpts), #[command(subcommand)] Base64(Base64SubCommand), + #[command(subcommand)] + Text(text::TextSubCommand), } -pub fn verify_input_file(filename: &str) -> Result { +pub fn verify_file(filename: &str) -> Result { // if input is "-" or file exists if filename == "-" || Path::new(filename).exists() { Ok(filename.into()) @@ -44,12 +48,9 @@ mod tests { #[test] fn test_verify_input_file() { - assert_eq!(verify_input_file("-"), Ok("-".into())); - assert_eq!(verify_input_file("*"), Err("File does not exist")); - assert_eq!(verify_input_file("Cargo.toml"), Ok("Cargo.toml".into())); - assert_eq!( - verify_input_file("./not_exist.csv"), - Err("File does not exist") - ); + assert_eq!(verify_file("-"), Ok("-".into())); + assert_eq!(verify_file("*"), Err("File does not exist")); + assert_eq!(verify_file("Cargo.toml"), Ok("Cargo.toml".into())); + assert_eq!(verify_file("./not_exist.csv"), Err("File does not exist")); } } diff --git a/src/cli/text.rs b/src/cli/text.rs new file mode 100644 index 0000000..6d38bb5 --- /dev/null +++ b/src/cli/text.rs @@ -0,0 +1,72 @@ +use std::{fmt, str::FromStr}; + +use clap::Parser; + +use super::verify_file; + +#[derive(Debug, Parser)] +pub enum TextSubCommand { + #[command(about = "Sign a message with a private/shared key")] + Sign(TextSignOpts), + #[command(name = "verify", about = "Verify a signed message")] + Verify(TextVerifyOpts), +} + +#[derive(Debug, Parser)] +pub struct TextSignOpts { + #[arg(short, long, value_parser = verify_file, default_value = "-")] + pub input: String, + #[arg(short, long, value_parser = verify_file)] + pub key: String, + #[arg(long, value_parser = parse_format, default_value = "blake3")] + pub format: TextSignFormat, +} + +#[derive(Debug, Parser)] +pub struct TextVerifyOpts { + #[arg(short, long, value_parser = verify_file, default_value = "-")] + pub input: String, + #[arg(short, long, value_parser = verify_file)] + pub key: String, + #[arg(long, value_parser = parse_format, default_value = "blake3")] + pub format: TextSignFormat, + #[arg(short, long)] + pub sig: String, +} + +#[derive(Debug, Clone, Copy)] +pub enum TextSignFormat { + Blake3, + Ed25519, +} + +fn parse_format(format: &str) -> Result { + format.parse() +} + +impl FromStr for TextSignFormat { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + match s { + "blake3" => Ok(TextSignFormat::Blake3), + "ed25519" => Ok(TextSignFormat::Ed25519), + _ => Err(anyhow::anyhow!("Invalid format")), + } + } +} + +impl From for &'static str { + fn from(format: TextSignFormat) -> Self { + match format { + TextSignFormat::Blake3 => "blake3", + TextSignFormat::Ed25519 => "ed25519", + } + } +} + +impl fmt::Display for TextSignFormat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", Into::<&'static str>::into(*self)) + } +} diff --git a/src/lib.rs b/src/lib.rs index da66a57..5b40fcf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,7 @@ mod cli; mod process; +mod utils; -pub use cli::{Base64Format, Base64SubCommand, Opts, Subcommand}; +pub use cli::{Base64Format, Base64SubCommand, Opts, Subcommand, TextSignFormat, TextSubCommand}; pub use process::*; +pub use utils::*; diff --git a/src/main.rs b/src/main.rs index 6625e66..70a4be7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ +use std::os::unix::process; + use clap::Parser; use rcli::{ - process_csv, process_decode, process_encode, process_genpass, Base64SubCommand, Opts, - Subcommand, + process_csv, process_decode, process_encode, process_genpass, process_text_sign, + Base64SubCommand, Opts, Subcommand, TextSubCommand, }; fn main() -> anyhow::Result<()> { @@ -30,6 +32,20 @@ fn main() -> anyhow::Result<()> { process_decode(&opts.input, opts.format)?; } }, + Subcommand::Text(subcmd) => match subcmd { + TextSubCommand::Sign(opts) => match opts.format { + rcli::TextSignFormat::Blake3 => { + process_text_sign(&opts.input, &opts.key, opts.format); + } + + rcli::TextSignFormat::Ed25519 => { + println!("Sign with Ed25519") + } + }, + TextSubCommand::Verify(opts) => { + println!("{:?}", opts); + } + }, } Ok(()) diff --git a/src/process/b64.rs b/src/process/b64.rs index a7de2bf..151da3c 100644 --- a/src/process/b64.rs +++ b/src/process/b64.rs @@ -5,7 +5,7 @@ use base64::{ Engine as _, }; -use crate::cli::Base64Format; +use crate::{cli::Base64Format, get_reader}; pub fn process_encode(input: &str, format: Base64Format) -> anyhow::Result<()> { let mut reader: Box = get_reader(input)?; @@ -42,16 +42,6 @@ pub fn process_decode(input: &str, format: Base64Format) -> anyhow::Result<()> { Ok(()) } -fn get_reader(input: &str) -> anyhow::Result> { - let reader: Box = if input == "-" { - Box::new(std::io::stdin()) - } else { - Box::new(File::open(input)?) - }; - - Ok(reader) -} - #[cfg(test)] mod tests { use super::*; @@ -63,10 +53,10 @@ mod tests { // assert!(process_encode(input, Base64Format::UrlSafe).is_ok()); } - // #[test] - // fn test_process_decode() { - // let input = "fixtures/base64.txt"; - // assert!(process_decode(input, Base64Format::Standard).is_ok()); - // // assert!(process_decode(input, Base64Format::UrlSafe).is_ok()); - // } + // #[test] + // fn test_process_decode() { + // let input = "fixtures/base64.txt"; + // assert!(process_decode(input, Base64Format::Standard).is_ok()); + // // assert!(process_decode(input, Base64Format::UrlSafe).is_ok()); + // } } diff --git a/src/process/mod.rs b/src/process/mod.rs index 96e9fd7..e7ffa92 100644 --- a/src/process/mod.rs +++ b/src/process/mod.rs @@ -1,7 +1,9 @@ mod b64; mod csv_convert; mod gen_pass; +mod text; pub use b64::{process_decode, process_encode}; pub use csv_convert::process_csv; pub use gen_pass::process_genpass; +pub use text::process_text_sign; diff --git a/src/process/text.rs b/src/process/text.rs new file mode 100644 index 0000000..0b1dcfe --- /dev/null +++ b/src/process/text.rs @@ -0,0 +1,85 @@ +use std::{fs, io::Read}; + +use anyhow::Ok; +use ed25519_dalek::{Signature, Signer, SigningKey, VerifyingKey}; + +use crate::{get_reader, TextSignFormat}; + +trait TextSign { + /// Sign the data from the reader and return the signature + fn sign(&self, reader: &mut dyn Read) -> anyhow::Result>; +} + +trait TextVerify { + /// Verify the data from the reader and return with the signature + fn verify(&self, reader: impl Read, sig: &[u8]) -> anyhow::Result; +} + +struct Blake3 { + key: [u8; 32], +} + +struct Ed25519Signer { + key: SigningKey, +} + +struct Ed25519Verifier { + key: VerifyingKey, +} + +pub fn process_text_sign(input: &str, key: &str, format: TextSignFormat) -> anyhow::Result<()> { + let mut reader = get_reader(input)?; + let mut buf = Vec::new(); + reader.read_to_end(&mut buf)?; + let signed = match format { + TextSignFormat::Blake3 => { + let key = fs::read(key)?; + let key = &key[..32]; + let key = key.try_into()?; + let signer = Blake3 { key }; + signer.sign(&mut reader)? + } + TextSignFormat::Ed25519 => todo!(), + }; + + // println!("{}", signed); + Ok(()) +} + +impl TextSign for Blake3 { + fn sign(&self, reader: &mut dyn Read) -> anyhow::Result> { + // TODO: improve performance by reading in chunks + let mut buf = Vec::new(); + reader.read_to_end(&mut buf)?; + Ok(blake3::keyed_hash(&self.key, &buf).as_bytes().to_vec()) + } +} + +impl TextSign for Ed25519Signer { + fn sign(&self, reader: &mut dyn Read) -> anyhow::Result> { + let mut buf = Vec::new(); + reader.read_to_end(&mut buf)?; + let sig = self.key.sign(&buf); + Ok(sig.to_bytes().to_vec()) + } +} + +impl TextVerify for Blake3 { + fn verify(&self, mut reader: impl Read, sig: &[u8]) -> anyhow::Result { + let mut buf = Vec::new(); + reader.read_to_end(&mut buf)?; + let hash = blake3::hash(&buf); + let hash = hash.as_bytes(); + Ok(hash == sig) + } +} + +impl TextVerify for Ed25519Verifier { + fn verify(&self, mut reader: impl Read, sig: &[u8]) -> anyhow::Result { + let mut buf = Vec::new(); + reader.read_to_end(&mut buf)?; + let sig = Signature::from_bytes(sig.try_into()?)?; + let ret = self.key.verify(&buf, &sig).is_ok(); + Ok(ret) + } +} diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..f9863d7 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,11 @@ +use std::{fs::File, io::Read}; + +pub fn get_reader(input: &str) -> anyhow::Result> { + let reader: Box = if input == "-" { + Box::new(std::io::stdin()) + } else { + Box::new(File::open(input)?) + }; + + Ok(reader) +}