use ed25519_dalek::{ExpandedSecretKey, PublicKey, SecretKey, SignatureError};
use rand::thread_rng;
use crate::onion::OnionAddressV3;
use crate::utils::BASE32_ALPHA;
pub const TORV3_PUBLIC_KEY_LENGTH: usize = ed25519_dalek::PUBLIC_KEY_LENGTH;
pub const TORV3_SECRET_KEY_LENGTH: usize = ed25519_dalek::EXPANDED_SECRET_KEY_LENGTH;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct TorPublicKeyV3(pub(crate) [u8; TORV3_PUBLIC_KEY_LENGTH]);
impl TorPublicKeyV3 {
#[inline]
pub fn to_bytes(&self) -> [u8; TORV3_PUBLIC_KEY_LENGTH] {
self.0
}
#[inline]
pub fn as_bytes(&self) -> &[u8; TORV3_PUBLIC_KEY_LENGTH] {
&self.0
}
#[inline]
pub fn from_bytes(bytes: &[u8; TORV3_PUBLIC_KEY_LENGTH]) -> Result<TorPublicKeyV3, SignatureError> {
PublicKey::from_bytes(bytes).map(|_pk| TorPublicKeyV3(bytes.clone()))
}
pub fn get_onion_address(&self) -> OnionAddressV3 {
OnionAddressV3::from(self)
}
}
impl std::fmt::Debug for TorPublicKeyV3 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "TorPublicKey({})", base32::encode(BASE32_ALPHA, &self.0))
}
}
impl std::fmt::Display for TorPublicKeyV3 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "TorPublicKey({})", base32::encode(BASE32_ALPHA, &self.0))
}
}
#[derive(Clone)]
#[repr(transparent)]
#[derive(From, Into)]
pub struct TorSecretKeyV3([u8; TORV3_SECRET_KEY_LENGTH]);
impl Eq for TorSecretKeyV3 {}
impl PartialEq for TorSecretKeyV3 {
fn eq(&self, other: &Self) -> bool {
self.0.iter().zip(other.0.iter()).all(|(b1, b2)| *b1 == *b2)
}
}
impl TorSecretKeyV3 {
pub(crate) fn as_tor_proto_encoded(&self) -> String {
base64::encode(&self.0[..])
}
pub fn generate() -> Self {
let sk: SecretKey = SecretKey::generate(&mut thread_rng());
let esk = ExpandedSecretKey::from(&sk);
TorSecretKeyV3(esk.to_bytes())
}
pub fn public(&self) -> TorPublicKeyV3 {
let esk = ExpandedSecretKey::from_bytes(&self.0).expect("Invalid secret key contained");
TorPublicKeyV3(PublicKey::from(&esk).to_bytes())
}
pub fn as_bytes(&self) -> [u8; 64] {
self.0.clone()
}
pub fn into_bytes(self) -> [u8; 64] {
self.0
}
}
impl std::fmt::Display for TorSecretKeyV3 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "TorSecretKey(****)")
}
}
impl std::fmt::Debug for TorSecretKeyV3 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "TorSecretKey(****)")
}
}