perf: reduce verification load (#75)

- assume valid keys in the db
- verify keys on import from headers + disk
- use references in keyring when possible
This commit is contained in:
Friedel Ziegelmayer
2019-05-17 10:19:43 +02:00
committed by Lars-Magnus Skog
parent 8678813051
commit 379fc72094
7 changed files with 54 additions and 36 deletions

View File

@@ -160,7 +160,13 @@ impl str::FromStr for Aheader {
.remove("keydata")
.and_then(|raw| Key::from_base64(&raw, KeyType::Public))
{
Some(key) => key,
Some(key) => {
if key.verify() {
key
} else {
return Err(());
}
}
None => {
return Err(());
}

View File

@@ -121,11 +121,9 @@ pub unsafe fn dc_e2ee_encrypt(
recipient_addr,
) && (peerstate.prefer_encrypt == 1i32 || 0 != e2ee_guaranteed)
{
if let Some(key_to_use) =
dc_apeerstate_peek_key(&peerstate, min_verified)
if let Some(key) = dc_apeerstate_peek_key(&peerstate, min_verified)
{
// TODO: avoid clone
keyring.add(key_to_use.clone());
keyring.add_owned(key.clone());
peerstates.push(peerstate);
}
} else {
@@ -143,8 +141,7 @@ pub unsafe fn dc_e2ee_encrypt(
}
}
let sign_key = if 0 != do_encrypt {
// TODO: avoid clone
keyring.add(public_key.clone());
keyring.add_ref(&public_key);
let key =
Key::from_self_private(context, addr, &context.sql.clone().read().unwrap());
@@ -670,12 +667,11 @@ pub unsafe fn dc_e2ee_decrypt(
if 0 != peerstate.degrade_event {
dc_handle_degrade_event(context, &peerstate);
}
// TODO: avoid clone
if let Some(ref key) = peerstate.gossip_key {
public_keyring_for_validate.add(key.clone());
public_keyring_for_validate.add_ref(key);
}
if let Some(ref key) = peerstate.public_key {
public_keyring_for_validate.add(key.clone());
public_keyring_for_validate.add_ref(key);
}
(*helper).signatures = malloc(::std::mem::size_of::<dc_hash_t>()) as *mut dc_hash_t;
dc_hash_init((*helper).signatures, 3i32, 1i32);

View File

@@ -522,6 +522,7 @@ unsafe fn set_self_key(
CStr::from_ptr(buf_base64).to_str().unwrap(),
KeyType::Private,
)
.and_then(|k| if k.verify() { Some(k) } else { None })
.and_then(|k| k.split_key().map(|pub_key| (k, pub_key)))
{
stmt = dc_sqlite3_prepare(

View File

@@ -97,14 +97,7 @@ impl Key {
};
match res {
Ok(key) => {
if key.verify() {
Some(key)
} else {
eprintln!("Invalid key: {:?}", key);
None
}
}
Ok(key) => Some(key),
Err(err) => {
eprintln!("Invalid key bytes: {:?}\n{}", err, hex::encode(bytes));
None

View File

@@ -1,3 +1,5 @@
use std::borrow::Cow;
use crate::constants::*;
use crate::dc_context::dc_context_t;
use crate::dc_key::*;
@@ -5,16 +7,24 @@ use crate::dc_sqlite3::*;
use crate::types::*;
#[derive(Default, Clone, Debug)]
pub struct Keyring {
keys: Vec<Key>,
pub struct Keyring<'a> {
keys: Vec<Cow<'a, Key>>,
}
impl Keyring {
pub fn add(&mut self, key: Key) {
impl<'a> Keyring<'a> {
pub fn add_owned(&mut self, key: Key) {
self.add(Cow::Owned(key))
}
pub fn add_ref(&mut self, key: &'a Key) {
self.add(Cow::Borrowed(key))
}
fn add(&mut self, key: Cow<'a, Key>) {
self.keys.push(key);
}
pub fn keys(&self) -> &[Key] {
pub fn keys(&self) -> &[Cow<'a, Key>] {
&self.keys
}
@@ -39,7 +49,7 @@ impl Keyring {
unsafe { sqlite3_bind_text(stmt, 1, self_addr, -1, None) };
while unsafe { sqlite3_step(stmt) == 100 } {
if let Some(key) = Key::from_stmt(stmt, 0, KeyType::Private) {
self.add(key);
self.add_owned(key);
}
}
unsafe { sqlite3_finalize(stmt) };

View File

@@ -182,6 +182,9 @@ pub fn dc_pgp_create_keypair(addr: *const libc::c_char) -> Option<(Key, Key)> {
.sign(&private_key, || "".into())
.expect("failed to sign public key");
private_key.verify().expect("invalid private key generated");
public_key.verify().expect("invalid public key generated");
Some((Key::Public(public_key), Key::Secret(private_key)))
}
@@ -197,8 +200,11 @@ pub fn dc_pgp_pk_encrypt(
let lit_msg = Message::new_literal_bytes("", bytes);
let pkeys: Vec<&SignedPublicKey> = public_keys_for_encryption
.keys()
.iter()
.filter_map(|key| key.try_into().ok())
.into_iter()
.filter_map(|key| {
let k: &Key = &key;
k.try_into().ok()
})
.collect();
let mut rng = thread_rng();
@@ -237,7 +243,10 @@ pub fn dc_pgp_pk_decrypt(
let skeys: Vec<&SignedSecretKey> = private_keys_for_decryption
.keys()
.iter()
.filter_map(|key| key.try_into().ok())
.filter_map(|key| {
let k: &Key = &key;
k.try_into().ok()
})
.collect();
msg.decrypt(|| "".into(), || "".into(), &skeys[..])
@@ -252,7 +261,10 @@ pub fn dc_pgp_pk_decrypt(
let pkeys: Vec<&SignedPublicKey> = public_keys_for_validation
.keys()
.iter()
.filter_map(|key| key.try_into().ok())
.filter_map(|key| {
let k: &Key = &key;
k.try_into().ok()
})
.collect();
for pkey in &pkeys {

View File

@@ -2239,8 +2239,8 @@ fn test_encryption_decryption() {
let original_text: *const libc::c_char =
b"This is a test\x00" as *const u8 as *const libc::c_char;
let mut keyring = Keyring::default();
keyring.add(public_key.clone());
keyring.add(public_key2.clone());
keyring.add_owned(public_key.clone());
keyring.add_ref(&public_key2);
let ctext = dc_pgp_pk_encrypt(
original_text as *const libc::c_void,
@@ -2270,13 +2270,13 @@ fn test_encryption_decryption() {
let ctext_unsigned = CString::new(ctext).unwrap();
let mut keyring = Keyring::default();
keyring.add(private_key);
keyring.add_owned(private_key);
let mut public_keyring = Keyring::default();
public_keyring.add(public_key.clone());
public_keyring.add_ref(&public_key);
let mut public_keyring2 = Keyring::default();
public_keyring2.add(public_key2.clone());
public_keyring2.add_owned(public_key2.clone());
let mut valid_signatures = dc_hash_t {
keyClass: 0,
@@ -2338,7 +2338,7 @@ fn test_encryption_decryption() {
dc_hash_clear(&mut valid_signatures);
public_keyring2.add(public_key.clone());
public_keyring2.add_ref(&public_key);
let plain = dc_pgp_pk_decrypt(
ctext_signed.as_ptr() as *const _,
@@ -2371,9 +2371,9 @@ fn test_encryption_decryption() {
dc_hash_clear(&mut valid_signatures);
let mut keyring = Keyring::default();
keyring.add(private_key2);
keyring.add_ref(&private_key2);
let mut public_keyring = Keyring::default();
public_keyring.add(public_key);
public_keyring.add_ref(&public_key);
let plain = dc_pgp_pk_decrypt(
ctext_signed.as_ptr() as *const _,