cli_commands/
key_params.rs

1//! CLI parameter wrappers for cryptographic keys with secure parsing and validation.
2
3use sidechain_domain::*;
4use std::convert::Infallible;
5use std::fmt::Display;
6use std::io;
7use std::io::ErrorKind;
8use std::str::FromStr;
9
10/// ECDSA private key wrapper for Partner Chain validator operations.
11#[derive(Clone, Debug)]
12pub struct SidechainSigningKeyParam(pub secp256k1::SecretKey);
13
14impl SidechainSigningKeyParam {
15	/// Derives the corresponding ECDSA public key.
16	pub fn to_pub_key(&self) -> secp256k1::PublicKey {
17		secp256k1::PublicKey::from_secret_key_global(&self.0)
18	}
19}
20
21impl FromStr for SidechainSigningKeyParam {
22	type Err = secp256k1::Error;
23
24	fn from_str(s: &str) -> Result<Self, Self::Err> {
25		let trimmed = s.trim_start_matches("0x");
26		let pair = secp256k1::SecretKey::from_str(trimmed)?;
27		Ok(SidechainSigningKeyParam(pair))
28	}
29}
30
31/// ECDSA public key wrapper for Partner Chain operations.
32#[derive(Clone, Debug)]
33pub struct SidechainPublicKeyParam(pub SidechainPublicKey);
34
35impl Display for SidechainPublicKeyParam {
36	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37		write!(f, "0x{}", hex::encode(&self.0.0))
38	}
39}
40
41impl FromStr for SidechainPublicKeyParam {
42	type Err = secp256k1::Error;
43
44	fn from_str(s: &str) -> Result<Self, Self::Err> {
45		let trimmed = s.trim_start_matches("0x");
46		let pk = secp256k1::PublicKey::from_str(trimmed)?;
47		Ok(SidechainPublicKeyParam(SidechainPublicKey(pk.serialize().to_vec())))
48	}
49}
50
51/// Generic string wrapper for public keys without cryptographic validation.
52#[derive(Clone, Debug)]
53pub struct PlainPublicKeyParam(pub String);
54
55impl Display for PlainPublicKeyParam {
56	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57		write!(f, "{}", self.0)
58	}
59}
60
61impl FromStr for PlainPublicKeyParam {
62	type Err = Infallible;
63
64	fn from_str(s: &str) -> Result<Self, Self::Err> {
65		Ok(PlainPublicKeyParam(s.to_string()))
66	}
67}
68
69/// Error types that can occur during Ed25519 signing key parsing.
70#[derive(Debug, thiserror::Error)]
71pub enum Ed25519SigningKeyError {
72	/// Hexadecimal decoding error
73	#[error("{0}")]
74	HexError(#[from] hex::FromHexError),
75	/// Ed25519 key validation error
76	#[error("{0}")]
77	Ed25519Error(#[from] ed25519_zebra::Error),
78}
79
80impl From<Ed25519SigningKeyError> for io::Error {
81	fn from(value: Ed25519SigningKeyError) -> Self {
82		io::Error::new(ErrorKind::InvalidInput, value)
83	}
84}
85
86/// Parses hex string into Ed25519 signing key with validation.
87pub(crate) fn parse_zebra_signing_key(
88	s: &str,
89) -> Result<ed25519_zebra::SigningKey, Ed25519SigningKeyError> {
90	let trimmed = s.trim_start_matches("0x");
91	Ok(ed25519_zebra::SigningKey::try_from(hex::decode(trimmed)?.as_slice())?)
92}
93
94/// Ed25519 private key wrapper for Cardano stake pool operations.
95#[derive(Clone, Debug)]
96pub struct StakePoolSigningKeyParam(pub ed25519_zebra::SigningKey);
97
98impl FromStr for StakePoolSigningKeyParam {
99	type Err = Ed25519SigningKeyError;
100
101	fn from_str(s: &str) -> Result<Self, Self::Err> {
102		Ok(Self(parse_zebra_signing_key(s)?))
103	}
104}
105
106impl From<[u8; 32]> for StakePoolSigningKeyParam {
107	/// Creates signing key from 32-byte array.
108	fn from(key: [u8; 32]) -> Self {
109		Self(ed25519_zebra::SigningKey::from(key))
110	}
111}
112
113impl StakePoolSigningKeyParam {
114	/// Derives the corresponding public key.
115	pub fn vkey(&self) -> StakePoolPublicKey {
116		StakePoolPublicKey(ed25519_zebra::VerificationKey::from(&self.0).into())
117	}
118}
119
120/// Ed25519 private key wrapper for Cardano staking operations.
121#[derive(Clone, Debug)]
122pub struct StakeSigningKeyParam(pub ed25519_zebra::SigningKey);
123
124impl FromStr for StakeSigningKeyParam {
125	type Err = Ed25519SigningKeyError;
126
127	fn from_str(s: &str) -> Result<Self, Self::Err> {
128		Ok(Self(parse_zebra_signing_key(s)?))
129	}
130}
131
132impl StakeSigningKeyParam {
133	/// Derives the corresponding public key.
134	pub fn vkey(&self) -> StakePublicKey {
135		StakePublicKey(ed25519_zebra::VerificationKey::from(&self.0).into())
136	}
137}
138
139/// ECDSA private key wrapper for cross-chain operations.
140#[derive(Clone, Debug)]
141pub struct CrossChainSigningKeyParam(pub k256::SecretKey);
142
143impl FromStr for CrossChainSigningKeyParam {
144	type Err = anyhow::Error;
145
146	fn from_str(s: &str) -> Result<Self, Self::Err> {
147		Ok(Self(k256::SecretKey::from_slice(&hex::decode(s)?)?))
148	}
149}
150
151impl CrossChainSigningKeyParam {
152	/// Derives the corresponding ECDSA public key.
153	pub fn vkey(&self) -> CrossChainPublicKey {
154		CrossChainPublicKey(self.0.public_key().to_sec1_bytes().to_vec())
155	}
156}