Skip to content

docs: update specification from manuscript 243f384#126

Merged
rocodes merged 18 commits intofreedomofpress:mainfrom
cfm:main
Dec 2, 2025
Merged

docs: update specification from manuscript 243f384#126
rocodes merged 18 commits intofreedomofpress:mainfrom
cfm:main

Conversation

@cfm
Copy link
Member

@cfm cfm commented Nov 25, 2025

Updates the v0.3 specification to match the definitions and figures in manuscript 243f384. Since there are no major functional or conceptual changes, just dotting of i's and crossing of t's, let's consider this an in-place refinement of version 0.3, not a new version 0.4. Specifically, these changes address from #121....

From @felixlinker in #121 (comment):

  • The results of signature verification are left implicit. It will be clear to most readers that one should abort if signature verification fails, but this should be made explicit.
  • In Section 2, FPF signs the newsroom's key, but that signature is nowhere verified or referenced.
  • In Section 6, the sender includes their $pk^{PKE}_S$ in the plaintext, but journalists have no such key.
  • Signature verification is inconsistent with signature generation. The client verifies a signature by the journalist on three items: APKE key, PKE key, fetching key, but journalists never generate such a signature. Suggested fix: Include fetching key in the signature in Section 3.2.
  • Removing journalist keys and adding source keys as the last step doesn't type-check. First (this is a nit), we remove three-tuples from $pks$, but $pks$ contains four-tuples. Second, journalists have sets of ephemeral key bundles - not a single one. One could have the journalist remove all key bundles which include their key as the verification key.
  • The inclusion of $pk^{sig}_{NR}$ in "reply case" seems redundant. I think it should be removed there? I also don't underestand the case between "all senders" and "anyone" as this section will only be "executed" by senders anyways.

From @ssveitch in #121 (comment):

  • I also would suggest writing up the key fetching a verification process as a separate subprotocol and clarify that this should happen whenever a source or journalist visits the instance (and then it can be made clear what happens when signature verification of these keys fails).
  • The one thing that is still unspecified is what happens if a (source) recipient tries to verify that a message they decrypted comes from a valid journalist and this verification step fails. (I would guess they just ignore the message?)
  • As discussed in a prior meeting, I would generate the source keys from the passphrase differently. Details can be copied from the paper.

Also:

@cfm cfm added this to SecureDrop Nov 25, 2025
@cfm cfm changed the title docs: update specification from manuscript cf81f37 docs: update specification from manuscript cf81f37 Nov 25, 2025
@cfm cfm moved this to In Progress in SecureDrop Nov 25, 2025
@cfm cfm requested a review from Copilot November 25, 2025 21:07
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the protocol specification documentation to synchronize with manuscript version cf81f37. The update refines cryptographic notation, corrects key nomenclature (introducing vk for verification keys), adds detailed building blocks documentation, and restructures the protocol flow descriptions with improved clarity and mathematical rigor.

Key changes:

  • Updated key notation to distinguish verification keys (vk) from public keys (pk)
  • Added comprehensive "Building blocks" section documenting cryptographic primitives (SIG, AEAD, PKE, APKE)
  • Restructured protocol flow sections with "Given/Then" format and improved tables
  • Updated manuscript reference comments throughout (from 7944378 to cf81f37)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 9 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

@rocodes rocodes moved this from Ready For Review to Under Review in SecureDrop Nov 26, 2025
@rocodes rocodes self-assigned this Nov 26, 2025
Copy link
Contributor

@rocodes rocodes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cfm this is a heroic amount of work, thank you. I have 2 comments about the overall protocol description, not about how faithfully you have represented the manuscript, but otherwise LVGTM:

  • We need to specify how the info parameter is calculated (we have c2 + info, but maybe we clarify that as far as our last convo, it is a concatenation of c2 (encaps pq_psk_kem_ct) || receiver fetching pubkey (so sender commits to receiver fetch key).
  • The way it's specified now, I think the same fetching key is signed $i$ times and included with every journalist one-time key bundle? But I think (and per prior discussion if I remember right) we would just sign it once, and it plus the journalist DH-AKEM reply key (two long-term keys) would be submitted to the server. Users would fetch a "welcome bundle" that includes all the long-term keys (newsroom key, newsroom sig over journalist signing keys, journalist sig over their own fetch+reply keys), and either at the same time or separately (depends if we're trying to add extra PoW?), the one-time journalist key bundles would be fetched, but those would just include the journalist signature over their (SD-APKE_E, SD-PKE_E) pubkeys.

@cfm
Copy link
Member Author

cfm commented Nov 26, 2025

@rocodes in #126 (review):

