mirror of
https://github.com/chatmail/core.git
synced 2026-04-21 15:36:30 +03:00
Refactor keypair handling and expose storing keypairs on ffi
The user-visible change here is that it allows the FFI API to save keys in the database for a context. This is primarily intended for testing purposes as it allows you to get a key without having to generate it. Internally the most important change is to start using the SignedPublicKey and SignedPrivateKey types from rpgp instead of wrapping them into a single Key object. This allows APIs to be specific about which they want instead of having to do runtime checks like .is_public() or so. This means some of the functionality of the Key impl now needs to be a trait. A thid API change is to introduce the KeyPair struct, which binds together the email address, public and private key for a keypair. All these changes result in a bunch of cleanups, though more more should be done to completely replace the Key type with the SignedPublicKye/SignedPrivateKey + traits. But this change is large enough already. Testing-wise this adds two new keys which can be loaded from disk and and avoids a few more key-generating tests. The encrypt/decrypt tests are moved from the stress tests into the pgp tests and split up.
This commit is contained in:
committed by
Floris Bruynooghe
parent
c7eca8deb3
commit
98b3151c5f
@@ -5,16 +5,16 @@
|
||||
use tempfile::{tempdir, TempDir};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::constants::KeyType;
|
||||
use crate::context::{Context, ContextCallback};
|
||||
use crate::dc_tools::EmailAddress;
|
||||
use crate::events::Event;
|
||||
use crate::key;
|
||||
use crate::key::{self, DcKey};
|
||||
|
||||
/// A Context and temporary directory.
|
||||
///
|
||||
/// The temporary directory can be used to store the SQLite database,
|
||||
/// see e.g. [test_context] which does this.
|
||||
pub struct TestContext {
|
||||
pub(crate) struct TestContext {
|
||||
pub ctx: Context,
|
||||
pub dir: TempDir,
|
||||
}
|
||||
@@ -25,7 +25,7 @@ pub struct TestContext {
|
||||
/// "db.sqlite" in the [TestContext.dir] directory.
|
||||
///
|
||||
/// [Context]: crate::context::Context
|
||||
pub fn test_context(callback: Option<Box<ContextCallback>>) -> TestContext {
|
||||
pub(crate) fn test_context(callback: Option<Box<ContextCallback>>) -> TestContext {
|
||||
let dir = tempdir().unwrap();
|
||||
let dbfile = dir.path().join("db.sqlite");
|
||||
let cb: Box<ContextCallback> = match callback {
|
||||
@@ -41,11 +41,11 @@ pub fn test_context(callback: Option<Box<ContextCallback>>) -> TestContext {
|
||||
/// The context will be opened and use the SQLite database as
|
||||
/// specified in [test_context] but there is no callback hooked up,
|
||||
/// i.e. [Context::call_cb] will always return `0`.
|
||||
pub fn dummy_context() -> TestContext {
|
||||
pub(crate) fn dummy_context() -> TestContext {
|
||||
test_context(None)
|
||||
}
|
||||
|
||||
pub fn logging_cb(_ctx: &Context, evt: Event) {
|
||||
pub(crate) fn logging_cb(_ctx: &Context, evt: Event) {
|
||||
match evt {
|
||||
Event::Info(msg) => println!("I: {}", msg),
|
||||
Event::Warning(msg) => println!("W: {}", msg),
|
||||
@@ -54,27 +54,54 @@ pub fn logging_cb(_ctx: &Context, evt: Event) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Load a pre-generated keypair for alice@example.com from disk.
|
||||
///
|
||||
/// This saves CPU cycles by avoiding having to generate a key.
|
||||
///
|
||||
/// The keypair was created using (this is purposefully not a doctest, it would be slow):
|
||||
/// let keypair = crate::pgp::create_keypair(EmailAddress::new("alice@example.com"))
|
||||
/// .unwrap();
|
||||
/// println!("{}", keypair.public.to_base64(64));
|
||||
/// println!("{}", keypair.secret.to_base64(64));
|
||||
pub(crate) fn alice_keypair() -> key::KeyPair {
|
||||
let addr = EmailAddress::new("alice@example.com").unwrap();
|
||||
let public =
|
||||
key::SignedPublicKey::from_base64(include_str!("../test-data/key/alice-public.asc"))
|
||||
.unwrap();
|
||||
let secret =
|
||||
key::SignedSecretKey::from_base64(include_str!("../test-data/key/alice-secret.asc"))
|
||||
.unwrap();
|
||||
key::KeyPair {
|
||||
addr,
|
||||
public,
|
||||
secret,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates Alice with a pre-generated keypair.
|
||||
///
|
||||
/// Returns the address of the keypair created (alice@example.org).
|
||||
pub fn configure_alice_keypair(ctx: &Context) -> String {
|
||||
let addr = String::from("alice@example.org");
|
||||
ctx.set_config(Config::ConfiguredAddr, Some(&addr)).unwrap();
|
||||
|
||||
// The keypair was created using:
|
||||
// let (public, private) = crate::pgp::dc_pgp_create_keypair("alice@example.com")
|
||||
// .unwrap();
|
||||
// println!("{}", public.to_base64(64));
|
||||
// println!("{}", private.to_base64(64));
|
||||
let public =
|
||||
key::Key::from_base64(include_str!("../test-data/key/public.asc"), KeyType::Public)
|
||||
.unwrap();
|
||||
let private = key::Key::from_base64(
|
||||
include_str!("../test-data/key/private.asc"),
|
||||
KeyType::Private,
|
||||
)
|
||||
.unwrap();
|
||||
let saved = key::dc_key_save_self_keypair(&ctx, &public, &private, &addr, true, &ctx.sql);
|
||||
assert_eq!(saved, true, "Failed to save Alice's key");
|
||||
addr
|
||||
/// Returns the address of the keypair created (alice@example.com).
|
||||
pub(crate) fn configure_alice_keypair(ctx: &Context) -> String {
|
||||
let keypair = alice_keypair();
|
||||
ctx.set_config(Config::ConfiguredAddr, Some(&keypair.addr.to_string()))
|
||||
.unwrap();
|
||||
key::save_self_keypair(&ctx, &keypair, key::KeyPairUse::Default)
|
||||
.expect("Failed to save Alice's key");
|
||||
keypair.addr.to_string()
|
||||
}
|
||||
|
||||
/// Load a pre-generated keypair for bob@example.net from disk.
|
||||
///
|
||||
/// Like [alice_keypair] but a different key and identity.
|
||||
pub(crate) fn bob_keypair() -> key::KeyPair {
|
||||
let addr = EmailAddress::new("bob@example.net").unwrap();
|
||||
let public =
|
||||
key::SignedPublicKey::from_base64(include_str!("../test-data/key/bob-public.asc")).unwrap();
|
||||
let secret =
|
||||
key::SignedSecretKey::from_base64(include_str!("../test-data/key/bob-secret.asc")).unwrap();
|
||||
key::KeyPair {
|
||||
addr,
|
||||
public,
|
||||
secret,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user