pub mod private_key;
pub mod public_key;
pub mod signature;
use std::io::{self, Error, ErrorKind};
use crate::codec::serde::hex_0x_bytes::Hex0xBytes;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
#[serde_as]
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
pub struct ProofOfPossession {
#[serde(rename = "publicKey")]
#[serde_as(as = "Hex0xBytes")]
pub public_key: Vec<u8>,
#[serde(rename = "proofOfPossession")]
#[serde_as(as = "Hex0xBytes")]
pub proof_of_possession: Vec<u8>,
#[serde(skip)]
pub pubkey: Option<public_key::Key>,
}
impl Default for ProofOfPossession {
fn default() -> Self {
Self::default()
}
}
impl ProofOfPossession {
pub fn default() -> Self {
Self {
public_key: Vec::new(),
proof_of_possession: Vec::new(),
pubkey: None,
}
}
}
impl ProofOfPossession {
pub fn new(public_key: &[u8], proof_of_possession: &[u8]) -> io::Result<Self> {
let pubkey = public_key::Key::from_bytes(public_key)?;
let sig = signature::Sig::from_bytes(proof_of_possession)?;
if !pubkey.verify_proof_of_possession(public_key, &sig) {
return Err(Error::new(
ErrorKind::Other,
"failed verify_proof_of_possession",
));
}
Ok(Self {
public_key: public_key.to_vec(),
proof_of_possession: proof_of_possession.to_vec(),
pubkey: Some(pubkey),
})
}
pub fn verify(&self) -> io::Result<bool> {
let pubkey = public_key::Key::from_bytes(&self.public_key)?;
let pubkey_bytes = pubkey.to_compressed_bytes();
let sig = signature::Sig::from_bytes(&self.proof_of_possession)?;
Ok(pubkey.verify_proof_of_possession(&pubkey_bytes, &sig))
}
pub fn load_pubkey(&self) -> io::Result<public_key::Key> {
let pubkey = public_key::Key::from_bytes(&self.public_key)?;
Ok(pubkey)
}
}
#[test]
fn test_proof_of_possession() {
let _ = env_logger::builder()
.filter_level(log::LevelFilter::Info)
.is_test(true)
.try_init();
let sk = private_key::Key::generate().unwrap();
let pubkey = sk.to_public_key();
let msg = random_manager::secure_bytes(50).unwrap();
let sig = sk.sign(&msg);
assert!(sig.verify(&msg, &pubkey));
assert!(!sig.verify_proof_of_possession(&msg, &pubkey));
let sig_pop = sk.sign_proof_of_possession(&msg);
assert!(!sig_pop.verify(&msg, &pubkey));
assert!(sig_pop.verify_proof_of_possession(&msg, &pubkey));
let b = sk.to_bytes();
let sk2 = private_key::Key::from_bytes(&b).unwrap();
assert_eq!(sk.to_bytes(), sk2.to_bytes());
let key_path = random_manager::tmp_path(10, None).unwrap();
let generated_key = private_key::Key::generate_to_file(&key_path).unwrap();
let loaded_key = private_key::Key::from_file(&key_path).unwrap();
assert_eq!(generated_key.to_bytes(), loaded_key.to_bytes());
let (loaded_key_2, generated) = private_key::Key::load_or_generate(&key_path).unwrap();
assert!(!generated);
assert_eq!(loaded_key.to_bytes(), loaded_key_2.to_bytes());
std::fs::remove_file(&key_path).unwrap();
let pop = sk.to_proof_of_possession();
log::info!(
"proof-of-possession: {}",
serde_json::to_string_pretty(&pop).unwrap()
);
assert!(pop.verify().unwrap());
let pop =
ProofOfPossession::new(&pubkey.to_compressed_bytes(), &pop.proof_of_possession).unwrap();
assert!(pop.verify().unwrap());
assert_eq!(pop.public_key, pubkey.to_compressed_bytes());
assert_eq!(
pop.pubkey.unwrap().to_compressed_bytes(),
pubkey.to_compressed_bytes()
);
}