#![doc = include_str!("../examples/basic.rs")]
#![warn(missing_docs)]
#![deny(rustdoc::broken_intra_doc_links)]
#![no_std]
extern crate alloc;
pub mod consts;
pub use consts::KeyNumber;
mod encoding;
pub use encoding::Codeable;
mod errors;
pub use errors::{Error, FormatError};
mod key;
pub use key::{NewKeyOpts, PrivateKey, PublicKey, Signature};
#[cfg(test)]
pub(crate) mod test_utils;
use ed25519_dalek::{Signer as _, Verifier as _};
impl PrivateKey {
pub fn sign(&self, msg: &[u8]) -> Signature {
let keypair = PrivateKey::from_key_bytes(&self.complete_key)
.expect("invalid private keypair used for signing");
let sig = keypair.sign(msg).to_bytes();
Signature::new(self.keynum, sig)
}
}
impl PublicKey {
pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> {
let current_keynum = self.keynum();
let expected_keynum = signature.keynum;
if expected_keynum != current_keynum {
return Err(Error::MismatchedKey {
expected: expected_keynum,
found: current_keynum,
});
}
let public_key = ed25519_dalek::VerifyingKey::from_bytes(&self.key())
.map_err(|_| Error::BadSignature)?;
let signature = ed25519_dalek::Signature::from_bytes(&signature.signature());
public_key
.verify(msg, &signature)
.map_err(|_| Error::BadSignature)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::StepperRng;
const MSG: &[u8] = b"signify!!!";
#[test]
fn check_signature_roundtrip() {
let mut rng = StepperRng::default();
let secret_key = PrivateKey::generate(&mut rng, NewKeyOpts::NoEncryption).unwrap();
let public_key = secret_key.public();
let signature = secret_key.sign(MSG);
assert_eq!(signature.signer_keynum(), public_key.keynum());
assert!(public_key.verify(MSG, &signature).is_ok());
}
#[test]
fn check_signature_mismatched_keynum() {
let mut rng = StepperRng::default();
let secret_key = PrivateKey::generate(&mut rng, NewKeyOpts::NoEncryption).unwrap();
let public_key = secret_key.public();
let mut signature = secret_key.sign(MSG);
let wrong_keynum = KeyNumber::new([0u8; KeyNumber::LEN]);
signature.keynum = wrong_keynum;
assert_eq!(
public_key.verify(MSG, &signature),
Err(Error::MismatchedKey {
expected: wrong_keynum,
found: public_key.keynum()
})
)
}
#[test]
fn check_malformed_publickey() {
let mut rng = StepperRng::default();
let secret_key = PrivateKey::generate(&mut rng, NewKeyOpts::NoEncryption).unwrap();
let mut public_key = secret_key.public();
let signature = secret_key.sign(MSG);
public_key.key = [
136, 95, 131, 189, 208, 168, 196, 163, 180, 145, 35, 42, 113, 108, 172, 178, 62, 108,
7, 205, 20, 215, 240, 50, 149, 237, 146, 32, 181, 180, 91, 255,
];
assert_eq!(public_key.verify(MSG, &signature), Err(Error::BadSignature));
}
#[test]
fn check_malformed_signature() {
let mut rng = StepperRng::default();
let secret_key = PrivateKey::generate(&mut rng, NewKeyOpts::NoEncryption).unwrap();
let public_key = secret_key.public();
let mut signature = secret_key.sign(MSG);
let real_sig = signature.sig;
signature.sig = [255u8; consts::SIG_LEN];
assert_eq!(public_key.verify(MSG, &signature), Err(Error::BadSignature));
signature.sig = real_sig;
signature.sig[20] = 3;
assert_eq!(public_key.verify(MSG, &signature), Err(Error::BadSignature));
}
}