keystore_dump/
main.rs

1use color_eyre::eyre::Result;
2#[cfg(target_family = "wasm")]
3fn main() -> Result<()> {
4    println!("the keystore dump tool is not available for WASM");
5    Ok(())
6}
7
8#[cfg(not(target_family = "wasm"))]
9#[tokio::main]
10async fn main() -> Result<()> {
11    #[derive(Debug, clap::Parser)]
12    #[command(author, version, about, long_about = None)]
13    struct Args {
14        #[arg(short, long)]
15        key: String,
16
17        path: String,
18    }
19
20    use chrono::TimeZone;
21    use clap::Parser as _;
22    use color_eyre::eyre::eyre;
23    use core_crypto_keystore::{Connection as Keystore, connection::FetchFromDatabase, entities::*};
24    use openmls::prelude::TlsDeserializeTrait;
25    use serde::ser::{SerializeMap, Serializer};
26
27    color_eyre::install()?;
28
29    let args = Args::parse();
30
31    if !tokio::fs::try_exists(&args.path).await.unwrap_or_default() {
32        return Err(eyre!("File not found: {}", args.path));
33    }
34
35    let keystore = Keystore::open_with_key(&args.path, &args.key)
36        .await
37        .map_err(|e| eyre!("The passkey is probably wrong; [err: {e}]"))?;
38
39    let mut json_serializer = serde_json::Serializer::pretty(std::io::stdout());
40    let mut json_map = json_serializer.serialize_map(None)?;
41
42    let mut credentials: Vec<serde_json::Value> = vec![];
43    for cred in keystore
44        .find_all::<MlsCredential>(Default::default())
45        .await?
46        .into_iter()
47    {
48        let mls_credential = openmls::prelude::Credential::tls_deserialize(&mut cred.credential.as_slice())?;
49        let date = chrono::Utc
50            .timestamp_opt(cred.created_at as i64, 0)
51            .single()
52            .ok_or_else(|| eyre!("Cannot parse credential creation date"))?;
53
54        credentials.push(serde_json::json!({
55            "id": cred.id,
56            "credential": mls_credential,
57            "created_at": date
58        }));
59    }
60    json_map.serialize_entry("mls_credentials", &credentials)?;
61
62    let mut signature_keypairs: Vec<serde_json::Value> = vec![];
63    for kp in keystore
64        .find_all::<MlsSignatureKeyPair>(Default::default())
65        .await?
66        .into_iter()
67    {
68        let mls_keypair = openmls_basic_credential::SignatureKeyPair::tls_deserialize(&mut kp.keypair.as_slice())?;
69        signature_keypairs.push(serde_json::json!({
70            "signature_scheme": kp.signature_scheme,
71            "mls_keypair": mls_keypair,
72            "credential_id": kp.credential_id,
73        }));
74    }
75    json_map.serialize_entry("mls_signature_keypairs", &signature_keypairs)?;
76
77    let hpke_sks: Vec<openmls_traits::types::HpkePrivateKey> = keystore
78        .find_all::<MlsHpkePrivateKey>(Default::default())
79        .await?
80        .into_iter()
81        .map(|hpke_sk| postcard::from_bytes::<openmls_traits::types::HpkePrivateKey>(&hpke_sk.sk))
82        .collect::<postcard::Result<_>>()?;
83    json_map.serialize_entry("mls_hpke_private_keys", &hpke_sks)?;
84
85    let hpke_keypairs: Vec<openmls_traits::types::HpkeKeyPair> = keystore
86        .find_all::<MlsEncryptionKeyPair>(Default::default())
87        .await?
88        .into_iter()
89        .map(|hpke_kp| postcard::from_bytes::<openmls_traits::types::HpkeKeyPair>(&hpke_kp.sk))
90        .collect::<postcard::Result<_>>()?;
91    json_map.serialize_entry("mls_hpke_keypairs", &hpke_keypairs)?;
92
93    let mut external_psks: std::collections::HashMap<String, openmls::schedule::psk::PskBundle> = Default::default();
94    for psk in keystore.find_all::<MlsPskBundle>(Default::default()).await?.into_iter() {
95        let mls_psk = postcard::from_bytes::<openmls::schedule::psk::PskBundle>(&psk.psk)?;
96        external_psks.insert(hex::encode(&psk.psk_id), mls_psk);
97    }
98
99    json_map.serialize_entry("external_psks", &external_psks)?;
100
101    let keypackages: Vec<openmls::prelude::KeyPackage> = keystore
102        .find_all::<MlsKeyPackage>(Default::default())
103        .await?
104        .into_iter()
105        .map(|kp| postcard::from_bytes::<openmls::prelude::KeyPackage>(&kp.keypackage))
106        .collect::<postcard::Result<_>>()?;
107    json_map.serialize_entry("mls_keypackages", &keypackages)?;
108
109    let e2ei_enrollments: Vec<core_crypto::prelude::E2eiEnrollment> = keystore
110        .find_all::<E2eiEnrollment>(Default::default())
111        .await?
112        .into_iter()
113        .map(|enrollment| serde_json::from_slice::<core_crypto::prelude::E2eiEnrollment>(&enrollment.content))
114        .collect::<serde_json::Result<_>>()?;
115    json_map.serialize_entry("e2ei_enrollments", &e2ei_enrollments)?;
116
117    let pgroups: Vec<openmls::prelude::MlsGroup> = keystore
118        .find_all::<PersistedMlsGroup>(Default::default())
119        .await?
120        .into_iter()
121        .map(|pgroup| core_crypto_keystore::deser::<openmls::prelude::MlsGroup>(&pgroup.state))
122        .collect::<core_crypto_keystore::CryptoKeystoreResult<_>>()?;
123    json_map.serialize_entry("mls_groups", &pgroups)?;
124
125    let pegroups: Vec<openmls::prelude::MlsGroup> = keystore
126        .find_all::<PersistedMlsPendingGroup>(Default::default())
127        .await?
128        .into_iter()
129        .map(|pgroup| core_crypto_keystore::deser::<openmls::prelude::MlsGroup>(&pgroup.state))
130        .collect::<core_crypto_keystore::CryptoKeystoreResult<_>>()?;
131    json_map.serialize_entry("mls_pending_groups", &pegroups)?;
132
133    if let Some(proteus_identity) = keystore.find::<ProteusIdentity>(&[]).await? {
134        let identity = {
135            let sk = proteus_identity.sk_raw();
136            let pk = proteus_identity.pk_raw();
137            proteus_wasm::keys::IdentityKeyPair::from_raw_key_pair(*sk, *pk)?
138        };
139        json_map.serialize_entry("proteus_identity", &identity)?;
140
141        let prekeys: Vec<proteus_wasm::keys::PreKey> = keystore
142            .find_all::<ProteusPrekey>(Default::default())
143            .await?
144            .into_iter()
145            .map(|pk| proteus_wasm::keys::PreKey::deserialise(&pk.prekey))
146            .collect::<Result<Vec<_>, proteus_wasm::DecodeError>>()?;
147        json_map.serialize_entry("proteus_prekeys", &prekeys)?;
148
149        let proteus_sessions: Vec<proteus_wasm::session::Session<proteus_wasm::keys::IdentityKeyPair>> = keystore
150            .find_all::<ProteusSession>(Default::default())
151            .await?
152            .into_iter()
153            .map(|session| proteus_wasm::session::Session::deserialise(identity.clone(), &session.session))
154            .collect::<Result<Vec<_>, proteus_wasm::DecodeError>>()?;
155
156        json_map.serialize_entry("proteus_sessions", &proteus_sessions)?;
157    }
158
159    json_map.end()?;
160
161    Ok(())
162}