Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(crypto): CRP-2596 create VetKdProtocol trait #2569

Merged
merged 11 commits into from
Nov 18, 2024
3 changes: 3 additions & 0 deletions rs/interfaces/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ pub use sign::ThresholdSigner;

pub use sign::canister_threshold_sig::*;

mod vetkd;
pub use vetkd::*;

use ic_crypto_interfaces_sig_verification::BasicSigVerifierByPublicKey;
use ic_types::consensus::{
certification::CertificationContent,
Expand Down
33 changes: 33 additions & 0 deletions rs/interfaces/src/crypto/vetkd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use ic_types::crypto::vetkd::{
VedKdKeyShareCreationError, VetKdArgs, VetKdEncryptedKey, VetKdEncryptedKeyShare,
VetKdKeyShareCombinationError, VetKdKeyShareVerificationError, VetKdKeyVerificationError,
};
use ic_types::NodeId;
use std::collections::BTreeMap;

pub trait VetKdProtocol {
#[allow(clippy::result_large_err)]
fn create_encrypted_key_share(
&self,
args: VetKdArgs,
eichhorl marked this conversation as resolved.
Show resolved Hide resolved
) -> Result<VetKdEncryptedKeyShare, VedKdKeyShareCreationError>;

fn verify_encrypted_key_share(
&self,
signer: NodeId,
key_share: &VetKdEncryptedKeyShare,
args: &VetKdArgs,
) -> Result<(), VetKdKeyShareVerificationError>;

fn combine_encrypted_key_shares(
&self,
shares: &BTreeMap<NodeId, VetKdEncryptedKeyShare>,
args: &VetKdArgs,
) -> Result<VetKdEncryptedKey, VetKdKeyShareCombinationError>;

fn verify_encrypted_key(
&self,
key: &VetKdEncryptedKey,
args: &VetKdArgs,
) -> Result<(), VetKdKeyVerificationError>;
}
46 changes: 45 additions & 1 deletion rs/test_utilities/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use ic_interfaces::crypto::{
IDkgDealingEncryptionKeyRotationError, IDkgKeyRotationResult, IDkgProtocol, KeyManager,
LoadTranscriptResult, NiDkgAlgorithm, ThresholdEcdsaSigVerifier, ThresholdEcdsaSigner,
ThresholdSchnorrSigVerifier, ThresholdSchnorrSigner, ThresholdSigVerifier,
ThresholdSigVerifierByPublicKey, ThresholdSigner,
ThresholdSigVerifierByPublicKey, ThresholdSigner, VetKdProtocol,
};
use ic_interfaces::crypto::{MultiSigVerifier, MultiSigner};
use ic_interfaces_registry::RegistryClient;
Expand Down Expand Up @@ -517,6 +517,50 @@ impl ThresholdSchnorrSigVerifier for CryptoReturningOk {
}
}

use ic_types::crypto::vetkd::{
VedKdKeyShareCreationError, VetKdArgs, VetKdEncryptedKey, VetKdEncryptedKeyShare,
VetKdKeyShareCombinationError, VetKdKeyShareVerificationError, VetKdKeyVerificationError,
};

impl VetKdProtocol for CryptoReturningOk {
fn create_encrypted_key_share(
&self,
_args: VetKdArgs,
) -> Result<VetKdEncryptedKeyShare, VedKdKeyShareCreationError> {
Ok(VetKdEncryptedKeyShare {
encrypted_key_share: vec![],
node_signature: vec![],
})
}

fn verify_encrypted_key_share(
&self,
_signer: NodeId,
_key_share: &VetKdEncryptedKeyShare,
_args: &VetKdArgs,
) -> Result<(), VetKdKeyShareVerificationError> {
Ok(())
}

fn combine_encrypted_key_shares(
&self,
_shares: &BTreeMap<NodeId, VetKdEncryptedKeyShare>,
_args: &VetKdArgs,
) -> Result<VetKdEncryptedKey, VetKdKeyShareCombinationError> {
Ok(VetKdEncryptedKey {
encrypted_key: vec![],
})
}

fn verify_encrypted_key(
&self,
_key: &VetKdEncryptedKey,
_args: &VetKdArgs,
) -> Result<(), VetKdKeyVerificationError> {
Ok(())
}
}

pub fn mock_random_number_generator() -> Box<dyn RngCore> {
Box::new(StdRng::from_seed([0u8; 32]))
}
30 changes: 30 additions & 0 deletions rs/types/types/src/crypto.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Defines crypto component types.
pub mod canister_threshold_sig;

pub mod vetkd;

