When changing self addr, transfer private key to new addr (#3351)

fix #3267
This commit is contained in:
Hocuri
2022-05-23 19:25:53 +02:00
committed by GitHub
parent c762834e05
commit b7af53c7d9
3 changed files with 128 additions and 39 deletions

View File

@@ -204,29 +204,8 @@ async fn generate_keypair(context: &Context) -> Result<KeyPair> {
let _guard = context.generating_key_mutex.lock().await;
// Check if the key appeared while we were waiting on the lock.
match context
.sql
.query_row_optional(
r#"
SELECT public_key, private_key
FROM keypairs
WHERE addr=?1
AND is_default=1;
"#,
paramsv![addr],
|row| {
let pub_bytes: Vec<u8> = row.get(0)?;
let sec_bytes: Vec<u8> = row.get(1)?;
Ok((pub_bytes, sec_bytes))
},
)
.await?
{
Some((pub_bytes, sec_bytes)) => Ok(KeyPair {
addr,
public: SignedPublicKey::from_slice(&pub_bytes)?,
secret: SignedSecretKey::from_slice(&sec_bytes)?,
}),
match load_keypair(context, &addr).await? {
Some(key_pair) => Ok(key_pair),
None => {
let start = std::time::SystemTime::now();
let keytype = KeyGenType::from_i32(context.get_config_int(Config::KeyGenType).await?)
@@ -246,6 +225,39 @@ async fn generate_keypair(context: &Context) -> Result<KeyPair> {
}
}
pub(crate) async fn load_keypair(
context: &Context,
addr: &EmailAddress,
) -> Result<Option<KeyPair>> {
let res = context
.sql
.query_row_optional(
r#"
SELECT public_key, private_key
FROM keypairs
WHERE addr=?1
AND is_default=1;
"#,
paramsv![addr],
|row| {
let pub_bytes: Vec<u8> = row.get(0)?;
let sec_bytes: Vec<u8> = row.get(1)?;
Ok((pub_bytes, sec_bytes))
},
)
.await?;
Ok(if let Some((pub_bytes, sec_bytes)) = res {
Some(KeyPair {
addr: addr.clone(),
public: SignedPublicKey::from_slice(&pub_bytes)?,
secret: SignedSecretKey::from_slice(&sec_bytes)?,
})
} else {
None
})
}
/// Use of a [KeyPair] for encryption or decryption.
///
/// This is used by [store_self_keypair] to know what kind of key is
@@ -275,23 +287,20 @@ pub async fn store_self_keypair(
keypair: &KeyPair,
default: KeyPairUse,
) -> Result<()> {
// Everything should really be one transaction, more refactoring
// is needed for that.
let mut conn = context.sql.get_conn().await?;
let transaction = conn.transaction()?;
let public_key = DcKey::to_bytes(&keypair.public);
let secret_key = DcKey::to_bytes(&keypair.secret);
context
.sql
transaction
.execute(
"DELETE FROM keypairs WHERE public_key=? OR private_key=?;",
paramsv![public_key, secret_key],
)
.await
.context("failed to remove old use of key")?;
if default == KeyPairUse::Default {
context
.sql
transaction
.execute("UPDATE keypairs SET is_default=0;", paramsv![])
.await
.context("failed to clear default")?;
}
let is_default = match default {
@@ -302,16 +311,16 @@ pub async fn store_self_keypair(
let addr = keypair.addr.to_string();
let t = time();
context
.sql
transaction
.execute(
"INSERT INTO keypairs (addr, is_default, public_key, private_key, created)
VALUES (?,?,?,?,?);",
paramsv![addr, is_default, public_key, secret_key, t],
)
.await
.context("failed to insert keypair")?;
transaction.commit()?;
Ok(())
}