Update PrivateKey -> X25519PrivateKey

This commit is contained in:
Jazz Turner-Baggs 2026-02-12 16:25:09 -08:00
parent 85ef7631d2
commit 99264d2f66
No known key found for this signature in database
11 changed files with 75 additions and 67 deletions

View File

@ -221,14 +221,14 @@ impl Debug for PrivateV1Convo {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use x25519_dalek::StaticSecret; use crypto::X25519PrivateKey;
use super::*; use super::*;
#[test] #[test]
fn test_encrypt_roundtrip() { fn test_encrypt_roundtrip() {
let saro = StaticSecret::random(); let saro = X25519PrivateKey::random();
let raya = StaticSecret::random(); let raya = X25519PrivateKey::random();
let pub_raya = X25519PublicKey::from(&raya); let pub_raya = X25519PublicKey::from(&raya);

View File

@ -1,5 +1,4 @@
pub use crypto::X25519PublicKey; pub use crypto::{X25519PrivateKey, X25519PublicKey};
pub use x25519_dalek::StaticSecret;
use prost::bytes::Bytes; use prost::bytes::Bytes;

View File

@ -1,9 +1,9 @@
use std::fmt; use std::fmt;
use crate::crypto::{StaticSecret, X25519PublicKey}; use crate::crypto::{X25519PrivateKey, X25519PublicKey};
pub struct Identity { pub struct Identity {
secret: StaticSecret, secret: X25519PrivateKey,
} }
impl fmt::Debug for Identity { impl fmt::Debug for Identity {
@ -18,7 +18,7 @@ impl fmt::Debug for Identity {
impl Identity { impl Identity {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
secret: StaticSecret::random(), secret: X25519PrivateKey::random(),
} }
} }
@ -26,7 +26,7 @@ impl Identity {
X25519PublicKey::from(&self.secret) X25519PublicKey::from(&self.secret)
} }
pub fn secret(&self) -> &StaticSecret { pub fn secret(&self) -> &X25519PrivateKey {
&self.secret &self.secret
} }
} }

View File

@ -10,7 +10,7 @@ use crypto::{PrekeyBundle, SymmetricKey32};
use crate::context::Introduction; use crate::context::Introduction;
use crate::conversation::{ChatError, ConversationId, Convo, Id, PrivateV1Convo}; use crate::conversation::{ChatError, ConversationId, Convo, Id, PrivateV1Convo};
use crate::crypto::{CopyBytes, StaticSecret, X25519PublicKey}; use crate::crypto::{CopyBytes, X25519PrivateKey, X25519PublicKey};
use crate::identity::Identity; use crate::identity::Identity;
use crate::inbox::handshake::InboxHandshake; use crate::inbox::handshake::InboxHandshake;
use crate::proto; use crate::proto;
@ -25,7 +25,7 @@ fn delivery_address_for_installation(_: X25519PublicKey) -> String {
pub struct Inbox { pub struct Inbox {
ident: Rc<Identity>, ident: Rc<Identity>,
local_convo_id: String, local_convo_id: String,
ephemeral_keys: HashMap<String, StaticSecret>, ephemeral_keys: HashMap<String, X25519PrivateKey>,
} }
impl std::fmt::Debug for Inbox { impl std::fmt::Debug for Inbox {
@ -47,12 +47,12 @@ impl Inbox {
Self { Self {
ident, ident,
local_convo_id, local_convo_id,
ephemeral_keys: HashMap::<String, StaticSecret>::new(), ephemeral_keys: HashMap::<String, X25519PrivateKey>::new(),
} }
} }
pub fn create_intro_bundle(&mut self) -> Introduction { pub fn create_intro_bundle(&mut self) -> Introduction {
let ephemeral = StaticSecret::random(); let ephemeral = X25519PrivateKey::random();
let ephemeral_key: X25519PublicKey = (&ephemeral).into(); let ephemeral_key: X25519PublicKey = (&ephemeral).into();
self.ephemeral_keys self.ephemeral_keys
@ -169,7 +169,7 @@ impl Inbox {
fn perform_handshake( fn perform_handshake(
&self, &self,
ephemeral_key: &StaticSecret, ephemeral_key: &X25519PrivateKey,
header: proto::InboxHeaderV1, header: proto::InboxHeaderV1,
bytes: Bytes, bytes: Bytes,
) -> Result<(SymmetricKey32, proto::InboxV1Frame), ChatError> { ) -> Result<(SymmetricKey32, proto::InboxV1Frame), ChatError> {
@ -215,7 +215,7 @@ impl Inbox {
Ok(frame) Ok(frame)
} }
fn lookup_ephemeral_key(&self, key: &str) -> Result<&StaticSecret, ChatError> { fn lookup_ephemeral_key(&self, key: &str) -> Result<&X25519PrivateKey, ChatError> {
self.ephemeral_keys self.ephemeral_keys
.get(key) .get(key)
.ok_or(ChatError::UnknownEphemeralKey()) .ok_or(ChatError::UnknownEphemeralKey())

View File

@ -5,7 +5,7 @@ use blake2::{
use crypto::{DomainSeparator, PrekeyBundle, SymmetricKey32, X3Handshake}; use crypto::{DomainSeparator, PrekeyBundle, SymmetricKey32, X3Handshake};
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
use crate::crypto::{StaticSecret, X25519PublicKey}; use crate::crypto::{X25519PrivateKey, X25519PublicKey};
type Blake2bMac256 = Blake2bMac<U32>; type Blake2bMac256 = Blake2bMac<U32>;
@ -21,7 +21,7 @@ pub struct InboxHandshake {}
impl InboxHandshake { impl InboxHandshake {
/// Performs /// Performs
pub fn perform_as_initiator<R: RngCore + CryptoRng>( pub fn perform_as_initiator<R: RngCore + CryptoRng>(
identity_keypair: &StaticSecret, identity_keypair: &X25519PrivateKey,
recipient_bundle: &PrekeyBundle, recipient_bundle: &PrekeyBundle,
rng: &mut R, rng: &mut R,
) -> (SymmetricKey32, X25519PublicKey) { ) -> (SymmetricKey32, X25519PublicKey) {
@ -42,9 +42,9 @@ impl InboxHandshake {
/// * `initiator_identity` - Initiator's identity public key /// * `initiator_identity` - Initiator's identity public key
/// * `initiator_ephemeral` - Initiator's ephemeral public key /// * `initiator_ephemeral` - Initiator's ephemeral public key
pub fn perform_as_responder( pub fn perform_as_responder(
identity_keypair: &StaticSecret, identity_keypair: &X25519PrivateKey,
signed_prekey: &StaticSecret, signed_prekey: &X25519PrivateKey,
onetime_prekey: Option<&StaticSecret>, onetime_prekey: Option<&X25519PrivateKey>,
initiator_identity: &X25519PublicKey, initiator_identity: &X25519PublicKey,
initiator_ephemeral: &X25519PublicKey, initiator_ephemeral: &X25519PublicKey,
) -> SymmetricKey32 { ) -> SymmetricKey32 {
@ -85,12 +85,12 @@ mod tests {
let mut rng = OsRng; let mut rng = OsRng;
// Alice (initiator) generates her identity key // Alice (initiator) generates her identity key
let alice_identity = StaticSecret::random_from_rng(rng); let alice_identity = X25519PrivateKey::random_from_rng(rng);
let alice_identity_pub = X25519PublicKey::from(&alice_identity); let alice_identity_pub = X25519PublicKey::from(&alice_identity);
// Bob (responder) generates his keys // Bob (responder) generates his keys
let bob_identity = StaticSecret::random_from_rng(rng); let bob_identity = X25519PrivateKey::random_from_rng(rng);
let bob_signed_prekey = StaticSecret::random_from_rng(rng); let bob_signed_prekey = X25519PrivateKey::random_from_rng(rng);
let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey); let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey);
// Create Bob's prekey bundle // Create Bob's prekey bundle

View File

@ -1,9 +1,8 @@
use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD}; use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD};
use chat_proto::logoschat::intro::IntroBundle; use chat_proto::logoschat::intro::IntroBundle;
use crypto::{Ed25519Signature, X25519PublicKey}; use crypto::{Ed25519Signature, X25519PrivateKey, X25519PublicKey};
use prost::Message; use prost::Message;
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
use x25519_dalek::StaticSecret;
use crate::errors::ChatError; use crate::errors::ChatError;
@ -17,7 +16,7 @@ fn intro_binding_message(ephemeral: &X25519PublicKey) -> Vec<u8> {
} }
pub(crate) fn sign_intro_binding<R: RngCore + CryptoRng>( pub(crate) fn sign_intro_binding<R: RngCore + CryptoRng>(
secret: &StaticSecret, secret: &X25519PrivateKey,
ephemeral: &X25519PublicKey, ephemeral: &X25519PublicKey,
rng: R, rng: R,
) -> Ed25519Signature { ) -> Ed25519Signature {
@ -44,7 +43,7 @@ pub struct Introduction {
impl Introduction { impl Introduction {
/// Create a new `Introduction` by signing the ephemeral key with the installation secret. /// Create a new `Introduction` by signing the ephemeral key with the installation secret.
pub(crate) fn new<R: RngCore + CryptoRng>( pub(crate) fn new<R: RngCore + CryptoRng>(
installation_secret: &StaticSecret, installation_secret: &X25519PrivateKey,
ephemeral_key: X25519PublicKey, ephemeral_key: X25519PublicKey,
rng: R, rng: R,
) -> Self { ) -> Self {
@ -147,9 +146,9 @@ mod tests {
use rand_core::OsRng; use rand_core::OsRng;
fn create_test_introduction() -> Introduction { fn create_test_introduction() -> Introduction {
let install_secret = StaticSecret::random_from_rng(OsRng); let install_secret = X25519PrivateKey::random_from_rng(OsRng);
let ephemeral_secret = StaticSecret::random_from_rng(OsRng); let ephemeral_secret = X25519PrivateKey::random_from_rng(OsRng);
let ephemeral_pub: X25519PublicKey = (&ephemeral_secret).into(); let ephemeral_pub: X25519PublicKey = (&ephemeral_secret).into();
Introduction::new(&install_secret, ephemeral_pub, OsRng) Introduction::new(&install_secret, ephemeral_pub, OsRng)

View File

@ -2,7 +2,7 @@ pub use generic_array::{GenericArray, typenum::U32};
use rand_core::{CryptoRng, OsRng, RngCore}; use rand_core::{CryptoRng, OsRng, RngCore};
use std::{fmt::Debug, ops::Deref}; use std::{fmt::Debug, ops::Deref};
use x25519_dalek::{PublicKey, SharedSecret, StaticSecret}; use x25519_dalek;
use xeddsa::xed25519; use xeddsa::xed25519;
use zeroize::{Zeroize, ZeroizeOnDrop}; use zeroize::{Zeroize, ZeroizeOnDrop};
@ -15,9 +15,9 @@ impl From<x25519_dalek::PublicKey> for X25519PublicKey {
} }
} }
impl From<&StaticSecret> for X25519PublicKey { impl From<&X25519PrivateKey> for X25519PublicKey {
fn from(value: &StaticSecret) -> Self { fn from(value: &X25519PrivateKey) -> Self {
Self(x25519_dalek::PublicKey::from(value)) Self(x25519_dalek::PublicKey::from(&value.0))
} }
} }
@ -28,7 +28,7 @@ impl From<[u8; 32]> for X25519PublicKey {
} }
impl Deref for X25519PublicKey { impl Deref for X25519PublicKey {
type Target = PublicKey; type Target = x25519_dalek::PublicKey;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.0 &self.0
} }
@ -60,6 +60,12 @@ impl X25519PrivateKey {
} }
} }
impl From<[u8; 32]> for X25519PrivateKey {
fn from(value: [u8; 32]) -> Self {
Self(x25519_dalek::StaticSecret::from(value))
}
}
impl Deref for X25519PrivateKey { impl Deref for X25519PrivateKey {
type Target = x25519_dalek::StaticSecret; type Target = x25519_dalek::StaticSecret;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
@ -67,6 +73,12 @@ impl Deref for X25519PrivateKey {
} }
} }
impl From<&X25519PrivateKey> for xed25519::PrivateKey {
fn from(value: &X25519PrivateKey) -> Self {
Self::from(&value.0)
}
}
/// A Generic secret key container for symmetric keys. /// A Generic secret key container for symmetric keys.
/// SymmetricKey retains ownership of bytes to ensure they are Zeroized on drop. /// SymmetricKey retains ownership of bytes to ensure they are Zeroized on drop.
#[derive(Clone, Zeroize, ZeroizeOnDrop, PartialEq)] #[derive(Clone, Zeroize, ZeroizeOnDrop, PartialEq)]
@ -107,10 +119,10 @@ impl From<GenericArray<u8, U32>> for SymmetricKey32 {
} }
} }
impl From<&SharedSecret> for SymmetricKey32 { impl From<&x25519_dalek::SharedSecret> for SymmetricKey32 {
// This relies on the feature 'zeroize' being set for x25519-dalek. // This relies on the feature 'zeroize' being set for x25519-dalek.
// If not the SharedSecret will need to manually zeroized // If not the SharedSecret will need to manually zeroized
fn from(value: &SharedSecret) -> Self { fn from(value: &x25519_dalek::SharedSecret) -> Self {
value.to_bytes().into() value.to_bytes().into()
} }
} }

View File

@ -2,6 +2,6 @@ mod keys;
mod x3dh; mod x3dh;
mod xeddsa_sign; mod xeddsa_sign;
pub use keys::{GenericArray, SymmetricKey32, X25519PublicKey}; pub use keys::{GenericArray, SymmetricKey32, X25519PrivateKey, X25519PublicKey};
pub use x3dh::{DomainSeparator, PrekeyBundle, X3Handshake}; pub use x3dh::{DomainSeparator, PrekeyBundle, X3Handshake};
pub use xeddsa_sign::{Ed25519Signature, SignatureError, xeddsa_sign, xeddsa_verify}; pub use xeddsa_sign::{Ed25519Signature, SignatureError, xeddsa_sign, xeddsa_verify};

View File

@ -3,9 +3,9 @@ use std::marker::PhantomData;
use hkdf::Hkdf; use hkdf::Hkdf;
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
use sha2::Sha256; use sha2::Sha256;
use x25519_dalek::{SharedSecret, StaticSecret}; use x25519_dalek::SharedSecret;
use crate::keys::{SymmetricKey32, X25519PublicKey}; use crate::keys::{SymmetricKey32, X25519PrivateKey, X25519PublicKey};
use crate::xeddsa_sign::Ed25519Signature; use crate::xeddsa_sign::Ed25519Signature;
/// A prekey bundle containing the public keys needed to initiate an X3DH key exchange. /// A prekey bundle containing the public keys needed to initiate an X3DH key exchange.
@ -67,12 +67,12 @@ impl<D: DomainSeparator> X3Handshake<D> {
/// # Returns /// # Returns
/// A tuple of (shared secret bytes, ephemeral public key) /// A tuple of (shared secret bytes, ephemeral public key)
pub fn initator<R: RngCore + CryptoRng>( pub fn initator<R: RngCore + CryptoRng>(
identity_keypair: &StaticSecret, identity_keypair: &X25519PrivateKey,
recipient_bundle: &PrekeyBundle, recipient_bundle: &PrekeyBundle,
rng: &mut R, rng: &mut R,
) -> (SymmetricKey32, X25519PublicKey) { ) -> (SymmetricKey32, X25519PublicKey) {
// Generate ephemeral key for this handshake (using StaticSecret for multiple DH operations) // Generate ephemeral key for this handshake (using X25519PrivateKey for multiple DH operations)
let ephemeral_secret = StaticSecret::random_from_rng(rng); let ephemeral_secret = X25519PrivateKey::random_from_rng(rng);
let ephemeral_public = X25519PublicKey::from(&ephemeral_secret); let ephemeral_public = X25519PublicKey::from(&ephemeral_secret);
// Perform the 4 Diffie-Hellman operations // Perform the 4 Diffie-Hellman operations
@ -102,9 +102,9 @@ impl<D: DomainSeparator> X3Handshake<D> {
/// # Returns /// # Returns
/// The derived shared secret bytes /// The derived shared secret bytes
pub fn responder( pub fn responder(
identity_keypair: &StaticSecret, identity_keypair: &X25519PrivateKey,
signed_prekey: &StaticSecret, signed_prekey: &X25519PrivateKey,
onetime_prekey: Option<&StaticSecret>, onetime_prekey: Option<&X25519PrivateKey>,
initiator_identity: &X25519PublicKey, initiator_identity: &X25519PublicKey,
initiator_ephemeral: &X25519PublicKey, initiator_ephemeral: &X25519PublicKey,
) -> SymmetricKey32 { ) -> SymmetricKey32 {
@ -135,17 +135,17 @@ mod tests {
let mut rng = OsRng; let mut rng = OsRng;
// Alice (initiator) generates her identity key // Alice (initiator) generates her identity key
let alice_identity = StaticSecret::random_from_rng(rng); let alice_identity = X25519PrivateKey::random_from_rng(rng);
let alice_identity_pub = X25519PublicKey::from(&alice_identity); let alice_identity_pub = X25519PublicKey::from(&alice_identity);
// Bob (responder) generates his keys // Bob (responder) generates his keys
let bob_identity = StaticSecret::random_from_rng(rng); let bob_identity = X25519PrivateKey::random_from_rng(rng);
let bob_identity_pub = X25519PublicKey::from(&bob_identity); let bob_identity_pub = X25519PublicKey::from(&bob_identity);
let bob_signed_prekey = StaticSecret::random_from_rng(rng); let bob_signed_prekey = X25519PrivateKey::random_from_rng(rng);
let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey); let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey);
let bob_onetime_prekey = StaticSecret::random_from_rng(rng); let bob_onetime_prekey = X25519PrivateKey::random_from_rng(rng);
let bob_onetime_prekey_pub = X25519PublicKey::from(&bob_onetime_prekey); let bob_onetime_prekey_pub = X25519PublicKey::from(&bob_onetime_prekey);
// Create Bob's prekey bundle (with one-time prekey) // Create Bob's prekey bundle (with one-time prekey)
@ -178,14 +178,14 @@ mod tests {
let mut rng = OsRng; let mut rng = OsRng;
// Alice (initiator) generates her identity key // Alice (initiator) generates her identity key
let alice_identity = StaticSecret::random_from_rng(rng); let alice_identity = X25519PrivateKey::random_from_rng(rng);
let alice_identity_pub = X25519PublicKey::from(&alice_identity); let alice_identity_pub = X25519PublicKey::from(&alice_identity);
// Bob (responder) generates his keys // Bob (responder) generates his keys
let bob_identity = StaticSecret::random_from_rng(rng); let bob_identity = X25519PrivateKey::random_from_rng(rng);
let bob_identity_pub = X25519PublicKey::from(&bob_identity); let bob_identity_pub = X25519PublicKey::from(&bob_identity);
let bob_signed_prekey = StaticSecret::random_from_rng(rng); let bob_signed_prekey = X25519PrivateKey::random_from_rng(rng);
let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey); let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey);
// Create Bob's prekey bundle (without one-time prekey) // Create Bob's prekey bundle (without one-time prekey)

View File

@ -4,10 +4,9 @@
//! that allow signing arbitrary messages with X25519 keys. //! that allow signing arbitrary messages with X25519 keys.
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
use x25519_dalek::StaticSecret;
use xeddsa::{Sign, Verify, xed25519}; use xeddsa::{Sign, Verify, xed25519};
use crate::keys::X25519PublicKey; use crate::keys::{X25519PrivateKey, X25519PublicKey};
/// A 64-byte XEdDSA signature over an Ed25519-compatible curve. /// A 64-byte XEdDSA signature over an Ed25519-compatible curve.
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
@ -46,7 +45,7 @@ pub struct SignatureError;
/// # Returns /// # Returns
/// An `Ed25519Signature` /// An `Ed25519Signature`
pub fn xeddsa_sign<R: RngCore + CryptoRng>( pub fn xeddsa_sign<R: RngCore + CryptoRng>(
secret: &StaticSecret, secret: &X25519PrivateKey,
message: &[u8], message: &[u8],
mut rng: R, mut rng: R,
) -> Ed25519Signature { ) -> Ed25519Signature {
@ -81,7 +80,7 @@ mod tests {
#[test] #[test]
fn test_sign_and_verify_roundtrip() { fn test_sign_and_verify_roundtrip() {
let secret = StaticSecret::random_from_rng(OsRng); let secret = X25519PrivateKey::random_from_rng(OsRng);
let public = X25519PublicKey::from(&secret); let public = X25519PublicKey::from(&secret);
let message = b"test message"; let message = b"test message";
@ -92,12 +91,12 @@ mod tests {
#[test] #[test]
fn test_wrong_key_fails() { fn test_wrong_key_fails() {
let secret = StaticSecret::random_from_rng(OsRng); let secret = X25519PrivateKey::random_from_rng(OsRng);
let message = b"test message"; let message = b"test message";
let signature = xeddsa_sign(&secret, message, OsRng); let signature = xeddsa_sign(&secret, message, OsRng);
let wrong_secret = StaticSecret::random_from_rng(OsRng); let wrong_secret = X25519PrivateKey::random_from_rng(OsRng);
let wrong_public = X25519PublicKey::from(&wrong_secret); let wrong_public = X25519PublicKey::from(&wrong_secret);
assert_eq!( assert_eq!(
@ -108,7 +107,7 @@ mod tests {
#[test] #[test]
fn test_wrong_message_fails() { fn test_wrong_message_fails() {
let secret = StaticSecret::random_from_rng(OsRng); let secret = X25519PrivateKey::random_from_rng(OsRng);
let public = X25519PublicKey::from(&secret); let public = X25519PublicKey::from(&secret);
let message = b"test message"; let message = b"test message";
@ -122,7 +121,7 @@ mod tests {
#[test] #[test]
fn test_corrupted_signature_fails() { fn test_corrupted_signature_fails() {
let secret = StaticSecret::random_from_rng(OsRng); let secret = X25519PrivateKey::random_from_rng(OsRng);
let public = X25519PublicKey::from(&secret); let public = X25519PublicKey::from(&secret);
let message = b"test message"; let message = b"test message";

View File

@ -1,19 +1,18 @@
use crypto::X25519PublicKey; use crypto::{X25519PrivateKey, X25519PublicKey};
use rand_core::OsRng; use rand_core::OsRng;
use x25519_dalek::StaticSecret;
use zeroize::{Zeroize, ZeroizeOnDrop}; use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::types::SharedSecret; use crate::types::SharedSecret;
#[derive(Clone, Zeroize, ZeroizeOnDrop)] #[derive(Clone, Zeroize, ZeroizeOnDrop)]
pub struct InstallationKeyPair { pub struct InstallationKeyPair {
secret: StaticSecret, secret: X25519PrivateKey,
public: X25519PublicKey, public: X25519PublicKey,
} }
impl InstallationKeyPair { impl InstallationKeyPair {
pub fn generate() -> Self { pub fn generate() -> Self {
let secret = StaticSecret::random_from_rng(OsRng); let secret = X25519PrivateKey::random_from_rng(OsRng);
let public = X25519PublicKey::from(&secret); let public = X25519PublicKey::from(&secret);
Self { secret, public } Self { secret, public }
} }
@ -33,14 +32,14 @@ impl InstallationKeyPair {
/// Import the secret key from raw bytes. /// Import the secret key from raw bytes.
pub fn from_secret_bytes(bytes: [u8; 32]) -> Self { pub fn from_secret_bytes(bytes: [u8; 32]) -> Self {
let secret = StaticSecret::from(bytes); let secret = X25519PrivateKey::from(bytes);
let public = X25519PublicKey::from(&secret); let public = X25519PublicKey::from(&secret);
Self { secret, public } Self { secret, public }
} }
} }
impl From<StaticSecret> for InstallationKeyPair { impl From<X25519PrivateKey> for InstallationKeyPair {
fn from(value: StaticSecret) -> Self { fn from(value: X25519PrivateKey) -> Self {
let public = X25519PublicKey::from(&value); let public = X25519PublicKey::from(&value);
Self { Self {
secret: value, secret: value,