Skip to main content

Crypto

Struct Crypto 

Source
pub struct Crypto { /* private fields */ }
Expand description

Bundle of crypto state used by a Dynomite peer instance.

Holds an RSA key pair loaded from a PEM file and a fresh 32-byte AES session key buffer generated when the bundle is constructed. The session key is used for symmetric encryption of DNODE payloads (AES-128-CBC consumes the first 16 bytes; the remaining 16 bytes match the C aes_key[AES_KEYLEN] buffer layout), while the RSA pair is used to wrap and unwrap session keys during the handshake.

§Examples

use dynomite::crypto::Crypto;

let crypto = Crypto::from_pem("conf/dynomite.pem").unwrap();
let payload = b"sample";
let cipher = Crypto::aes_encrypt(payload, crypto.aes_key()).unwrap();
let plain = Crypto::aes_decrypt(&cipher, crypto.aes_key()).unwrap();
assert_eq!(plain, payload);

Implementations§

Source§

impl Crypto

Source

pub fn from_pem<P: AsRef<Path>>(path: P) -> Result<Self, CryptoError>

Construct a new bundle by loading an RSA private key from the given PEM file and generating a fresh 32-byte AES key buffer from the system CSPRNG.

AES-128-CBC consumes only the first 16 bytes of the buffer; the trailing 16 bytes match the C aes_key[AES_KEYLEN] layout.

§Examples
use dynomite::crypto::Crypto;
let crypto = Crypto::from_pem("conf/dynomite.pem").unwrap();
assert_eq!(crypto.aes_key().len(), 32);
Source

pub fn from_parts(rsa: RsaPrivateKey, aes_key: [u8; 32]) -> Self

Construct a bundle from an already-loaded RSA private key and a caller-supplied AES key. Used by tests and embedders that want to exercise the bundle without touching the filesystem.

§Examples
use dynomite::crypto::Crypto;
use rsa::RsaPrivateKey;
use rand::rngs::OsRng;

let aes_key = Crypto::generate_aes_key().unwrap();
let mut rng = OsRng;
let rsa = RsaPrivateKey::new(&mut rng, 2048).unwrap();
let crypto = Crypto::from_parts(rsa, aes_key);
assert_eq!(crypto.aes_key().len(), 32);
Source

pub fn generate_aes_key() -> Result<[u8; 32], CryptoError>

Generate a fresh 32-byte AES key buffer from the system CSPRNG.

The returned slice is 32 random bytes. AES-128-CBC consumes only the first 16 bytes; the trailing 16 bytes are kept to match the C aes_key[AES_KEYLEN] buffer layout.

§Examples
use dynomite::crypto::Crypto;

let a = Crypto::generate_aes_key().unwrap();
let b = Crypto::generate_aes_key().unwrap();
assert_ne!(a, b);
Source

pub fn aes_key(&self) -> &[u8; 32]

Borrow the bundle’s AES session key.

§Examples
use dynomite::crypto::Crypto;
let crypto = Crypto::from_pem("conf/dynomite.pem").unwrap();
assert_eq!(crypto.aes_key().len(), 32);
Source

pub fn rsa_private_key(&self) -> &RsaPrivateKey

Borrow the bundle’s RSA private key.

§Examples
use dynomite::crypto::Crypto;
let crypto = Crypto::from_pem("conf/dynomite.pem").unwrap();
assert!(crypto.rsa_size() > 0);
Source

pub fn rsa_size(&self) -> usize

Modulus size of the loaded RSA key in bytes.

§Examples
use dynomite::crypto::Crypto;
let crypto = Crypto::from_pem("conf/dynomite.pem").unwrap();
assert!(crypto.rsa_size() >= 128);
Source

pub fn aes_encrypt( msg: &[u8], aes_key: &[u8; 32], ) -> Result<Vec<u8>, CryptoError>

AES-128-CBC encrypt msg with aes_key. The output is the PKCS#7-padded ciphertext with no IV prefix.

§Security
  • AES-128 in CBC mode with PKCS#7 padding. The cipher consumes only the first 16 bytes of the 32-byte aes_key buffer.
  • The IV is the same 16 bytes as the key. The static IV is a known weakness of the legacy wire protocol; the Rust port faithfully reproduces it for wire compatibility. Two encryptions of the same plaintext under the same key produce identical ciphertext.
  • The output is not authenticated. Integrity is provided by the surrounding DNODE message framing. Embedders that need authenticated payloads should treat this as a transport-layer encryption only and layer an AEAD on top.
§Examples
use dynomite::crypto::Crypto;
let key = Crypto::generate_aes_key().unwrap();
let cipher = Crypto::aes_encrypt(b"hi", &key).unwrap();
let plain = Crypto::aes_decrypt(&cipher, &key).unwrap();
assert_eq!(plain, b"hi");
Source

pub fn aes_decrypt( enc: &[u8], aes_key: &[u8; 32], ) -> Result<Vec<u8>, CryptoError>

AES-128-CBC decrypt the output of Crypto::aes_encrypt.

enc must be a non-empty integral number of 16-byte ciphertext blocks. There is no IV prefix; the IV is derived from aes_key exactly as on the encryption side.

