Skip to content

Commit

Permalink
FeatureAdd: complete text generate key for blake3 and ed25519
Browse files Browse the repository at this point in the history
  • Loading branch information
Firstero committed Apr 25, 2024
1 parent 803ebc4 commit 288234c
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 10 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ blake3 = "1.5.1"
clap = { version = "4.5.4", features = ["derive"] }
csv = "1.3.0"
ed25519 = "2.2.3"
ed25519-dalek = "2.1.1"
ed25519-dalek = { version = "2.1.1", features = ["rand_core"] }
rand = "0.8.5"
serde = { version = "1.0.198", features = ["derive"] }
serde_json = "1.0.116"
Expand Down
1 change: 1 addition & 0 deletions fixtures/blake3.key
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xUSZqzRNnuCE%~FWTh?axY8LuE*Mb4D4
Binary file added fixtures/ed25519.pk
Binary file not shown.
1 change: 1 addition & 0 deletions fixtures/ed25519.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
\�{��+��w^Hy���$|vqK�Ư��:��G
12 changes: 11 additions & 1 deletion src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod genpass_opts;
mod text;

use std::fs;
use std::path::{Path, PathBuf};

pub use self::base64_opts::{Base64Format, Base64Opts, Base64SubCommand};
pub use self::csv_opts::{CsvOpts, OutputFormat};
Expand Down Expand Up @@ -34,14 +35,23 @@ pub enum SubCommand {
}

// 模块级别的函数,共享input file的解析逻辑
fn parse_input_file(path: &str) -> Result<String, String> {
pub fn parse_input_file(path: &str) -> Result<String, String> {
if path == "-" || fs::metadata(path).is_ok() {
Ok(path.to_string())
} else {
Err(format!("file not found: {}", path))
}
}

pub fn verify_dir(path: &str) -> Result<PathBuf, &'static str> {
let path = Path::new(path);
if path.exists() && path.is_dir() {
Ok(path.into())
} else {
Err("directory not found")
}
}

// 单元测试
#[cfg(test)]
mod tests {
Expand Down
14 changes: 12 additions & 2 deletions src/cli/text.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use clap::Parser;
use std::{fmt::Display, str::FromStr};
use std::{fmt::Display, path::PathBuf, str::FromStr};

use super::parse_input_file;
use super::{parse_input_file, verify_dir};
#[derive(Debug, Parser)]
pub struct TextOpts {
#[command(subcommand)]
Expand All @@ -14,6 +14,16 @@ pub enum TextSubCommand {
Sign(TextSignOpts),
#[command(name = "verify", about = "Verify text with public/shared key.")]
Verify(TextVerifyOpts),
#[command(name = "generate", about = "Generate random key.")]
Generate(TextKeyGenerateOpts),
}

#[derive(Debug, Parser)]
pub struct TextKeyGenerateOpts {
#[arg(long, value_parser=TextSignFormat::from_str, default_value="blake3", help = "key file path, or '-' for stdin")]
pub format: TextSignFormat,
#[arg(short, long, value_parser=verify_dir)]
pub output: PathBuf,
}

#[derive(Debug, Parser)]
Expand Down
9 changes: 6 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
mod cli;
mod process;
mod utils;
pub use cli::{Base64SubCommand, Opts, SubCommand, TextSignFormat, TextSubCommand};
pub use cli::{
parse_input_file, verify_dir, Base64SubCommand, Opts, SubCommand, TextSignFormat,
TextSubCommand,
};
pub use process::{
process_b64decode, process_b64encode, process_csv, process_genpass, process_sign,
process_verify,
process_b64decode, process_b64encode, process_csv, process_generate, process_genpass,
process_sign, process_verify,
};
pub use utils::{get_content, get_reader};
22 changes: 20 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::fs;

use anyhow::Result;
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
use clap::Parser;
use zxcvbn::zxcvbn;

use rcli::{
get_content, get_reader, process_b64decode, process_b64encode, process_csv, process_genpass,
process_sign, process_verify, Base64SubCommand, Opts, SubCommand, TextSubCommand,
get_content, get_reader, process_b64decode, process_b64encode, process_csv, process_generate,
process_genpass, process_sign, process_verify, Base64SubCommand, Opts, SubCommand,
TextSignFormat, TextSubCommand,
};

// usage:
Expand Down Expand Up @@ -58,13 +61,28 @@ fn main() -> Result<()> {
let mut reader = get_reader(&opts.input)?;
let key = get_content(&opts.key)?;
let sig = URL_SAFE_NO_PAD.decode(&opts.sig)?;
println!("sig: {:?}", sig.len());
let verified = process_verify(&mut reader, &key, &sig, opts.format)?;
if verified {
println!("✓ Signature verified");
} else {
println!("⚠ Signature not verified");
}
}
TextSubCommand::Generate(opts) => {
let keys = process_generate(opts.format)?;
match opts.format {
TextSignFormat::Blake3 => {
let name = opts.output.join("blake3.key");
let keys = process_generate(opts.format)?;
fs::write(name, &keys[0])?;
}
TextSignFormat::Ed25519 => {
fs::write(opts.output.join("ed25519.sk"), &keys[0])?;
fs::write(opts.output.join("ed25519.pk"), &keys[1])?;
}
}
}
},
}
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ pub use base64_processor::process_decode as process_b64decode;
pub use base64_processor::process_encode as process_b64encode;
pub use csv_processor::process as process_csv;
pub use genpass_processor::process as process_genpass;
pub use text::{process_sign, process_verify};
pub use text::{process_generate, process_sign, process_verify};
34 changes: 34 additions & 0 deletions src/process/text.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use crate::process_genpass;
use crate::TextSignFormat;
use anyhow::anyhow;
use anyhow::Result;
use ed25519::signature::{Signer, Verifier};
use ed25519_dalek::{Signature, SigningKey, VerifyingKey};
use rand::rngs::OsRng;
use std::io::Read;
use std::vec;

trait TextSign {
fn sign(&self, reader: &mut dyn Read) -> Result<Vec<u8>>;
Expand All @@ -13,6 +16,10 @@ trait TextVerify {
fn verify(&self, reader: &mut dyn Read, sig: &[u8]) -> Result<bool>;
}

trait KeyGenerator {
fn generate() -> Result<Vec<Vec<u8>>>;
}

struct Blake3 {
key: [u8; 32],
}
Expand Down Expand Up @@ -42,6 +49,14 @@ impl TextSign for Blake3 {
}
}

impl KeyGenerator for Blake3 {
fn generate() -> Result<Vec<Vec<u8>>> {
let ret = process_genpass(false, false, false, false, 32);
println!("{:?}", ret);
Ok(vec![ret])
}
}

impl TextVerify for Blake3 {
fn verify(&self, reader: &mut dyn Read, sig: &[u8]) -> Result<bool> {
let mut data = Vec::new();
Expand Down Expand Up @@ -76,6 +91,18 @@ impl TextSign for Ed25519Signer {
}
}

impl KeyGenerator for Ed25519Signer {
fn generate() -> Result<Vec<Vec<u8>>> {
let mut rng = OsRng;
let signing_key = SigningKey::generate(&mut rng);
let verifying_key = VerifyingKey::from(&signing_key);
Ok(vec![
signing_key.as_bytes().to_vec(),
verifying_key.as_bytes().to_vec(),
])
}
}

struct Ed25519Verifier {
key: VerifyingKey,
}
Expand Down Expand Up @@ -125,6 +152,13 @@ pub fn process_verify(
verifier.verify(reader, sig)
}

pub fn process_generate(format: TextSignFormat) -> Result<Vec<Vec<u8>>> {
match format {
TextSignFormat::Blake3 => Blake3::generate(),
TextSignFormat::Ed25519 => Ed25519Signer::generate(),
}
}

// 生成测试用例
#[cfg(test)]
mod tests {
Expand Down

0 comments on commit 288234c

Please sign in to comment.