Skip to main content

deltachat/
key.rs

1//! Cryptographic key module.
2
3use std::collections::BTreeMap;
4use std::fmt::{self, Write as _};
5use std::io::Cursor;
6
7use anyhow::{Context as _, Result, bail, ensure};
8use base64::Engine as _;
9use deltachat_contact_tools::EmailAddress;
10use pgp::composed::{Deserializable, SignedKeyDetails};
11pub use pgp::composed::{SignedPublicKey, SignedSecretKey};
12use pgp::crypto::aead::AeadAlgorithm;
13use pgp::crypto::hash::HashAlgorithm;
14use pgp::crypto::sym::SymmetricKeyAlgorithm;
15use pgp::packet::{
16    Features, KeyFlags, Notation, PacketTrait as _, SignatureConfig, SignatureType, Subpacket,
17    SubpacketData,
18};
19use pgp::ser::Serialize;
20use pgp::types::{CompressionAlgorithm, KeyDetails, KeyVersion};
21use rand_old::thread_rng;
22use tokio::runtime::Handle;
23
24use crate::context::Context;
25use crate::events::EventType;
26use crate::log::LogExt;
27use crate::tools::{self, time_elapsed};
28
29/// Convenience trait for working with keys.
30///
31/// This trait is implemented for rPGP's [SignedPublicKey] and
32/// [SignedSecretKey] types and makes working with them a little
33/// easier in the deltachat world.
34pub trait DcKey: Serialize + Deserializable + Clone {
35    /// Create a key from some bytes.
36    fn from_slice(bytes: &[u8]) -> Result<Self> {
37        let res = <Self as Deserializable>::from_bytes(Cursor::new(bytes));
38        if let Ok(res) = res {
39            return Ok(res);
40        }
41
42        // Workaround for keys imported using
43        // Delta Chat core < 1.0.0.
44        // Old Delta Chat core had a bug
45        // that resulted in treating CRC24 checksum
46        // as part of the key when reading ASCII Armor.
47        // Some users that started using Delta Chat in 2019
48        // have such corrupted keys with garbage bytes at the end.
49        //
50        // Garbage is at least 3 bytes long
51        // and may be longer due to padding
52        // at the end of the real key data
53        // and importing the key multiple times.
54        //
55        // If removing 10 bytes is not enough,
56        // the key is likely actually corrupted.
57        for garbage_bytes in 3..std::cmp::min(bytes.len(), 10) {
58            let res = <Self as Deserializable>::from_bytes(Cursor::new(
59                bytes
60                    .get(..bytes.len().saturating_sub(garbage_bytes))
61                    .unwrap_or_default(),
62            ));
63            if let Ok(res) = res {
64                return Ok(res);
65            }
66        }
67
68        // Removing garbage bytes did not help, return the error.
69        Ok(res?)
70    }
71
72    /// Create a key from a base64 string.
73    fn from_base64(data: &str) -> Result<Self> {
74        // strip newlines and other whitespace
75        let cleaned: String = data.split_whitespace().collect();
76        let bytes = base64::engine::general_purpose::STANDARD.decode(cleaned.as_bytes())?;
77        Self::from_slice(&bytes)
78    }
79
80    /// Create a key from an ASCII-armored string.
81    fn from_asc(data: &str) -> Result<Self> {
82        let bytes = data.as_bytes();
83        let res = Self::from_armor_single(Cursor::new(bytes));
84        let (key, _headers) = match res {
85            Err(pgp::errors::Error::NoMatchingPacket { .. }) => match Self::is_private() {
86                true => bail!("No private key packet found"),
87                false => bail!("No public key packet found"),
88            },
89            _ => res.context("rPGP error")?,
90        };
91        Ok(key)
92    }
93
94    /// Serialise the key as bytes.
95    fn to_bytes(&self) -> Vec<u8> {
96        // Not using Serialize::to_bytes() to make clear *why* it is
97        // safe to ignore this error.
98        // Because we write to a Vec<u8> the io::Write impls never
99        // fail and we can hide this error.
100        let mut buf = Vec::new();
101        self.to_writer(&mut buf).unwrap();
102        buf
103    }
104
105    /// Serialise the key to a base64 string.
106    fn to_base64(&self) -> String {
107        base64::engine::general_purpose::STANDARD.encode(DcKey::to_bytes(self))
108    }
109
110    /// Serialise the key to ASCII-armored representation.
111    ///
112    /// Each header line must be terminated by `\r\n`.  Only allows setting one
113    /// header as a simplification since that's the only way it's used so far.
114    // Since .to_armored_string() are actual methods on SignedPublicKey and
115    // SignedSecretKey we can not generically implement this.
116    fn to_asc(&self, header: Option<(&str, &str)>) -> String;
117
118    /// The fingerprint for the key.
119    fn dc_fingerprint(&self) -> Fingerprint;
120
121    /// Whether the key is private (or public).
122    fn is_private() -> bool;
123}
124
125/// Converts secret key to public key.
126pub(crate) fn secret_key_to_public_key(
127    context: &Context,
128    mut signed_secret_key: SignedSecretKey,
129    timestamp: u32,
130    addr: &str,
131    relay_addrs: &str,
132) -> Result<SignedPublicKey> {
133    info!(context, "Converting secret key to public key.");
134    let timestamp = pgp::types::Timestamp::from_secs(timestamp);
135
136    // Subpackets that we want to share between DKS and User ID signature.
137    let common_subpackets = || -> Result<Vec<Subpacket>> {
138        let keyflags = {
139            let mut keyflags = KeyFlags::default();
140            keyflags.set_certify(true);
141            keyflags.set_sign(true);
142            keyflags
143        };
144        let features = {
145            let mut features = Features::default();
146            features.set_seipd_v1(true);
147            features.set_seipd_v2(true);
148            features
149        };
150
151        Ok(vec![
152            Subpacket::regular(SubpacketData::SignatureCreationTime(timestamp))?,
153            Subpacket::regular(SubpacketData::IssuerFingerprint(
154                signed_secret_key.fingerprint(),
155            ))?,
156            Subpacket::regular(SubpacketData::KeyFlags(keyflags))?,
157            Subpacket::regular(SubpacketData::Features(features))?,
158            Subpacket::regular(SubpacketData::PreferredSymmetricAlgorithms(smallvec![
159                SymmetricKeyAlgorithm::AES256,
160                SymmetricKeyAlgorithm::AES192,
161                SymmetricKeyAlgorithm::AES128
162            ]))?,
163            Subpacket::regular(SubpacketData::PreferredHashAlgorithms(smallvec![
164                HashAlgorithm::Sha256,
165                HashAlgorithm::Sha384,
166                HashAlgorithm::Sha512,
167                HashAlgorithm::Sha224,
168            ]))?,
169            Subpacket::regular(SubpacketData::PreferredCompressionAlgorithms(smallvec![
170                CompressionAlgorithm::ZLIB,
171                CompressionAlgorithm::ZIP,
172            ]))?,
173            Subpacket::regular(SubpacketData::PreferredAeadAlgorithms(smallvec![(
174                SymmetricKeyAlgorithm::AES256,
175                AeadAlgorithm::Ocb
176            )]))?,
177            Subpacket::regular(SubpacketData::IsPrimary(true))?,
178        ])
179    };
180
181    // RFC 4880 required that Transferrable Public Key (aka OpenPGP Certificate)
182    // contains at least one User ID:
183    // <https://www.rfc-editor.org/rfc/rfc4880#section-11.1>
184    // RFC 9580 does not require User ID even for V4 certificates anymore:
185    // <https://www.rfc-editor.org/rfc/rfc9580.html#name-openpgp-version-4-certifica>
186    //
187    // We do not use and do not expect User ID in any keys,
188    // but nevertheless include User ID in V4 keys for compatibility with clients that follow RFC 4880.
189    // RFC 9580 also recommends including User ID into V4 keys:
190    // <https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.10-8>
191    //
192    // We do not support keys older than V4 and are not going
193    // to include User ID in newer V6 keys as all clients that support V6
194    // should support keys without User ID.
195    let users = if signed_secret_key.version() == KeyVersion::V4 {
196        let user_id = format!("<{addr}>");
197
198        let mut rng = thread_rng();
199        // Self-signature is a "positive certification",
200        // see <https://www.ietf.org/archive/id/draft-gallagher-openpgp-signatures-02.html#name-certification-signature-typ>.
201        let mut user_id_signature_config = SignatureConfig::from_key(
202            &mut rng,
203            &signed_secret_key.primary_key,
204            SignatureType::CertPositive,
205        )?;
206        user_id_signature_config.hashed_subpackets = common_subpackets()?;
207        user_id_signature_config.unhashed_subpackets = vec![Subpacket::regular(
208            SubpacketData::IssuerKeyId(signed_secret_key.legacy_key_id()),
209        )?];
210        let user_id_packet =
211            pgp::packet::UserId::from_str(pgp::types::PacketHeaderVersion::New, &user_id)?;
212        let signature = user_id_signature_config.sign_certification(
213            &signed_secret_key.primary_key,
214            &signed_secret_key.primary_key.public_key(),
215            &pgp::types::Password::empty(),
216            user_id_packet.tag(),
217            &user_id_packet,
218        )?;
219        vec![user_id_packet.into_signed(signature)]
220    } else {
221        vec![]
222    };
223
224    let direct_signatures = {
225        let mut rng = thread_rng();
226        let mut direct_key_signature_config = SignatureConfig::from_key(
227            &mut rng,
228            &signed_secret_key.primary_key,
229            SignatureType::Key,
230        )?;
231        direct_key_signature_config.hashed_subpackets = common_subpackets()?;
232        let notation = Notation {
233            readable: true,
234            name: "relays@chatmail.at".into(),
235            value: relay_addrs.to_string().into(),
236        };
237        direct_key_signature_config
238            .hashed_subpackets
239            .push(Subpacket::regular(SubpacketData::Notation(notation))?);
240        let direct_key_signature = direct_key_signature_config.sign_key(
241            &signed_secret_key.primary_key,
242            &pgp::types::Password::empty(),
243            signed_secret_key.primary_key.public_key(),
244        )?;
245        vec![direct_key_signature]
246    };
247
248    signed_secret_key.details = SignedKeyDetails {
249        revocation_signatures: vec![],
250        direct_signatures,
251        users,
252        user_attributes: vec![],
253    };
254
255    Ok(signed_secret_key.to_public_key())
256}
257
258/// Attempts to load own public key.
259///
260/// Returns `None` if no secret key is generated yet.
261pub(crate) async fn load_self_public_key_opt(context: &Context) -> Result<Option<SignedPublicKey>> {
262    let mut lock = context.self_public_key.lock().await;
263
264    if let Some(ref public_key) = *lock {
265        return Ok(Some(public_key.clone()));
266    }
267
268    let Some(secret_key_bytes) = context
269        .sql
270        .query_row_optional(
271            "SELECT private_key
272             FROM keypairs
273             WHERE id=(SELECT value FROM config WHERE keyname='key_id')",
274            (),
275            |row| {
276                let bytes: Vec<u8> = row.get(0)?;
277                Ok(bytes)
278            },
279        )
280        .await?
281    else {
282        return Ok(None);
283    };
284    let signed_secret_key = SignedSecretKey::from_slice(&secret_key_bytes)?;
285    let timestamp = context
286        .sql
287        .query_get_value::<u32>(
288            "SELECT MAX(timestamp)
289             FROM (SELECT add_timestamp AS timestamp
290                   FROM transports
291                   UNION ALL
292                   SELECT remove_timestamp AS timestamp
293                   FROM removed_transports)",
294            (),
295        )
296        .await?
297        .context("No transports configured")?;
298    let addr = context.get_primary_self_addr().await?;
299    let all_addrs = context.get_published_self_addrs().await?.join(",");
300    let signed_public_key =
301        secret_key_to_public_key(context, signed_secret_key, timestamp, &addr, &all_addrs)?;
302    *lock = Some(signed_public_key.clone());
303
304    Ok(Some(signed_public_key))
305}
306
307/// Loads own public key.
308///
309/// If no key is generated yet, generates a new one.
310pub(crate) async fn load_self_public_key(context: &Context) -> Result<SignedPublicKey> {
311    match load_self_public_key_opt(context).await? {
312        Some(public_key) => Ok(public_key),
313        None => {
314            generate_keypair(context).await?;
315            let public_key = load_self_public_key_opt(context)
316                .await?
317                .context("Secret key generated, but public key cannot be created")?;
318            Ok(public_key)
319        }
320    }
321}
322
323/// Ensures a private key exists for the configured user.
324///
325/// Normally the private key is generated when the first message is
326/// sent but in a few locations there are no such guarantees,
327/// e.g. when exporting keys, and calling this function ensures a
328/// private key will be present.
329pub async fn ensure_secret_key_exists(context: &Context) -> Result<()> {
330    load_self_public_key(context).await?;
331    Ok(())
332}
333
334/// Returns our own public keyring.
335///
336/// No keys are generated and at most one key is returned.
337pub(crate) async fn load_self_public_keyring(context: &Context) -> Result<Vec<SignedPublicKey>> {
338    if let Some(public_key) = load_self_public_key_opt(context).await? {
339        Ok(vec![public_key])
340    } else {
341        Ok(vec![])
342    }
343}
344
345/// Returns own public key fingerprint in (not human-readable) hex representation.
346/// This is the fingerprint format that is used in the database.
347///
348/// If no key is generated yet, generates a new one.
349///
350/// For performance reasons, the fingerprint is cached after the first invocation.
351pub(crate) async fn self_fingerprint(context: &Context) -> Result<&str> {
352    if let Some(fp) = context.self_fingerprint.get() {
353        Ok(fp)
354    } else {
355        let fp = load_self_public_key(context).await?.dc_fingerprint().hex();
356        Ok(context.self_fingerprint.get_or_init(|| fp))
357    }
358}
359
360/// Returns own public key fingerprint in (not human-readable) hex representation.
361/// This is the fingerprint format that is used in the database.
362///
363/// Returns `None` if no key is generated yet.
364///
365/// For performance reasons, the fingerprint is cached after the first invocation.
366pub(crate) async fn self_fingerprint_opt(context: &Context) -> Result<Option<&str>> {
367    if let Some(fp) = context.self_fingerprint.get() {
368        Ok(Some(fp))
369    } else if let Some(key) = load_self_public_key_opt(context).await? {
370        let fp = key.dc_fingerprint().hex();
371        Ok(Some(context.self_fingerprint.get_or_init(|| fp)))
372    } else {
373        Ok(None)
374    }
375}
376
377pub(crate) async fn load_self_secret_key(context: &Context) -> Result<SignedSecretKey> {
378    let private_key = context
379        .sql
380        .query_row_optional(
381            "SELECT private_key
382             FROM keypairs
383             WHERE id=(SELECT value FROM config WHERE keyname='key_id')",
384            (),
385            |row| {
386                let bytes: Vec<u8> = row.get(0)?;
387                Ok(bytes)
388            },
389        )
390        .await?;
391    match private_key {
392        Some(bytes) => SignedSecretKey::from_slice(&bytes),
393        None => {
394            let secret = generate_keypair(context).await?;
395            Ok(secret)
396        }
397    }
398}
399
400pub(crate) async fn load_self_secret_keyring(context: &Context) -> Result<Vec<SignedSecretKey>> {
401    let keys = context
402        .sql
403        .query_map_vec(
404            r#"SELECT private_key
405               FROM keypairs
406               ORDER BY id=(SELECT value FROM config WHERE keyname='key_id') DESC"#,
407            (),
408            |row| {
409                let bytes: Vec<u8> = row.get(0)?;
410                Ok(bytes)
411            },
412        )
413        .await?
414        .into_iter()
415        .filter_map(|bytes| SignedSecretKey::from_slice(&bytes).log_err(context).ok())
416        .collect();
417    Ok(keys)
418}
419
420impl DcKey for SignedPublicKey {
421    fn to_asc(&self, header: Option<(&str, &str)>) -> String {
422        // Not using .to_armored_string() to make clear *why* it is
423        // safe to ignore this error.
424        // Because we write to a Vec<u8> the io::Write impls never
425        // fail and we can hide this error.
426        let headers =
427            header.map(|(key, value)| BTreeMap::from([(key.to_string(), vec![value.to_string()])]));
428        let mut buf = Vec::new();
429        self.to_armored_writer(&mut buf, headers.as_ref().into())
430            .unwrap_or_default();
431        std::string::String::from_utf8(buf).unwrap_or_default()
432    }
433
434    fn is_private() -> bool {
435        false
436    }
437
438    fn dc_fingerprint(&self) -> Fingerprint {
439        self.fingerprint().into()
440    }
441}
442
443impl DcKey for SignedSecretKey {
444    fn to_asc(&self, header: Option<(&str, &str)>) -> String {
445        // Not using .to_armored_string() to make clear *why* it is
446        // safe to do these unwraps.
447        // Because we write to a Vec<u8> the io::Write impls never
448        // fail and we can hide this error.  The string is always ASCII.
449        let headers =
450            header.map(|(key, value)| BTreeMap::from([(key.to_string(), vec![value.to_string()])]));
451        let mut buf = Vec::new();
452        self.to_armored_writer(&mut buf, headers.as_ref().into())
453            .unwrap_or_default();
454        std::string::String::from_utf8(buf).unwrap_or_default()
455    }
456
457    fn is_private() -> bool {
458        true
459    }
460
461    fn dc_fingerprint(&self) -> Fingerprint {
462        self.fingerprint().into()
463    }
464}
465
466async fn generate_keypair(context: &Context) -> Result<SignedSecretKey> {
467    let addr = context.get_primary_self_addr().await?;
468    let addr = EmailAddress::new(&addr)?;
469    let _public_key_guard = context.self_public_key.lock().await;
470
471    // Check if the key appeared while we were waiting on the lock.
472    match load_keypair(context).await? {
473        Some(key_pair) => Ok(key_pair),
474        None => {
475            let start = tools::Time::now();
476            info!(context, "Generating keypair.");
477            let keypair = Handle::current()
478                .spawn_blocking(move || crate::pgp::create_keypair(addr))
479                .await??;
480
481            store_self_keypair(context, &keypair).await?;
482            info!(
483                context,
484                "Keypair generated in {:.3}s.",
485                time_elapsed(&start).as_secs(),
486            );
487            Ok(keypair)
488        }
489    }
490}
491
492pub(crate) async fn load_keypair(context: &Context) -> Result<Option<SignedSecretKey>> {
493    let res = context
494        .sql
495        .query_row_optional(
496            "SELECT private_key
497                 FROM keypairs
498                 WHERE id=(SELECT value FROM config WHERE keyname='key_id')",
499            (),
500            |row| {
501                let sec_bytes: Vec<u8> = row.get(0)?;
502                Ok(sec_bytes)
503            },
504        )
505        .await?;
506
507    let signed_secret_key = if let Some(sec_bytes) = res {
508        Some(SignedSecretKey::from_slice(&sec_bytes)?)
509    } else {
510        None
511    };
512
513    Ok(signed_secret_key)
514}
515
516/// Stores own keypair in the database and sets it as a default.
517///
518/// Fails if we already have a key, so it is not possible to
519/// have more than one key for new setups. Existing setups
520/// may still have more than one key for compatibility.
521pub(crate) async fn store_self_keypair(
522    context: &Context,
523    signed_secret_key: &SignedSecretKey,
524) -> Result<()> {
525    // This public key is stored in the database
526    // only for backwards compatibility.
527    //
528    // It should not be used e.g. in Autocrypt headers or vCards.
529    // Use `secret_key_to_public_key()` function instead,
530    // which adds relay list to the signature.
531    let signed_public_key = signed_secret_key.to_public_key();
532    let mut config_cache_lock = context.sql.config_cache.write().await;
533    let new_key_id = context
534        .sql
535        .transaction(|transaction| {
536            let public_key = DcKey::to_bytes(&signed_public_key);
537            let secret_key = DcKey::to_bytes(signed_secret_key);
538
539            // private_key and public_key columns
540            // are UNIQUE since migration 107,
541            // so this fails if we already have this key.
542            transaction
543                .execute(
544                    "INSERT INTO keypairs (public_key, private_key)
545                     VALUES (?,?)",
546                    (&public_key, &secret_key),
547                )
548                .context("Failed to insert keypair")?;
549
550            let new_key_id = transaction.last_insert_rowid();
551
552            // This will fail if we already have `key_id`.
553            //
554            // Setting default key is only possible if we don't
555            // have a key already.
556            transaction.execute(
557                "INSERT INTO config (keyname, value) VALUES ('key_id', ?)",
558                (new_key_id,),
559            )?;
560            Ok(new_key_id)
561        })
562        .await?;
563    context.emit_event(EventType::AccountsItemChanged);
564    config_cache_lock.insert("key_id".to_string(), Some(new_key_id.to_string()));
565    Ok(())
566}
567
568/// Saves a keypair as the default keys.
569///
570/// This API is used for testing purposes
571/// to avoid generating the key in tests.
572/// Use import/export APIs instead.
573pub async fn preconfigure_keypair(context: &Context, secret_data: &str) -> Result<()> {
574    let secret = SignedSecretKey::from_asc(secret_data)?;
575    store_self_keypair(context, &secret).await?;
576    Ok(())
577}
578
579/// A key fingerprint
580#[derive(Clone, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
581pub struct Fingerprint(Vec<u8>);
582
583impl Fingerprint {
584    /// Creates new fingerprint.
585    ///
586    /// It is 160-bit (20 bytes) for v4 keys and 32 bytes for v6 keys.
587    pub fn new(v: Vec<u8>) -> Fingerprint {
588        debug_assert!(v.len() == 20 || v.len() == 32);
589        Fingerprint(v)
590    }
591
592    /// Make a hex string from the fingerprint.
593    ///
594    /// Use [std::fmt::Display] or [ToString::to_string] to get a
595    /// human-readable formatted string.
596    pub fn hex(&self) -> String {
597        hex::encode_upper(&self.0)
598    }
599
600    /// Make a human-readable fingerprint.
601    pub fn human_readable(&self) -> String {
602        let mut f = String::new();
603        // Split key into chunks of 4 with space and newline at 20 chars
604        for (i, c) in self.hex().chars().enumerate() {
605            if i > 0 && i % 20 == 0 {
606                writeln!(&mut f).ok();
607            } else if i > 0 && i % 4 == 0 {
608                write!(&mut f, " ").ok();
609            }
610            write!(&mut f, "{c}").ok();
611        }
612        f
613    }
614}
615
616impl From<pgp::types::Fingerprint> for Fingerprint {
617    fn from(fingerprint: pgp::types::Fingerprint) -> Fingerprint {
618        Self::new(fingerprint.as_bytes().into())
619    }
620}
621
622impl fmt::Debug for Fingerprint {
623    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
624        f.debug_struct("Fingerprint")
625            .field("hex", &self.hex())
626            .finish()
627    }
628}
629
630/// Parse a human-readable or otherwise formatted fingerprint.
631impl std::str::FromStr for Fingerprint {
632    type Err = anyhow::Error;
633
634    fn from_str(input: &str) -> Result<Self> {
635        let hex_repr: String = input
636            .to_uppercase()
637            .chars()
638            .filter(|&c| c.is_ascii_hexdigit())
639            .collect();
640        let v: Vec<u8> = hex::decode(&hex_repr)?;
641        ensure!(
642            v.len() == 20 || v.len() == 32,
643            "wrong fingerprint length: {hex_repr}"
644        );
645        let fp = Fingerprint::new(v);
646        Ok(fp)
647    }
648}
649
650#[cfg(test)]
651mod tests {
652    use std::sync::{Arc, LazyLock};
653
654    use super::*;
655    use crate::config::Config;
656    use crate::test_utils::{TestContext, alice_keypair};
657
658    static KEYPAIR: LazyLock<SignedSecretKey> = LazyLock::new(alice_keypair);
659
660    #[test]
661    fn test_from_armored_string() {
662        let private_key = SignedSecretKey::from_asc(
663            "-----BEGIN PGP PRIVATE KEY BLOCK-----
664
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
7177yPJeQ==
718=KZk/
719-----END PGP PRIVATE KEY BLOCK-----",
720        )
721        .expect("failed to decode");
722        let binary = DcKey::to_bytes(&private_key);
723        SignedSecretKey::from_slice(&binary).expect("invalid private key");
724    }
725
726    #[test]
727    fn test_asc_roundtrip() {
728        let key = KEYPAIR.clone().to_public_key();
729        let asc = key.to_asc(Some(("spam", "ham")));
730        let key2 = SignedPublicKey::from_asc(&asc).unwrap();
731        assert_eq!(key, key2);
732
733        let key = KEYPAIR.clone();
734        let asc = key.to_asc(Some(("spam", "ham")));
735        let key2 = SignedSecretKey::from_asc(&asc).unwrap();
736        assert_eq!(key, key2);
737    }
738
739    #[test]
740    fn test_from_slice_roundtrip() {
741        let private_key = KEYPAIR.clone();
742        let public_key = KEYPAIR.clone().to_public_key();
743
744        let binary = DcKey::to_bytes(&public_key);
745        let public_key2 = SignedPublicKey::from_slice(&binary).expect("invalid public key");
746        assert_eq!(public_key, public_key2);
747
748        let binary = DcKey::to_bytes(&private_key);
749        let private_key2 = SignedSecretKey::from_slice(&binary).expect("invalid private key");
750        assert_eq!(private_key, private_key2);
751    }
752
753    #[test]
754    fn test_from_slice_bad_data() {
755        let mut bad_data: [u8; 4096] = [0; 4096];
756        for (i, v) in bad_data.iter_mut().enumerate() {
757            *v = (i & 0xff) as u8;
758        }
759        for j in 0..(4096 / 40) {
760            let slice = &bad_data.get(j..j + 4096 / 2 + j).unwrap();
761            assert!(SignedPublicKey::from_slice(slice).is_err());
762            assert!(SignedSecretKey::from_slice(slice).is_err());
763        }
764    }
765
766    /// Tests workaround for Delta Chat core < 1.0.0
767    /// which parsed CRC24 at the end of ASCII Armor
768    /// as the part of the key.
769    /// Depending on the alignment and the number of
770    /// `=` characters at the end of the key,
771    /// this resulted in various number of garbage
772    /// octets at the end of the key, starting from 3 octets,
773    /// but possibly 4 or 5 and maybe more octets
774    /// if the key is imported multiple times.
775    #[test]
776    fn test_ignore_trailing_garbage() {
777        // Test several variants of garbage.
778        for garbage in [
779            b"\x02\xfc\xaa\x38\x4b\x5c".as_slice(),
780            b"\x02\xfc\xaa".as_slice(),
781            b"\x01\x02\x03\x04\x05".as_slice(),
782        ] {
783            let private_key = KEYPAIR.clone();
784
785            let mut binary = DcKey::to_bytes(&private_key);
786            binary.extend(garbage);
787
788            let private_key2 =
789                SignedSecretKey::from_slice(&binary).expect("Failed to ignore garbage");
790
791            assert_eq!(private_key.dc_fingerprint(), private_key2.dc_fingerprint());
792        }
793    }
794
795    #[test]
796    fn test_base64_roundtrip() {
797        let key = KEYPAIR.clone().to_public_key();
798        let base64 = key.to_base64();
799        let key2 = SignedPublicKey::from_base64(&base64).unwrap();
800        assert_eq!(key, key2);
801    }
802
803    #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
804    async fn test_load_self_generate_public() {
805        let t = TestContext::new().await;
806        t.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
807            .await
808            .unwrap();
809        let key = load_self_public_key(&t).await;
810        assert!(key.is_ok());
811    }
812
813    #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
814    async fn test_load_self_generate_secret() {
815        let t = TestContext::new().await;
816        t.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
817            .await
818            .unwrap();
819        let key = load_self_secret_key(&t).await;
820        assert!(key.is_ok());
821    }
822
823    #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
824    async fn test_load_self_generate_concurrent() {
825        use std::thread;
826
827        let t = TestContext::new().await;
828        t.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
829            .await
830            .unwrap();
831        let thr0 = {
832            let ctx = t.clone();
833            thread::spawn(move || {
834                tokio::runtime::Runtime::new()
835                    .unwrap()
836                    .block_on(load_self_public_key(&ctx))
837            })
838        };
839        let thr1 = {
840            let ctx = t.clone();
841            thread::spawn(move || {
842                tokio::runtime::Runtime::new()
843                    .unwrap()
844                    .block_on(load_self_public_key(&ctx))
845            })
846        };
847        let res0 = thr0.join().unwrap();
848        let res1 = thr1.join().unwrap();
849        assert_eq!(res0.unwrap(), res1.unwrap());
850    }
851
852    /// Tests that setting a default key second time is not allowed.
853    #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
854    async fn test_save_self_key_twice() {
855        // Saving the same key twice should result in only one row in
856        // the keypairs table.
857        let t = TestContext::new().await;
858        let ctx = Arc::new(t);
859
860        let nrows = || async {
861            ctx.sql
862                .count("SELECT COUNT(*) FROM keypairs;", ())
863                .await
864                .unwrap()
865        };
866        assert_eq!(nrows().await, 0);
867        store_self_keypair(&ctx, &KEYPAIR).await.unwrap();
868        assert_eq!(nrows().await, 1);
869
870        // Saving a second key fails.
871        let res = store_self_keypair(&ctx, &KEYPAIR).await;
872        assert!(res.is_err());
873
874        assert_eq!(nrows().await, 1);
875    }
876
877    #[test]
878    fn test_fingerprint_from_str() {
879        let res = Fingerprint::new(vec![
880            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
881        ]);
882
883        let fp: Fingerprint = "0102030405060708090A0B0c0d0e0F1011121314".parse().unwrap();
884        assert_eq!(fp, res);
885
886        let fp: Fingerprint = "zzzz 0102 0304 0506\n0708090a0b0c0D0E0F1011121314 yyy"
887            .parse()
888            .unwrap();
889        assert_eq!(fp, res);
890
891        assert!("1".parse::<Fingerprint>().is_err());
892    }
893
894    #[test]
895    fn test_fingerprint_hex() {
896        let fp = Fingerprint::new(vec![
897            1, 2, 4, 8, 16, 32, 64, 128, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
898        ]);
899        assert_eq!(fp.hex(), "0102040810204080FF0A0B0C0D0E0F1011121314");
900    }
901
902    #[test]
903    fn test_fingerprint_to_string() {
904        let fp = Fingerprint::new(vec![
905            1, 2, 4, 8, 16, 32, 64, 128, 255, 1, 2, 4, 8, 16, 32, 64, 128, 255, 19, 20,
906        ]);
907        assert_eq!(
908            fp.human_readable(),
909            "0102 0408 1020 4080 FF01\n0204 0810 2040 80FF 1314"
910        );
911    }
912
913    mod ensure_secret_key_exists {
914        use super::*;
915
916        #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
917        async fn test_prexisting() {
918            let t = TestContext::new_alice().await;
919            assert!(ensure_secret_key_exists(&t).await.is_ok());
920        }
921
922        #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
923        async fn test_not_configured() {
924            let t = TestContext::new().await;
925            assert!(ensure_secret_key_exists(&t).await.is_err());
926        }
927    }
928}