use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
use rand_core::OsRng;
use zeroize::Zeroizing;
use crate::CoreError;
pub const HANDSHAKE_AUTH_NONE: u8 = 0;
pub const HANDSHAKE_AUTH_ED25519: u8 = 1;
#[derive(Clone, Eq, PartialEq)]
pub struct IdentityKeyPair {
secret_key: Zeroizing<[u8; 32]>,
public_key: [u8; 32],
}
impl core::fmt::Debug for IdentityKeyPair {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("IdentityKeyPair")
.field("public_key", &self.public_key)
.finish()
}
}
impl IdentityKeyPair {
pub fn generate() -> Self {
let signing_key = SigningKey::generate(&mut OsRng);
Self::from_secret_key_bytes(signing_key.to_bytes())
}
pub fn from_secret_key_bytes(secret_key: [u8; 32]) -> Self {
let signing_key = SigningKey::from_bytes(&secret_key);
let public_key = signing_key.verifying_key().to_bytes();
Self {
secret_key: Zeroizing::new(secret_key),
public_key,
}
}
pub fn public_key(&self) -> [u8; 32] {
self.public_key
}
pub fn secret_key_bytes(&self) -> [u8; 32] {
*self.secret_key
}
pub fn sign(&self, message: &[u8]) -> [u8; 64] {
let signing_key = SigningKey::from_bytes(&self.secret_key);
signing_key.sign(message).to_bytes()
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct PeerIdentity {
pub public_key: [u8; 32],
}
impl PeerIdentity {
pub fn new(public_key: [u8; 32]) -> Self {
Self { public_key }
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HandshakeAuth {
pub identity_public_key: [u8; 32],
pub signature: [u8; 64],
}
impl HandshakeAuth {
pub fn sign(identity: &IdentityKeyPair, message: &[u8]) -> Self {
Self {
identity_public_key: identity.public_key(),
signature: identity.sign(message),
}
}
pub fn verify(&self, message: &[u8]) -> Result<(), CoreError> {
let verifying_key = VerifyingKey::from_bytes(&self.identity_public_key)
.map_err(|_| CoreError::InvalidPeerAuthentication)?;
let signature = Signature::from_bytes(&self.signature);
verifying_key
.verify(message, &signature)
.map_err(|_| CoreError::InvalidPeerAuthentication)
}
pub const fn encoded_len() -> usize {
32 + 64
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct SessionAuthConfig {
local_identity: Option<IdentityKeyPair>,
peer_identity: Option<PeerIdentity>,
require_peer_authentication: bool,
}
impl SessionAuthConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_local_identity(mut self, identity: IdentityKeyPair) -> Self {
self.local_identity = Some(identity);
self
}
pub fn with_peer_identity(mut self, identity: PeerIdentity) -> Self {
self.peer_identity = Some(identity);
self
}
pub fn require_peer_authentication(mut self, require: bool) -> Self {
self.require_peer_authentication = require;
self
}
pub fn local_identity(&self) -> Option<&IdentityKeyPair> {
self.local_identity.as_ref()
}
pub fn peer_identity(&self) -> Option<PeerIdentity> {
self.peer_identity
}
pub fn requires_peer_authentication(&self) -> bool {
self.require_peer_authentication
}
}