We need to specify how the info parameter is calculated (we have c2 + info, but maybe we clarify that as far as our last convo, it is a concatenation of c2 (encaps pq_psk_kem_ct) || receiver fetching pubkey (so sender commits to receiver fetch key).

Why don't I add a comment to make explicit that c2 + info is $c_2 \Vert info$, and then we can define the value of info in #124?

The way it's specified now, I think the same fetching key is signed $i$ times and included with every journalist one-time key bundle? But I think (and per prior discussion if I remember right) we would just sign it once, and it plus the journalist DH-AKEM reply key (two long-term keys) would be submitted to the server. Users would fetch a "welcome bundle" that includes all the long-term keys (newsroom key, newsroom sig over journalist signing keys, journalist sig over their own fetch+reply keys), and either at the same time or separately (depends if we're trying to add extra PoW?), the one-time journalist key bundles would be fetched, but those would just include the journalist signature over their (SD-APKE_E, SD-PKE_E) pubkeys.

Good point. I'll open a follow-up ticket.

@rocodes
Copy link
Contributor

rocodes commented Nov 26, 2025

I was taking for granted that c2 + info means $c_2||info$ :) I think we require a definition for clarity, even a working one, because I think info = c2 || info is circular, and since we're now (maybe?) using this as canonical and getting feedback from ethz, I don't think it's necesarily better to punt it until it appears in the manuscript.

But if you object, then maybe we can at least leave in a comment what our working definition is, so that people can fact check all/as many as possible assumptions in one place :)

@cfm
Copy link
Member Author

cfm commented Nov 26, 2025

Ah, I see! Let me tack that on.

m, ad, info):
(c2, K2) = KEM_PQ.Encap(pkR=pkR2)
(c1, cp) = pskAEnc(skS=skS1, pkR=pkR1, psk=K2, m=m, ad=ad, info=c2) # cp = c'
(c1, cp) = pskAEnc(skS=skS1, pkR=pkR1, psk=K2, m=m, ad=ad, info=c2 + info) # where cp = c' and "+" means concatenation
Copy link
Member Author

@cfm cfm Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NB. This isn't circular: pskAEnc()'s keyword argument info takes the concatenation of the local variable c2 and the enclosing AuthEnc()'s positional argument info, which is where we pass $pk_R^{fetch}$:

| $`ct^{APKE} \gets \text{SD-APKE.AuthEnc}(sk_S^{APKE}, pk_{R,i}^{APKE}, pt, NR, pk_R^{fetch})`$ | | |

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed as of manuscript 243f384.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My comment about circularity was that we could distinguish terms a bit, as in, we could call one $info`$ or something for readability. However, I don't have strong feelings.

…3f384)

Figure 5 now builds the values of r, x, z, and id on one line to show
the parallelism between the k-subscripted case (real messages) and the
j-subscripted case (decoys).  Here I stick to one assignment per line
for legibility.
@cfm cfm changed the title docs: update specification from manuscript cf81f37 docs: update specification from manuscript 243f384 Dec 1, 2025
@cfm
Copy link
Member Author

cfm commented Dec 1, 2025

ab3ae02 brings us to manuscript 243f384, resolving this TODO:

| $`\forall C_k = (id_k, C_{S_k}, X_k, Z_k):`$ **TODO:** pad up to $n$ total challenges | | |

Copy link
Contributor

@rocodes rocodes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the extra commits! I think this is looking really good, the only thing still outstanding to me is the repeated fetching key signatures section. I saw you filed it as a separate issue, which is fine, but I still think we shouldn't merge it into main if it's not our desired behaviour, because it will be confusing for people trying to follow along.

I'd suggest we do any of: specify the behaviour as we understand it from our discussions; leave it as is but add a visible "under construction" comment/warning in that section of protocol.md explaining the discrepancy and/or that it's WIP so that people don't take it as canonical while we clarify; or move the PR to "blocked or waiting". I'd like to merge it so I'd kind of be in favour of the first or second options, but I leave it to your discretion.

Thank you again :)

@cfm
Copy link
Member Author

cfm commented Dec 1, 2025

@rocodes in #126 (review):

the only thing still outstanding to me is the repeated fetching key signatures section. I saw you filed it as a separate issue, which is fine, but I still think we shouldn't merge it into main if it's not our desired behaviour, because it will be confusing for people trying to follow along.

I'd suggest we do any of: specify the behaviour as we understand it from our discussions; leave it as is but add a visible "under construction" comment/warning in that section of protocol.md explaining the discrepancy and/or that it's WIP so that people don't take it as canonical while we clarify; or move the PR to "blocked or waiting". I'd like to merge it so I'd kind of be in favour of the first or second options, but I leave it to your discretion.

Sure. How's c8dd13a, so that we can coordinate the changes both here in the spec and "upstream" in the manuscript around #127?

@cfm cfm requested a review from rocodes December 1, 2025 22:37
Copy link
Contributor

@rocodes rocodes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you - LGTM

@rocodes rocodes added this pull request to the merge queue Dec 2, 2025
Merged via the queue into freedomofpress:main with commit 66d8baf Dec 2, 2025
5 checks passed
@github-project-automation github-project-automation bot moved this from Under Review to Done in SecureDrop Dec 2, 2025
@nathandyer nathandyer removed this from SecureDrop Dec 2, 2025
@cfm cfm mentioned this pull request Jan 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

document generic KGen()

2 participants