Skip to content

Commit

Permalink
long signature certificates
Browse files Browse the repository at this point in the history
Signed-off-by: Dr Maxim Orlovsky <[email protected]>
  • Loading branch information
dr-orlovsky committed Apr 26, 2024
1 parent e340d02 commit c8da72d
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub use ed25519::Ed25519Secret;
pub use identity::{Ssi, SsiParseError, Uid};
pub use public::{
Algo, CertParseError, Chain, Fingerprint, InvalidPubkey, InvalidSig, SsiCert, SsiPub, SsiQuery,
SsiSig, UnknownAlgo, UnknownChain,
SsiSig, UnknownAlgo, UnknownChain, VerifyError,
};
pub use runtime::{Error, SsiRuntime, SSI_DIR};
pub use secret::{SecretParseError, SsiPair, SsiSecret};
23 changes: 19 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ pub enum Command {

/// Sign a file or a message
Sign {
/// Generate signature including the full identity
#[clap(long)]
full: bool,

/// Text message to sign
#[clap(short, long, conflicts_with = "file")]
text: Option<String>,
Expand Down Expand Up @@ -177,7 +181,12 @@ fn main() {
runtime.store().expect("unable to save data");
}

Command::Sign { text, file, ssi } => {
Command::Sign {
full,
text,
file,
ssi,
} => {
eprintln!("Signing with {ssi} ...");

let passwd = rpassword::prompt_password("Password for private key encryption: ")
Expand All @@ -199,15 +208,21 @@ fn main() {
.expect("unknown signing identity");
eprintln!("Using key {signer}");
let cert = signer.sign(msg);
println!("{cert}");
if full {
println!("{cert:#}");
} else {
println!("{cert}");
}
}

Command::Verify { signature } => {
eprint!("Verifying signature for message digest {} ... ", signature.msg);
let ssi = runtime
let pk = runtime
.find_identity(signature.fp)
.map(|ssi| ssi.pk)
.or(signature.pk)
.expect("unknown signing identity");
match ssi.pk.verify(signature.msg.to_byte_array(), signature.sig) {
match pk.verify(signature.msg.to_byte_array(), signature.sig) {
Ok(_) => eprintln!("valid"),
Err(err) => eprintln!("invalid: {err}"),
}
Expand Down
38 changes: 35 additions & 3 deletions src/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,17 +288,38 @@ impl FromStr for Fingerprint {
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct SsiCert {
pub fp: Fingerprint,
pub pk: Option<SsiPub>,
pub msg: Bytes32,
pub sig: SsiSig,
}

#[derive(Debug, Display, Error, From)]
#[display(inner)]
pub enum VerifyError {
#[display("the certificate has no identity, verification impossible.")]
NoIdentity,
#[from]
InvalidSig(InvalidSig),
}

impl SsiCert {
pub fn verify(&self) -> Result<(), VerifyError> {
let Some(pk) = self.pk else {
return Err(VerifyError::NoIdentity);
};
Ok(pk.verify(self.msg.to_byte_array(), self.sig)?)
}
}

#[derive(Debug, Display, Error, From)]
#[display(doc_comments)]
pub enum CertParseError {
/// SSI URI lacks signature or message information.
DataMissed,
/// invalid fingerprint data in private key - {0}.
/// invalid certificate identity fingerprint - {0}.
InvalidFingerprint(Baid64ParseError),
/// invalid certificate identity key - {0}.
InvalidPub(Baid64ParseError),
/// invalid message digest - {0}.
#[from]
InvalidMessage(hex::Error),
Expand All @@ -320,15 +341,26 @@ impl FromStr for SsiCert {
.split_once('&')
.ok_or(CertParseError::DataMissed)?;
let sig = rest.trim_start_matches("sig=");
let fp = Fingerprint::from_str(fp).map_err(CertParseError::InvalidFingerprint)?;
let (fp, pk) = match fp.len() {
8 => (Fingerprint::from_str(fp).map_err(CertParseError::InvalidFingerprint)?, None),
_ => {
let pk = SsiPub::from_str(fp).map_err(CertParseError::InvalidPub)?;
(pk.fingerprint(), Some(pk))
}
};
let msg = Bytes32::from_str(msg)?;
let sig = SsiSig::from_str(sig)?;
Ok(SsiCert { fp, msg, sig })
Ok(SsiCert { fp, pk, msg, sig })
}
}

impl Display for SsiCert {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if f.alternate() {
if let Some(pk) = self.pk {
return write!(f, "{pk}?msg={msg}&sig={sig}", msg = self.msg, sig = self.sig);
}
}
write!(f, "ssi:{fp}?msg={msg}&sig={sig}", fp = self.fp, msg = self.msg, sig = self.sig)
}
}
1 change: 1 addition & 0 deletions src/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ impl SsiPair {
let sig = self.sk.sign(digest.into());
SsiCert {
fp: self.pk.fingerprint(),
pk: Some(self.pk),
msg: Bytes32::from_byte_array(digest),
sig,
}
Expand Down

0 comments on commit c8da72d

Please sign in to comment.