Skip to content

Commit

Permalink
Custom Serialize and Deserialize for OpCert
Browse files Browse the repository at this point in the history
  • Loading branch information
iquerejeta authored and jpraynaud committed Sep 23, 2022
1 parent 5437505 commit 1764263
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 43 deletions.
6 changes: 3 additions & 3 deletions mithril-common/src/crypto_helper/cardano/key_certification.rs
Expand Up @@ -282,7 +282,7 @@ mod test {
StmInitializerWrapper::setup_new(params, "./test-data/kes1.skey", 0, 10, &mut rng)
.unwrap();

let opcert1 = OpCert::from_file("./test-data/node1.cert")
let opcert1: OpCert = OpCert::from_file("./test-data/node1.cert")
.expect("opcert deserialization should not fail");

let key_registration_1 = key_reg.register(
Expand All @@ -298,12 +298,12 @@ mod test {
StmInitializerWrapper::setup_new(params, "./test-data/kes2.skey", 0, 10, &mut rng)
.unwrap();

let opcert2 = OpCert::from_file("./test-data/node2.cert")
let opcert2: OpCert = OpCert::from_file("./test-data/node2.cert")
.expect("opcert deserialization should not fail");

let key_registration_2 = key_reg.register(
None,
Some(opcert1),
Some(opcert2),
initializer_2.kes_signature,
0,
initializer_2.stm_initializer.verification_key(),
Expand Down
86 changes: 46 additions & 40 deletions mithril-common/src/crypto_helper/cardano/opcert.rs
@@ -1,11 +1,10 @@
use super::FromShelleyFile;

use crate::crypto_helper::cardano::{ParseError, ProtocolRegistrationError};
use crate::crypto_helper::cardano::ProtocolRegistrationError;
use ed25519_dalek::{PublicKey as EdPublicKey, Signature as EdSignature, Verifier};
use kes_summed_ed25519::common::PublicKey as KesPublicKey;
use mithril::RegisterError;
use serde::{Deserialize, Serialize};
use std::path::Path;
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

/// Raw Fields of the operational certificates (without incluiding the cold VK)
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
Expand All @@ -20,13 +19,8 @@ struct RawFields(
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
struct RawOpCert(RawFields, EdPublicKey);

impl FromShelleyFile for RawOpCert {
const TYPE: &'static str = "NodeOperationalCertificate";
const DESCRIPTION: &'static str = "";
}

/// Parsed Operational Certificate
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct OpCert {
pub(crate) kes_vk: KesPublicKey,
pub(crate) issue_number: u64,
Expand All @@ -35,25 +29,32 @@ pub struct OpCert {
pub(crate) cold_vk: EdPublicKey,
}

impl FromShelleyFile for OpCert {
const TYPE: &'static str = "NodeOperationalCertificate";
const DESCRIPTION: &'static str = "";
}

impl OpCert {
/// Parse raw bytes into an Operational Certificate
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, RegisterError> {
let a: RawOpCert =
RawOpCert::from_file(path).map_err(|_| RegisterError::SerializationError)?;
/// Validate a certificate
pub fn validate(&self) -> Result<(), ProtocolRegistrationError> {
let mut msg = [0u8; 48];
msg[..32].copy_from_slice(self.kes_vk.as_bytes());
msg[32..40].copy_from_slice(&self.issue_number.to_be_bytes());
msg[40..48].copy_from_slice(&self.start_kes_period.to_be_bytes());

Ok(Self {
kes_vk: KesPublicKey::from_bytes(&a.0 .0)
.map_err(|_| RegisterError::SerializationError)?,
issue_number: a.0 .1,
start_kes_period: a.0 .2,
cert_sig: EdSignature::from_bytes(&a.0 .3)
.map_err(|_| RegisterError::SerializationError)?,
cold_vk: a.1,
})
if self.cold_vk.verify(&msg, &self.cert_sig).is_ok() {
return Ok(());
}

Err(ProtocolRegistrationError::OpCertInvalid)
}
}

/// Creates a file in the path provided with the OpCert
pub fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), ParseError> {
impl Serialize for OpCert {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let raw_cert = RawOpCert(
RawFields(
self.kes_vk.as_bytes().to_vec(),
Expand All @@ -63,21 +64,26 @@ impl OpCert {
),
self.cold_vk,
);
raw_cert.to_file(path)
}

/// Validate a certificate
pub fn validate(&self) -> Result<(), ProtocolRegistrationError> {
let mut msg = [0u8; 48];
msg[..32].copy_from_slice(self.kes_vk.as_bytes());
msg[32..40].copy_from_slice(&self.issue_number.to_be_bytes());
msg[40..48].copy_from_slice(&self.start_kes_period.to_be_bytes());

if self.cold_vk.verify(&msg, &self.cert_sig).is_ok() {
return Ok(());
}
raw_cert.serialize(serializer)
}
}

Err(ProtocolRegistrationError::OpCertInvalid)
impl<'de> Deserialize<'de> for OpCert {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let raw_cert = RawOpCert::deserialize(deserializer)?;
Ok(Self {
kes_vk: KesPublicKey::from_bytes(&raw_cert.0 .0)
.map_err(|_| Error::custom("KES vk serialisation error"))?,
issue_number: raw_cert.0 .1,
start_kes_period: raw_cert.0 .2,
cert_sig: EdSignature::from_bytes(&raw_cert.0 .3)
.map_err(|_| Error::custom("ed25519 signature serialisation error"))?,
cold_vk: raw_cert.1,
})
}
}

Expand All @@ -87,13 +93,13 @@ mod tests {

#[test]
fn test_vector_op_cert() {
let cert = OpCert::from_file("./test-data/node1.cert").unwrap();
let cert: OpCert = OpCert::from_file("./test-data/node1.cert").unwrap();

assert!(cert.validate().is_ok());

assert!(cert.to_file("./test-data/node_test.cert").is_ok());

let cert_test = OpCert::from_file("./test-data/node_test.cert").unwrap();
let cert_test: OpCert = OpCert::from_file("./test-data/node_test.cert").unwrap();
assert!(cert_test.validate().is_ok());
}
}

0 comments on commit 1764263

Please sign in to comment.