Skip to main content
Glama
key_pair.rs3.43 kB
use std::path::Path; use sodiumoxide::crypto::box_; use telemetry::prelude::*; use thiserror::Error; use tokio::{ fs::File, io::AsyncWriteExt, }; use crate::{ VeritechDecryptionKey, VeritechEncryptionKey, }; /// An error that can be returned when working with a [`VeritechKeyPair`]. #[remain::sorted] #[derive(Error, Debug)] pub enum VeritechKeyPairError { /// When an error is return while creating and writing key files #[error("write io error: {0}")] WriteIo(#[from] std::io::Error), } /// A Veritech encryption/decryption key pair generator. pub struct VeritechKeyPair; impl VeritechKeyPair { /// Generates and writes a new pair of keys to the given file paths. /// /// # Errors /// /// Return `Err` if: /// /// - A key file path cannot be created or is not writable (i.e. incorrect permission and/or /// ownership) pub async fn create_and_write_files( secret_key_path: impl AsRef<Path>, public_key_path: impl AsRef<Path>, ) -> Result<(), VeritechKeyPairError> { let (public_key, secret_key) = box_::gen_keypair(); let mut file = File::create(&secret_key_path).await?; file.write_all(&secret_key.0).await?; let mut file = File::create(&public_key_path).await?; file.write_all(&public_key.0).await?; Ok(()) } /// Generates a new pair of keys. pub fn create() -> (VeritechEncryptionKey, VeritechDecryptionKey) { let (public_key, secret_key) = box_::gen_keypair(); (public_key.into(), secret_key.into()) } } #[cfg(test)] mod tests { use tempfile::NamedTempFile; use tokio::io::AsyncReadExt; use super::*; #[tokio::test] async fn create_and_write_files() { sodiumoxide::init().expect("failed to init sodiumoxide"); let secret_key_path = NamedTempFile::new() .expect("failed to create named tempfile") .into_temp_path(); let public_key_path = NamedTempFile::new() .expect("failed to create named tempfile") .into_temp_path(); VeritechKeyPair::create_and_write_files(&secret_key_path, &public_key_path) .await .expect("unable to create key pair"); let mut buf = Vec::new(); File::open(&secret_key_path) .await .expect("unable to open secret key file") .read_to_end(&mut buf) .await .expect("failed to read from secret key file"); let secret_key = box_::SecretKey::from_slice(&buf).expect("unable to parse secret key from bytes"); buf.clear(); File::open(&public_key_path) .await .expect("unable to open public key file") .read_to_end(&mut buf) .await .expect("failed to read from public key file"); let public_key = box_::PublicKey::from_slice(&buf).expect("unable to parse public key from bytes"); // Attempt an encryption/decryption round trip to ensure that both keys are related let message = "our-lady-peace".to_string(); let crypted = sodiumoxide::crypto::sealedbox::seal(message.as_bytes(), &public_key); let decrypted = sodiumoxide::crypto::sealedbox::open(&crypted, &public_key, &secret_key) .expect("failed to decrypt"); assert_eq!(message.as_bytes(), &decrypted); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server