mod hash;

pub use hash::crypto_hash;
Expand Down Expand Up @@ -36,6 +38,34 @@ use strum_macros::{Display, EnumIter};
#[cfg(test)]
mod tests;

macro_rules! impl_display_using_debug {
($t:ty) => {
impl std::fmt::Display for $t {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
}
}
};
}
pub(crate) use impl_display_using_debug;

pub struct HexEncoding<'a> {
pub bytes: &'a [u8],
}

impl fmt::Debug for HexEncoding<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0x{}", hex::encode(self.bytes))?;
Ok(())
}
}

impl<'a> From<&'a Vec<u8>> for HexEncoding<'a> {
fn from(bytes: &'a Vec<u8>) -> Self {
HexEncoding { bytes }
}
}

/// A cryptographic hash.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
pub struct CryptoHash(#[serde(with = "serde_bytes")] pub Vec<u8>);
Expand Down
2 changes: 1 addition & 1 deletion rs/types/types/src/crypto/canister_threshold_sig.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Defines canister threshold signature types.
use crate::crypto::canister_threshold_sig::error::impl_display_using_debug;
use crate::crypto::canister_threshold_sig::idkg::{
IDkgMaskedTranscriptOrigin, IDkgReceivers, IDkgTranscript, IDkgTranscriptType,
IDkgUnmaskedTranscriptOrigin,
};
use crate::crypto::impl_display_using_debug;
use crate::crypto::AlgorithmId;
use crate::{NumberOfNodes, Randomness};
use core::fmt;
Expand Down
13 changes: 1 addition & 12 deletions rs/types/types/src/crypto/canister_threshold_sig/error.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
//! Defines errors that may occur in the context of canister threshold
//! signatures.
use crate::crypto::impl_display_using_debug;
use crate::crypto::{AlgorithmId, CryptoError};
use crate::registry::RegistryClientError;
use crate::{Height, NodeId, RegistryVersion};
use ic_protobuf::proxy::ProxyDecodeError;
use ic_protobuf::registry::crypto::v1::AlgorithmId as AlgorithmIdProto;
use serde::{Deserialize, Serialize};

macro_rules! impl_display_using_debug {
($t:ty) => {
impl std::fmt::Display for $t {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
};
}

pub(crate) use impl_display_using_debug;

#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize)]
pub enum IDkgTranscriptIdError {
DecreasedBlockHeight {
Expand Down
2 changes: 1 addition & 1 deletion rs/types/types/src/crypto/canister_threshold_sig/idkg.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Defines interactive distributed key generation (IDkg) types.
use crate::consensus::get_faults_tolerated;
use crate::crypto::canister_threshold_sig::error::impl_display_using_debug;
use crate::crypto::canister_threshold_sig::error::{
IDkgParamsValidationError, IDkgTranscriptIdError, InitialIDkgDealingsValidationError,
};
use crate::crypto::impl_display_using_debug;
use crate::crypto::{AlgorithmId, CryptoHashOf, Signed, SignedBytesWithoutDomainSeparator};
use crate::signature::{BasicSignature, BasicSignatureBatch};
use crate::{Height, NodeId, NumberOfNodes, RegistryVersion};
Expand Down
93 changes: 93 additions & 0 deletions rs/types/types/src/crypto/vetkd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use crate::crypto::canister_threshold_sig::ExtendedDerivationPath;
use crate::crypto::impl_display_using_debug;
use crate::crypto::threshold_sig::errors::threshold_sig_data_not_found_error::ThresholdSigDataNotFoundError;
use crate::crypto::threshold_sig::ni_dkg::NiDkgId;
use crate::crypto::HexEncoding;
use crate::NodeId;
use serde::{Deserialize, Serialize};
use std::fmt;

#[cfg(test)]
mod test;

#[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
pub struct VetKdArgs {
pub ni_dkg_id: NiDkgId,
pub derivation_path: ExtendedDerivationPath,
#[serde(with = "serde_bytes")]
pub derivation_id: Vec<u8>,
#[serde(with = "serde_bytes")]
pub encryption_key: Vec<u8>,
}

impl fmt::Debug for VetKdArgs {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("VetKdArgs")
.field("ni_dkg_id", &self.ni_dkg_id)
.field("derivation_path", &self.derivation_path)
.field("derivation_id", &HexEncoding::from(&self.derivation_id))
.field("encryption_key", &HexEncoding::from(&self.encryption_key))
.finish()
}
}
impl_display_using_debug!(VetKdArgs);

#[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
pub struct VetKdEncryptedKeyShare {
#[serde(with = "serde_bytes")]
pub encrypted_key_share: Vec<u8>,
/// Node's Ed25519 signature for optimized variant
#[serde(with = "serde_bytes")]
pub node_signature: Vec<u8>,
}

impl std::fmt::Debug for VetKdEncryptedKeyShare {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("VetKdEncryptedKeyShare")
.field(
"encrypted_key_share",
&HexEncoding::from(&self.encrypted_key_share),
)
.field("node_signature", &HexEncoding::from(&self.node_signature))
.finish()
}
}
impl_display_using_debug!(VetKdEncryptedKeyShare);

#[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
pub struct VetKdEncryptedKey {
#[serde(with = "serde_bytes")]
pub encrypted_key: Vec<u8>,
}

impl std::fmt::Debug for VetKdEncryptedKey {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("VetKdEncryptedKey")
.field("encrypted_key", &HexEncoding::from(&self.encrypted_key))
.finish()
}
}
impl_display_using_debug!(VetKdEncryptedKey);

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum VedKdKeyShareCreationError {
ThresholdSigDataNotFound(ThresholdSigDataNotFoundError),
SecretKeyNotFound { dkg_id: NiDkgId, key_id: String },
KeyIdInstantiationError(String),
TransientInternalError(String),
}
impl_display_using_debug!(VedKdKeyShareCreationError);

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum VetKdKeyShareVerificationError {}
impl_display_using_debug!(VetKdKeyShareVerificationError);

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum VetKdKeyShareCombinationError {
InvalidShares(Vec<NodeId>),
}
impl_display_using_debug!(VetKdKeyShareCombinationError);

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum VetKdKeyVerificationError {}
impl_display_using_debug!(VetKdKeyVerificationError);
71 changes: 71 additions & 0 deletions rs/types/types/src/crypto/vetkd/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use crate::crypto::canister_threshold_sig::ExtendedDerivationPath;
use crate::crypto::threshold_sig::ni_dkg::{NiDkgId, NiDkgTag, NiDkgTargetId, NiDkgTargetSubnet};
use crate::crypto::vetkd::{VetKdArgs, VetKdEncryptedKey, VetKdEncryptedKeyShare};
use crate::Height;
use ic_base_types::PrincipalId;
use ic_base_types::SubnetId;

mod display_and_debug {
use super::*;

#[test]
fn should_correctly_print_vetkd_args() {
let input = VetKdArgs {
ni_dkg_id: NiDkgId {
start_block_height: Height::new(7),
dealer_subnet: SubnetId::from(PrincipalId::new_subnet_test_id(42)),
dkg_tag: NiDkgTag::HighThreshold,
target_subnet: NiDkgTargetSubnet::Remote(NiDkgTargetId::new(
[42; NiDkgTargetId::SIZE],
)),
},
derivation_path: ExtendedDerivationPath {
caller: PrincipalId::new_node_test_id(17),
derivation_path: vec![b"dp".to_vec()],
},
derivation_id: b"did".to_vec(),
encryption_key: b"ek".to_vec(),
};
let output = "VetKdArgs { \
ni_dkg_id: NiDkgId { start_block_height: 7, dealer_subnet: ot5wk-sbkaa-aaaaa-aaaap-yai, dkg_tag: HighThreshold, target_subnet: Remote(0x2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a) }, \
derivation_path: ExtendedDerivationPath { caller: 7xzs3-rqraa-aaaaa-aaaap-2ai, \
derivation_path: { 6470 } }, \
derivation_id: 0x646964, \
encryption_key: 0x656b \
}"
.to_string();

assert_eq!(output, format!("{:?}", input));
assert_eq!(output, format!("{}", input));
}

#[test]
fn should_correctly_print_vetkd_encrypted_key_share() {
let input = VetKdEncryptedKeyShare {
encrypted_key_share: b"eks".to_vec(),
node_signature: b"ns".to_vec(),
};
let output = "VetKdEncryptedKeyShare { \
encrypted_key_share: 0x656b73, \
node_signature: 0x6e73 \
}"
.to_string();

assert_eq!(output, format!("{:?}", input));
assert_eq!(output, format!("{}", input));
}

#[test]
fn should_correctly_print_vetkd_encrypted_key() {
let input = VetKdEncryptedKey {
encrypted_key: b"ek".to_vec(),
};
let output = "VetKdEncryptedKey { \
encrypted_key: 0x656b \
}"
.to_string();

assert_eq!(output, format!("{:?}", input));
assert_eq!(output, format!("{}", input));
}
}