§Examples
use dynomite::crypto::Crypto;
let key = Crypto::generate_aes_key().unwrap();
let cipher = Crypto::aes_encrypt(b"hello", &key).unwrap();
let plain = Crypto::aes_decrypt(&cipher, &key).unwrap();
assert_eq!(plain, b"hello");
Source

pub fn dyn_aes_encrypt( msg: &[u8], aes_key: &[u8; 32], pool: &MbufPool, ) -> Result<MbufQueue, CryptoError>

AES-128-CBC encrypt msg, writing the result into a fresh MbufQueue drawn from pool. The chain holds the raw ciphertext; there is no IV prefix. Output spans as many chunks as needed; each chunk is filled up to the writable region before allocating the next one.

§Examples
use dynomite::crypto::Crypto;
use dynomite::io::mbuf::MbufPool;

let pool = MbufPool::default();
let key = Crypto::generate_aes_key().unwrap();
let mut chain = Crypto::dyn_aes_encrypt(b"hello", &key, &pool).unwrap();
let plain = Crypto::dyn_aes_decrypt_to_vec(&mut chain, &key).unwrap();
assert_eq!(plain, b"hello");
Source

pub fn dyn_aes_decrypt( enc: &mut MbufQueue, aes_key: &[u8; 32], pool: &MbufPool, ) -> Result<MbufQueue, CryptoError>

AES-128-CBC decrypt a ciphertext chain produced by Crypto::dyn_aes_encrypt, appending the recovered plaintext to a fresh MbufQueue drawn from pool.

enc is consumed: chunks are popped off the front and pushed to the pool free list as they are drained.

§Examples
use dynomite::crypto::Crypto;
use dynomite::io::mbuf::MbufPool;

let pool = MbufPool::default();
let key = Crypto::generate_aes_key().unwrap();
let mut chain = Crypto::dyn_aes_encrypt(b"abc", &key, &pool).unwrap();
let mut plain_chain = Crypto::dyn_aes_decrypt(&mut chain, &key, &pool).unwrap();
assert_eq!(plain_chain.total_len(), 3);
Source

pub fn dyn_aes_decrypt_to_vec( enc: &mut MbufQueue, aes_key: &[u8; 32], ) -> Result<Vec<u8>, CryptoError>

Convenience wrapper that decrypts a ciphertext chain into a flat Vec<u8>. Useful for tests and protocol code that needs the cleartext as a single buffer.

§Examples
use dynomite::crypto::Crypto;
use dynomite::io::mbuf::MbufPool;

let pool = MbufPool::default();
let key = Crypto::generate_aes_key().unwrap();
let mut chain = Crypto::dyn_aes_encrypt(b"hello", &key, &pool).unwrap();
let plain = Crypto::dyn_aes_decrypt_to_vec(&mut chain, &key).unwrap();
assert_eq!(plain, b"hello");
Source

pub fn dyn_aes_encrypt_msg( msg: &Mbuf, aes_key: &[u8; 32], pool: &MbufPool, ) -> Result<(MbufQueue, usize), CryptoError>

AES-128-CBC encrypt the readable region of msg, returning a new chain holding the ciphertext along with the total number of ciphertext bytes written.

The handshake encodes its own framing on top of the returned chain, so the output count is reported separately rather than derived from the queue.

§Examples
use dynomite::crypto::Crypto;
use dynomite::io::mbuf::{Mbuf, MbufPool};

let pool = MbufPool::default();
let key = Crypto::generate_aes_key().unwrap();
let mut buf = pool.get();
buf.recv(b"payload");
let (mut chain, n) = Crypto::dyn_aes_encrypt_msg(&buf, &key, &pool).unwrap();
assert!(n > 0);
let plain = Crypto::dyn_aes_decrypt_to_vec(&mut chain, &key).unwrap();
assert_eq!(plain, b"payload");
Source

pub fn rsa_encrypt(&self, msg: &[u8]) -> Result<Vec<u8>, CryptoError>

RSA encrypt msg with the bundle’s public key using PKCS#1 OAEP padding (with the OpenSSL default SHA-1 hash and MGF1). The output length is the RSA modulus size in bytes (typically 128 for 1024-bit keys, 256 for 2048-bit).

§Examples
use dynomite::crypto::Crypto;
let crypto = Crypto::from_pem("conf/dynomite.pem").unwrap();
let key = Crypto::generate_aes_key().unwrap();
let wrapped = crypto.rsa_encrypt(&key).unwrap();
let unwrapped = crypto.rsa_decrypt(&wrapped).unwrap();
assert_eq!(unwrapped, key);
Source

pub fn rsa_decrypt(&self, enc: &[u8]) -> Result<Vec<u8>, CryptoError>

RSA decrypt enc with the bundle’s private key using PKCS#1 OAEP padding (with the OpenSSL default SHA-1 hash and MGF1).

§Examples
use dynomite::crypto::Crypto;
let crypto = Crypto::from_pem("conf/dynomite.pem").unwrap();
let key = Crypto::generate_aes_key().unwrap();
let wrapped = crypto.rsa_encrypt(&key).unwrap();
let unwrapped = crypto.rsa_decrypt(&wrapped).unwrap();
assert_eq!(unwrapped, key);

Trait Implementations§

Source§

impl Debug for Crypto

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,