fix: ensure public key signatures are not in the past compared to the public key

We use the timestamp of the latest transport modification
as the timestamp of the Direct Key Signature.
However, first transport is created before the public key
and existing transports may even have zero timestamp
if they were created before migration 142.

For interoperability with Sequoia-PGP,
make sure signatures always have a timestamp
that is not in the past compared to the timestamp
of the primary key.
This commit is contained in:
link2xt
2026-07-02 00:32:03 +00:00
committed by l
parent 2b6515e3b5
commit 31b2d7961a

View File

@@ -131,7 +131,13 @@ pub(crate) fn secret_key_to_public_key(
relay_addrs: &str,
) -> Result<SignedPublicKey> {
info!(context, "Converting secret key to public key.");
let timestamp = pgp::types::Timestamp::from_secs(timestamp);
// Make sure timestamp of created signatures
// is not in the past compared to the primary key timestamp.
let timestamp = std::cmp::max(
signed_secret_key.primary_key.created_at(),
pgp::types::Timestamp::from_secs(timestamp),
);
// Subpackets that we want to share between DKS and User ID signature.
let common_subpackets = || -> Result<Vec<Subpacket>> {
@@ -650,10 +656,12 @@ impl std::str::FromStr for Fingerprint {
#[cfg(test)]
mod tests {
use std::sync::{Arc, LazyLock};
use std::time::Duration;
use super::*;
use crate::config::Config;
use crate::test_utils::{TestContext, alice_keypair};
use crate::test_utils::{TestContext, TestContextManager, alice_keypair};
use crate::tools::SystemTime;
static KEYPAIR: LazyLock<SignedSecretKey> = LazyLock::new(alice_keypair);
@@ -874,6 +882,25 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
assert_eq!(nrows().await, 1);
}
/// Tests that key signature timestamp
/// is not in the past compared to the primary key creation timestamp.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_signature_not_in_the_past() -> Result<()> {
let mut tcm = TestContextManager::new();
let t = &tcm.unconfigured().await;
t.configure_addr("foo@example.org").await;
SystemTime::shift(Duration::from_secs(600));
let key = load_self_public_key(t).await?;
assert!(
key.details.direct_signatures[0].created().unwrap() >= key.primary_key.created_at()
);
Ok(())
}
#[test]
fn test_fingerprint_from_str() {
let res = Fingerprint::new(vec![