-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 🐛 Complete signing feature and start working on verifying.
- Loading branch information
1 parent
fc38e7b
commit 7bca000
Showing
8 changed files
with
141 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,9 +70,10 @@ where | |
|
||
#[cfg(test)] | ||
mod tests { | ||
use pgp::{types::KeyTrait, Deserializable, SignedSecretKey}; | ||
|
||
use crate::{key_pair::KeyPair, Result}; | ||
use pgp::{types::KeyTrait, SignedSecretKey}; | ||
|
||
use crate::{from_file::FromFile, key_pair::KeyPair, Result}; | ||
|
||
#[test] | ||
fn test() -> Result<()> { | ||
|
@@ -88,9 +89,9 @@ mod tests { | |
fn extract_key_info() -> Result<()> { | ||
let secret_key_str = KeyPair::generate("example", "[email protected]", String::new)? | ||
.secret_key() | ||
.to_armored_string(None)?; | ||
.to_armored_bytes(None)?; | ||
|
||
let secret_key = SignedSecretKey::from_string(&secret_key_str)?.0; | ||
let secret_key = SignedSecretKey::try_from_armored_bytes(secret_key_str)?; | ||
dbg!(&secret_key); | ||
let key_id = secret_key.key_id(); | ||
dbg!(&key_id); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,26 @@ | ||
//! Utilities for signing files. | ||
use std::path::{Path, PathBuf}; | ||
use std::{ | ||
io::{self, Read}, | ||
path::{Path, PathBuf}, | ||
}; | ||
|
||
use chrono::Utc; | ||
use pgp::{ | ||
packet::{self, SignatureConfigBuilder, SignatureType, Subpacket, SubpacketData}, | ||
types::{PublicKeyTrait, SecretKeyTrait}, | ||
Signature, SignedSecretKey, | ||
types::SecretKeyTrait, | ||
Signature, SignedPublicKey, SignedSecretKey, | ||
}; | ||
use tokio::fs::{read, File}; | ||
use tokio::fs::File; | ||
|
||
use crate::{from_file::FromFile, Result}; | ||
|
||
/// Generate a signature of the given data. | ||
fn sign(data: &[u8], secret_key: &impl SecretKeyTrait) -> Result<Signature> { | ||
fn sign( | ||
data: impl Read, | ||
secret_key: &impl SecretKeyTrait, | ||
passwd_fn: impl FnOnce() -> String + Clone, | ||
) -> Result<Signature> { | ||
let now = Utc::now(); | ||
let sig_conf = SignatureConfigBuilder::default() | ||
.pub_alg(secret_key.algorithm()) | ||
|
@@ -26,12 +33,7 @@ fn sign(data: &[u8], secret_key: &impl SecretKeyTrait) -> Result<Signature> { | |
]) | ||
.unhashed_subpackets(vec![]) | ||
.build()?; | ||
Ok(sig_conf.sign(secret_key, String::new, data)?) | ||
} | ||
#[allow(dead_code)] | ||
/// Verify a signature of the given data. | ||
fn verify(data: &[u8], public_key: &impl PublicKeyTrait, signature: &Signature) -> Result<()> { | ||
Ok(signature.verify(public_key, data)?) | ||
Ok(sig_conf.sign(secret_key, passwd_fn, data)?) | ||
} | ||
|
||
/// Sign the given file with the given secret key. | ||
|
@@ -42,13 +44,19 @@ fn verify(data: &[u8], public_key: &impl PublicKeyTrait, signature: &Signature) | |
/// - The file or secret key cannot be read. | ||
/// - Secret key is invalid. | ||
/// - Failed to write to signature file. | ||
pub async fn sign_file_with_key( | ||
file_path: impl AsRef<Path>, | ||
secret_key_path: impl AsRef<Path>, | ||
) -> Result<PathBuf> { | ||
let file_data = read(&file_path).await?; | ||
let secret_key = SignedSecretKey::try_from_file(secret_key_path.as_ref()).await?; | ||
let signature = sign(&file_data, &secret_key)?; | ||
pub async fn sign_file_with_key<F, S, PF>( | ||
file_path: F, | ||
secret_key_path: S, | ||
passwd_fn: PF, | ||
) -> Result<PathBuf> | ||
where | ||
F: AsRef<Path>, | ||
S: AsRef<Path> + Send, | ||
PF: FnOnce() -> String + Clone, | ||
{ | ||
let file = File::open(&file_path).await?; | ||
let secret_key = SignedSecretKey::try_from_file(secret_key_path).await?; | ||
let signature = sign(file.into_std().await, &secret_key, passwd_fn)?; | ||
let mut signature_path = file_path.as_ref().to_owned(); | ||
signature_path.as_mut_os_string().push(".sig"); | ||
let mut signature_file = File::options() | ||
|
@@ -62,14 +70,43 @@ pub async fn sign_file_with_key( | |
Ok(signature_path) | ||
} | ||
|
||
/// . | ||
/// | ||
/// # Errors | ||
/// | ||
/// This function will return an error if . | ||
pub async fn verify_file_with_key<S, P>(signature_path: S, public_key_path: P) -> Result<bool> | ||
where | ||
S: AsRef<Path> + Send, | ||
P: AsRef<Path> + Send, | ||
{ | ||
let signature_path = signature_path.as_ref(); | ||
let signature = Signature::try_from_file(signature_path).await?; | ||
let public_key = SignedPublicKey::try_from_file(public_key_path).await?; | ||
if let Some(file_path) = signature_path | ||
.extension() | ||
.is_some_and(|ext| ext == "sig") | ||
.then(|| signature_path.with_extension("")) | ||
{ | ||
Ok(signature | ||
.verify(&public_key, File::open(file_path).await?.into_std().await) | ||
.is_ok()) | ||
} else { | ||
Err(io::Error::new( | ||
io::ErrorKind::NotFound, | ||
"Original file not found.", | ||
))? | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
|
||
use pgp::{Signature, SignedPublicKey}; | ||
use temp_dir::TempDir; | ||
use tokio::fs::write; | ||
|
||
use super::{sign, sign_file_with_key, verify}; | ||
use super::{sign, sign_file_with_key}; | ||
use crate::{ | ||
from_file::FromFile, | ||
key_pair::KeyPair, | ||
|
@@ -81,25 +118,27 @@ mod tests { | |
fn test_sign() -> Result<()> { | ||
let key_pair = KeyPair::generate("example", "[email protected]", String::new)?; | ||
let (secret_key, public_key) = (key_pair.secret_key(), key_pair.public_key()); | ||
let signature = sign(b"Hello", &secret_key)?; | ||
verify(b"Hello", &public_key, &signature)?; | ||
let signature = sign(&b"Hello"[..], &secret_key, String::new)?; | ||
signature.verify(public_key, &b"Hello"[..])?; | ||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn test_sign_error() -> Result<()> { | ||
let key_pair = KeyPair::generate("example", "[email protected]", String::new)?; | ||
let (secret_key, public_key) = (key_pair.secret_key(), key_pair.public_key()); | ||
let signature = sign(b"Hello", &secret_key)?; | ||
let signature = sign(&b"Hello"[..], &secret_key, String::new)?; | ||
eprintln!( | ||
"{:?}", | ||
verify(b"Help", &public_key, &signature).expect_err("Should not pass") | ||
signature | ||
.verify(&public_key, &b"Help"[..]) | ||
.expect_err("Should not pass") | ||
); | ||
Ok(()) | ||
} | ||
|
||
#[tokio::test] | ||
async fn test_sign_file() -> Result<()> { | ||
async fn test_whole_process() -> Result<()> { | ||
let tmp_dir = TempDir::new()?; | ||
let KeyPairPaths { | ||
secret_key_path, | ||
|
@@ -118,16 +157,16 @@ mod tests { | |
|
||
let data_path = tmp_dir.path().join("data"); | ||
write(&data_path, data).await?; | ||
|
||
let public_key = SignedPublicKey::try_from_file(&public_key_path).await?; | ||
|
||
let sig_path = sign_file_with_key(&data_path, secret_key_path).await?; | ||
|
||
dbg!(&data_path); | ||
let sig_path = sign_file_with_key(&data_path, &secret_key_path, String::new).await?; | ||
dbg!(&sig_path); | ||
let signature = Signature::try_from_file(sig_path).await?; | ||
let public_key = SignedPublicKey::try_from_file(&public_key_path).await?; | ||
dbg!(&public_key); | ||
|
||
dbg!(&signature); | ||
|
||
let verified = verify(data, &public_key, &signature).is_ok(); | ||
let verified = signature.verify(&public_key, &data[..]).is_ok(); //verify(data, &public_key, &signature).is_ok(); | ||
|
||
dbg!(verified); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,20 @@ | ||
use std::path::{Path, PathBuf}; | ||
|
||
use digital_signature_crypto::signing::sign_file_with_key; | ||
use futures::{future::join_all, TryFutureExt}; | ||
use futures::future::try_join_all; | ||
|
||
use crate::error::Result; | ||
|
||
#[tauri::command] | ||
pub async fn sign_files(file_paths: Vec<&Path>, key_path: &Path) -> Result<Vec<PathBuf>> { | ||
join_all( | ||
pub async fn sign_files( | ||
file_paths: Vec<&Path>, | ||
key_path: &Path, | ||
passwd: &str, | ||
) -> Result<Vec<PathBuf>> { | ||
Ok(try_join_all( | ||
file_paths | ||
.into_iter() | ||
.map(|file_path| sign_file_with_key(file_path, key_path).err_into()), | ||
.map(|file_path| sign_file_with_key(file_path, key_path, || String::from(passwd))), | ||
) | ||
.await | ||
.into_iter() | ||
.collect::<Result<_>>() | ||
.await?) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
use std::{convert::identity, path::Path}; | ||
|
||
use digital_signature_crypto::signing::verify_file_with_key; | ||
use futures::future::try_join_all; | ||
|
||
use crate::error::Result; | ||
#[tauri::command] | ||
pub async fn verify_signatures(sig_paths: Vec<&Path>, public_key_path: &Path) -> Result<bool> { | ||
let result = try_join_all( | ||
sig_paths | ||
.into_iter() | ||
.map(|sig_path| verify_file_with_key(sig_path, public_key_path)), | ||
) | ||
.await?; | ||
Ok(result.into_iter().all(identity)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.