vodozemac/utilities/
libolm_compat.rs1#[cfg(feature = "libolm-compat")]
16use std::io::Cursor;
17
18#[cfg(feature = "libolm-compat")]
19use matrix_pickle::{Decode, Encode};
20#[cfg(feature = "libolm-compat")]
21use zeroize::{Zeroize, ZeroizeOnDrop};
22
23#[cfg(feature = "libolm-compat")]
24use super::{base64_decode, base64_encode};
25#[cfg(feature = "libolm-compat")]
26use crate::{LibolmPickleError, cipher::Cipher};
27
28pub(crate) fn get_version(source: &[u8]) -> Option<u32> {
30 let version = source.get(0..4)?;
33 Some(u32::from_be_bytes(version.try_into().ok()?))
34}
35
36#[cfg(feature = "libolm-compat")]
45pub(crate) fn unpickle_libolm<P: Decode, T: TryFrom<P, Error = LibolmPickleError>>(
46 pickle: &str,
47 pickle_key: &[u8],
48 pickle_version: u32,
49) -> Result<T, LibolmPickleError> {
50 let decoded = base64_decode(pickle)?;
52
53 let cipher = Cipher::new_pickle(pickle_key);
56 let mut decrypted = cipher.decrypt_pickle(&decoded)?;
57
58 let version = get_version(&decrypted).ok_or(LibolmPickleError::MissingVersion)?;
62
63 if version == pickle_version {
64 let mut cursor = Cursor::new(&decrypted);
65 let pickle = P::decode(&mut cursor)?;
66
67 decrypted.zeroize();
68 pickle.try_into()
69 } else {
70 Err(LibolmPickleError::Version(pickle_version, version))
71 }
72}
73
74#[cfg(feature = "libolm-compat")]
75pub(crate) fn pickle_libolm<P>(pickle: P, pickle_key: &[u8]) -> Result<String, LibolmPickleError>
76where
77 P: Encode,
78{
79 let mut encoded = pickle.encode_to_vec()?;
80
81 let cipher = Cipher::new_pickle(pickle_key);
82 let encrypted = cipher.encrypt_pickle(&encoded);
83 encoded.zeroize();
84
85 Ok(base64_encode(encrypted))
86}
87
88#[cfg(feature = "libolm-compat")]
89#[derive(Encode, Decode, Zeroize, ZeroizeOnDrop)]
90pub(crate) struct LibolmEd25519Keypair {
91 pub public_key: [u8; 32],
92 #[secret]
93 pub private_key: Box<[u8; 64]>,
94}
95
96#[cfg(all(feature = "libolm-compat", test))]
97mod test {
98 use super::*;
99
100 #[test]
101 fn encode_cycle() {
102 let key_pair =
103 LibolmEd25519Keypair { public_key: [10u8; 32], private_key: [20u8; 64].into() };
104
105 let encoded = key_pair.encode_to_vec().unwrap();
106 let decoded = LibolmEd25519Keypair::decode_from_slice(&encoded).unwrap();
107
108 assert_eq!(key_pair.public_key, decoded.public_key);
109 assert_eq!(key_pair.private_key, decoded.private_key);
110 }
111}