pub(crate) mod arti;
use std::result::Result as StdResult;
use derive_more::From;
use rand::{CryptoRng, RngCore};
use ssh_key::private::{Ed25519Keypair, Ed25519PrivateKey, KeypairData, OpaqueKeypair};
use ssh_key::public::{Ed25519PublicKey, KeyData, OpaquePublicKey};
use ssh_key::{Algorithm, AlgorithmName};
use tor_error::internal;
use tor_hscrypto::pk::{
HsBlindIdKey, HsBlindIdKeypair, HsClientDescEncKeypair, HsClientIntroAuthKeypair,
HsDescSigningKeypair, HsIdKey, HsIdKeypair,
};
use tor_llcrypto::pk::{curve25519, ed25519};
use crate::key_type::ssh::{ED25519_EXPANDED_ALGORITHM_NAME, X25519_ALGORITHM_NAME};
use crate::key_type::KeyType;
use crate::{KeyPath, KeySpecifier, KeystoreId, Result};
use downcast_rs::{impl_downcast, Downcast};
pub type ErasedKey = Box<dyn EncodableKey>;
pub trait KeygenRng: RngCore + CryptoRng {}
impl<T> KeygenRng for T where T: RngCore + CryptoRng {}
pub trait Keystore: Send + Sync + 'static {
fn id(&self) -> &KeystoreId;
fn contains(&self, key_spec: &dyn KeySpecifier, key_type: &KeyType) -> Result<bool>;
fn get(&self, key_spec: &dyn KeySpecifier, key_type: &KeyType) -> Result<Option<ErasedKey>>;
fn insert(
&self,
key: &dyn EncodableKey,
key_spec: &dyn KeySpecifier,
key_type: &KeyType,
) -> Result<()>;
fn remove(&self, key_spec: &dyn KeySpecifier, key_type: &KeyType) -> Result<Option<()>>;
fn list(&self) -> Result<Vec<(KeyPath, KeyType)>>;
}
pub trait Keygen {
fn generate(rng: &mut dyn KeygenRng) -> Result<Self>
where
Self: Sized;
}
#[derive(From, Clone, Debug)]
#[non_exhaustive]
pub enum SshKeyData {
Public(KeyData),
Private(KeypairData),
}
impl SshKeyData {
pub fn into_public(self) -> StdResult<KeyData, Self> {
match self {
SshKeyData::Public(key_data) => Ok(key_data),
SshKeyData::Private(_) => Err(self),
}
}
pub fn into_private(self) -> StdResult<KeypairData, Self> {
match self {
SshKeyData::Public(_) => Err(self),
SshKeyData::Private(keypair_data) => Ok(keypair_data),
}
}
}
pub trait EncodableKey: Downcast {
fn key_type() -> KeyType
where
Self: Sized;
fn as_ssh_key_data(&self) -> Result<SshKeyData>;
}
impl_downcast!(EncodableKey);
impl Keygen for curve25519::StaticKeypair {
fn generate(rng: &mut dyn KeygenRng) -> Result<Self>
where
Self: Sized,
{
let secret = curve25519::StaticSecret::new(rng);
let public = curve25519::PublicKey::from(&secret);
Ok(curve25519::StaticKeypair { secret, public })
}
}
impl EncodableKey for curve25519::StaticKeypair {
fn key_type() -> KeyType
where
Self: Sized,
{
KeyType::X25519StaticKeypair
}
fn as_ssh_key_data(&self) -> Result<SshKeyData> {
let algorithm_name = AlgorithmName::new(X25519_ALGORITHM_NAME)
.map_err(|_| internal!("invalid algorithm name"))?;
let ssh_public = OpaquePublicKey::new(
self.public.to_bytes().to_vec(),
Algorithm::Other(algorithm_name),
);
let keypair = OpaqueKeypair::new(self.secret.to_bytes().to_vec(), ssh_public);
Ok(ssh_key::private::KeypairData::Other(keypair).into())
}
}
impl EncodableKey for curve25519::PublicKey {
fn key_type() -> KeyType
where
Self: Sized,
{
KeyType::X25519PublicKey
}
fn as_ssh_key_data(&self) -> Result<SshKeyData> {
let algorithm_name = AlgorithmName::new(X25519_ALGORITHM_NAME)
.map_err(|_| internal!("invalid algorithm name"))?;
let ssh_public =
OpaquePublicKey::new(self.to_bytes().to_vec(), Algorithm::Other(algorithm_name));
Ok(KeyData::Other(ssh_public).into())
}
}
impl Keygen for ed25519::Keypair {
fn generate(rng: &mut dyn KeygenRng) -> Result<Self>
where
Self: Sized,
{
use tor_llcrypto::util::rand_compat::RngCompatExt;
Ok(ed25519::Keypair::generate(&mut rng.rng_compat()))
}
}
impl EncodableKey for ed25519::Keypair {
fn key_type() -> KeyType
where
Self: Sized,
{
KeyType::Ed25519Keypair
}
fn as_ssh_key_data(&self) -> Result<SshKeyData> {
let keypair = Ed25519Keypair {
public: Ed25519PublicKey(self.public.to_bytes()),
private: Ed25519PrivateKey::from_bytes(self.secret.as_bytes()),
};
Ok(KeypairData::Ed25519(keypair).into())
}
}
impl EncodableKey for ed25519::PublicKey {
fn key_type() -> KeyType
where
Self: Sized,
{
KeyType::Ed25519PublicKey
}
fn as_ssh_key_data(&self) -> Result<SshKeyData> {
let key_data = Ed25519PublicKey(self.to_bytes());
Ok(ssh_key::public::KeyData::Ed25519(key_data).into())
}
}
impl Keygen for ed25519::ExpandedKeypair {
fn generate(rng: &mut dyn KeygenRng) -> Result<Self>
where
Self: Sized,
{
let keypair = <ed25519::Keypair as Keygen>::generate(rng)?;
Ok((&keypair).into())
}
}
impl EncodableKey for ed25519::ExpandedKeypair {
fn key_type() -> KeyType
where
Self: Sized,
{
KeyType::Ed25519ExpandedKeypair
}
fn as_ssh_key_data(&self) -> Result<SshKeyData> {
let algorithm_name = AlgorithmName::new(ED25519_EXPANDED_ALGORITHM_NAME)
.map_err(|_| internal!("invalid algorithm name"))?;
let ssh_public = OpaquePublicKey::new(
self.public.to_bytes().to_vec(),
Algorithm::Other(algorithm_name),
);
let keypair = OpaqueKeypair::new(self.secret.to_bytes().to_vec(), ssh_public);
Ok(ssh_key::private::KeypairData::Other(keypair).into())
}
}
pub trait ToEncodableKey {
type Key: EncodableKey + 'static;
fn to_encodable_key(self) -> Self::Key;
fn from_encodable_key(key: Self::Key) -> Self;
}
impl ToEncodableKey for HsClientDescEncKeypair {
type Key = curve25519::StaticKeypair;
fn to_encodable_key(self) -> Self::Key {
self.into()
}
fn from_encodable_key(key: Self::Key) -> Self {
HsClientDescEncKeypair::new(key.public.into(), key.secret.into())
}
}
impl ToEncodableKey for HsClientIntroAuthKeypair {
type Key = ed25519::Keypair;
fn to_encodable_key(self) -> Self::Key {
self.into()
}
fn from_encodable_key(key: Self::Key) -> Self {
HsClientIntroAuthKeypair::from(key)
}
}
impl ToEncodableKey for HsBlindIdKeypair {
type Key = ed25519::ExpandedKeypair;
fn to_encodable_key(self) -> Self::Key {
self.into()
}
fn from_encodable_key(key: Self::Key) -> Self {
HsBlindIdKeypair::from(key)
}
}
impl ToEncodableKey for HsBlindIdKey {
type Key = ed25519::PublicKey;
fn to_encodable_key(self) -> Self::Key {
self.into()
}
fn from_encodable_key(key: Self::Key) -> Self {
HsBlindIdKey::from(key)
}
}
impl ToEncodableKey for HsIdKeypair {
type Key = ed25519::ExpandedKeypair;
fn to_encodable_key(self) -> Self::Key {
self.into()
}
fn from_encodable_key(key: Self::Key) -> Self {
HsIdKeypair::from(key)
}
}
impl ToEncodableKey for HsIdKey {
type Key = ed25519::PublicKey;
fn to_encodable_key(self) -> Self::Key {
self.into()
}
fn from_encodable_key(key: Self::Key) -> Self {
HsIdKey::from(key)
}
}
impl ToEncodableKey for HsDescSigningKeypair {
type Key = ed25519::Keypair;
fn to_encodable_key(self) -> Self::Key {
self.into()
}
fn from_encodable_key(key: Self::Key) -> Self {
HsDescSigningKeypair::from(key)
}
}