**Session Date/Time:** 24 Jul 2026 09:30 [00:00:25] **Prachi Wadhawan**: We are at time. That's a very big room with very few people. [00:00:31] **Siobhan West**: It is. I'm gonna go close the doors. So I'll be back, but I think you can probably start. Who who does Felix go first? Do you go first? Okay. Brenda's. I don't need to click her right away. [00:00:57] **Prachi Wadhawan**: Alright. Shall we show you a start? [00:01:00] **Shubhav**: Yeah. That's right. [00:01:02] **Siobhan West**: Okay. [00:01:05] **Prachi Wadhawan**: Welcome to Keytrans at IETF 120. Happy Friday, you all. I we hope you had an excellent week, and thank you for showing up on a Friday session. We understand it's hard, and most of the people start traveling back. So, yeah, we appreciate you being here. Okay. Let's start with the Note Well. That's the rules and and processes of ITF. Please take a good look at those. We expect you all to follow the processes and policies as listed here. But if anybody has any questions there, you have Deb there. So we appreciate you, Deb, there being our in person delegate as well. Yes. [00:01:55] **Siobhan West**: Gonna make you move up. [00:01:58] **Prachi Wadhawan**: Yes. Please do. Yeah. We can't see any faces, so we really don't know who's in the room. [00:02:03] **Siobhan West**: We now doubled the numbers. We now have eight if they close the door. Oh, k. Close the door, Jonathan. Thank you. Not quite double, but close. [00:02:19] **Prachi Wadhawan**: Well, we'll take everybody in the hallway as well. They're all willing to come in. [00:02:24] **Siobhan West**: It's hard to close the door. I think it's hard to these doors are weird. You're gonna have to take up weight lifting. Excellent. [00:02:44] **Prachi Wadhawan**: Okay. Meeting oh, yep. Sorry. [00:02:47] **Siobhan West**: No. You're good. [00:02:48] **Prachi Wadhawan**: Okay. Meeting tips, you all are probably already aware of. It's Friday. But one thing to note, keep your audio off if you are not actively speaking. But, yeah, let's move on. Okay. For the agenda today, we wanna give a quick update on architecture document, and then Brendan will be talking about the protocol doc updates and Felix and Kai. And I don't see Kai on in the meeting yet. [00:03:25] **Shubhav**: Yeah. I can message him on the side. [00:03:27] **Prachi Wadhawan**: Okay. Thank you, Siobhan, on the client implementations. And that's it. I think with that, we will jump on to Brandon. Let's see. Oh, no. Sorry. First, an update on the Keytrans doc. We have submitted, that doc to IESG for publication, and thank you, Deb. I know you mentioned you'd be taking a look at it after this, week. So thank you again. And then big thanks to Corey for agreeing to be the document shepherd. Alright. Moving on. We'll hand it over to Brendan to talk about the updates on protocol doc. Let me see if I can [00:04:10] **Shubhav**: bring [00:04:11] **Prachi Wadhawan**: up this. Right? Yeah. Go ahead, Shubhav. [00:04:13] **Shubhav**: Yeah. I think we have Timo in the room. I think I saw him come in. [00:04:16] **Siobhan West**: Timo Timo is in the room. Yes. [00:04:18] **Shubhav**: Thank you. Thank you for taking notes, Timo. [00:04:20] **Timo**: Yes. I confirm. I will be taking notes. [00:04:23] **Prachi Wadhawan**: Thank you. Alright. All else, Brendan? [00:04:42] **Brendan McMillion**: Hello. Are you gonna hand me slides as well, or do I do, like, the next slide thing? There we go. [00:04:51] **Shubhav**: Request? Oh, okay. Cool. There we go. [00:04:53] **Prachi Wadhawan**: Yes. Yep. I just [00:04:54] **Brendan McMillion**: yep. Okay. Well, hello, everyone. I'm gonna I'm gonna present updates to the protocol document. My name is Brendan. I'm sure we all know each other. But yeah. So for the first big update, we have monitoring wire formats now. All of the core algorithms that explain how the protocol has been to work have been stable for at least the last two IETFs. However, because there was quite a lot of shuffling around, mostly last year, we didn't have concrete request and response wire formats for the monitoring related operations. So, like, contact monitoring, owner state initial state initialization, and also owner monitoring because I didn't have time to write them. But now I did write them, and so we do have them. And so that's wonderful. I'm not gonna make you look at them because they're very boring. If you just think about, like, what information you would need to do to those operations, that's what's in those wire formats. So that's great. Where things get a little bit more interesting is that there was a change to third party management. So as kind of a recap here as well, third party management is a deployment mode where a third party operates the transparency log. So does they do all the actual work of, like, storing the data and, like, processing requests. And all the service operator really does is just sign new new versions of labels as they're created. The the service operator is the entity that users actually interact with, what that means is that when a user submits an update request, that request first goes to the service operator. The service operator checks if the user is actually allowed to make that sort of change. And if they are, the service operator wraps that request with its own signature and then forwards that to the transparency log, which is actually the manager to be actually sequenced and added into the tree structure. The the previous work wire format captured that idea very, very directly. So, like, it was literally just, like it was literally just, here's the other request, and here is my signature over it. What is funny, though, is that it's actually impossible to implement it that way. So when the service operator signs some new version of a label, Part of what the service operator needs to sign is the version counter, and it needs to sign the version counter because if it didn't sign it, then the manager would have all kinds of opportunities to misbehave, like rearranging the versions of the label. But the version number was not assigned by the service operator. It was assigned by the transparency log as it was doing the actual, like, construction of the new version of the tree. And like we said, in this in this deployment mode, the transparency log is the manager who is also the person that we don't trust to make this decision, and so that doesn't really work. And, also, there's only one signature in the structure, and that doesn't work because an update request can request the creation of multiple new versions of a label. And when you can provide multiple values, and that creates a series of new versions of the label all atomically. And it's it's been like it's been like way for, I believe, about a year. You've been able to do that, but the structures hasn't hasn't been updated in that time. So what I did was I updated it. So now we have this new wire format. The first three fields of this are basically just a straight copy of the user's update request. And then after that, we take all of the new values that the user requested, for for the new version versions of the label, and we attach a signature to each of them from the service operator. So now each new value is signed separately. And then this last field here, signed version, this is the first version counter that the service operator signed and assigned to the first new value that was created. So that's the the signed version field is the version of the first new value, and then the subsequent value after that is signed version plus one, and then the value after that is signed version plus two, and it keeps going like that. But, of course, there there's kind of a change of responsibility here because now the service operator is the one who is authoritative for assigning version numbers. It's not the transparency log anymore. The transparency log essentially just has to accommodate whatever the service operator has decided the version numbers are. And that can get interesting in one particular case because the service operator, as a rule, is not allowed to ever reuse version counters. So if I sign version one of a label and then I submit that to the manager who's running the transparency log and that request fails for whatever reason, I can't sign a different value for version one. I just have to move on to to version two with my next request if I don't wanna retry the exact same value again and again into list of seeds. And so that can lead to cases where there are these kind of gaps of versions that don't exist, where, you know, maybe I tried to create version one, but that failed for whatever reason. And so now that moved on to version two, and version one just will never exist. That is a little bit weird, but it's really not a big deal. And it's just a it's a fairly minor implementation detail to handle. Yeah. And so that's all for third party management. The next place where there's been some decent work is on credentials. So, again, as a recap, credentials are key transparency proofs that are meant to be sent peer to peer, and they're also meant to be verified with no network access. This is really useful for anonymous use cases because when you have a credential, I never need to talk to my own transparency log about other users. I only ever go and talk to my own transparency log about myself to create a credential that I can go and then send to the people I wanna talk to through some, like, secret encrypted channel that nobody can see. And that lets people that keeps people from knowing who I'm talking to, which is quite nice. But the whole credential section was essentially a big to do before, and now it's fully classified. And we have two types of credential. We have standard and provisional, which I will get more into in the next couple of slides, but both correspond roughly to doing a greatest version search for a label. And, also, all credentials are constructed essentially as a reference to a specific, quote, unquote, recent distinguished log entry. And applications already control how often distinguished log entries are created when they configure their reasonable monitoring window. And so now applications also can provide their own definition of what a recent distinguished log entry is. So, a deployment might say that the reasonable monitoring window is twenty four hours, and so we're expecting roughly one new distinguished log entry every twenty four hours. And then it will say that all of the recent distinguished log entries are those that were created in the past, like, seven days. And so then the past seven distinguished bug entries are the recent ones. I'm just looking at a question in the chat. So the service operator is trusted to use is trusted to assign version counters in order. If the service operator issues version counters out of order, that's essentially just not gonna work because the manager is gonna reject it. This is a a collusion secure system, and so the either the service operator is malicious or [00:13:09] **Siobhan West**: in the room. Just come to the mic. He can do it. I'm not even gonna make him join the queue. No. Just go. You're fine. Just talk. There's no reason to do this like [00:13:21] **Prachi Wadhawan**: No. No. [00:13:21] **Shubhav**: We [00:13:21] **Speaker 5**: believe in due process. Right? Yeah. No. So the the service operator, like, can they do one two five? Is that or, like, do they really like, you'll reject anything that's not in the right order? [00:13:40] **Brendan McMillion**: Well, so the the security model for third party management is collision security, and it's only this model is only functional if we assume that either the service operator is malicious or the manager is malicious, but they are not both malicious at the same time. And so the service operator using version counters out of order is the service operator being malicious, which means the manager is not malicious. And a manager that's behaving correctly, essentially won't be able to verify those requests, and it will reject them if the version counters come out of order. [00:14:19] **Speaker 5**: Okay. Because you could it's quite easy to like, there's a really good paper about how you have fair coin flips from if you have a pocket of coins, half of which are compromised by the KGB and half are compromised by the NSA because you assume that they don't collaborate and therefore each of their best strategies is to give you a random coin flip. It's not you could have two people being malicious without them collaborating. [00:14:52] **Brendan McMillion**: Yeah. That's an interesting point. But I believe also the example you gave was 125. Was that correct? Yeah. [00:15:00] **Speaker 5**: Or or 12 132. But, like, yeah, 125 would be bad. [00:15:04] **Brendan McMillion**: 125 is actually fine because the version counters are assigned monotonically. So what matters is the version counter always increases. And like I said, sometimes because requests are dropped, certain versions don't exist. Mhmm. But as long as they are done monotonically. 132 is an issue because it's not monotonic. [00:15:26] **Speaker 5**: And 133. Right? That would be monotonic. [00:15:28] **Brendan McMillion**: 133, yeah, is also an issue. [00:15:30] **Speaker 5**: So, yes, just strictly increasing. It's even stronger than monotonic. [00:15:34] **Brendan McMillion**: Yes. Thanks. [00:15:38] **Felix Linker**: So I thought I'd wait until the end, but now that we're discussing this version counter management, I'll jump in anyway. I wonder what the benefit of the service operator no. What the benefit is of the service operator managing the versions. My impression is these versions are an artifact of the log. So it's overhead for the service operator to manage these version counters without any real benefit. Yeah. I'm probab I mean, the intended use of KT is that people just use the latest keys of each other, and older versions are just there for monitoring purposes, so for the log. So I would expect the service operator to have some database where they have every user's latest key. And whenever they get a request to update it, they just throw it at the log and update their database, and that's it. So why not just send an update request to the service operator and get back a version counter, and then you may check that, but you don't have to care which version of the user you now wrote? [00:16:47] **Brendan McMillion**: I'm not sure I'm totally following. Like, are you saying that you don't want the service operator to have to maintain the version counters? [00:16:56] **Felix Linker**: Yeah. I mean, service operate so I I maybe more generally, I don't want to force service operators to maintain version counters because I don't see it I don't see it as being necessary. Users should be able to look at their version counters by interacting with a log operator just fine, And the service operator probably just needs the latest key. So they like, whenever there's an update, they just give it to the log, and then they they can all I mean, I don't wanna stop them from handling the version, but it seems simpler to me to just have the log and monitor the version and handle the version. And if the service operator really wants to be meticulous, they can check all the versions in the lock themselves. [00:17:38] **Brendan McMillion**: The issue is that I think that it is necessary from from a security standpoint for the service operator to keep track of the versions because part of the security guarantee here comes from the fact that the service operator is signing every new value for the label. And so if we say, okay. The service operator is only gonna assign the label and the value, and it's not gonna assign the version counter, then what that lets the manager do is it has basically a big set of acceptable values for this label, and it can present them in any order. It can present any of them as most recent. [00:18:18] **Felix Linker**: Yeah. But the service operator could detect that. No? [00:18:29] **Brendan McMillion**: Oh, if you if you [00:18:30] **Felix Linker**: you can you can just submit an update and then check that it was included correctly. Right? [00:18:39] **Siobhan West**: Go to the mic. There you go. You can even come to this mic if you want. Pick a mic. [00:18:46] **Speaker 5**: Maybe I'm just missing something. It is Friday. But if the service operator isn't keeping track of the number, how does it know whether the log added it correctly? [00:19:01] **Felix Linker**: Well, I I I understood Brendan's attack as let's assume we have one fixed pseudonym and we have five key updates. We just give them to the log operator. Yeah? Now the log operator is free to mix them in any order. That is correct, but only under the assumption that we're giving them five updates for the same label simultaneously, which I don't think is the typical case, right? The typical case is you have one key update. You give that to the log operator, and then you can wait for the log operator to include it. And then you can just check, did they include it as the last version? And if so, I'm good. And now I can forget about all the past because I know up to this route everything was fine. So you maintain an invariant on the order of numbers. Only if you allow multiple key updates submitted in parallel can the log operator do some shenanigans, but I think we can just tell the log operator to not do that the service operator to not do that, which is a good idea anyway, I think. [00:20:04] **Brendan McMillion**: I mean, this idea of checking checking if the update was done correctly at the time that it was done doesn't work because, yes, you can check that the update was done correctly in, like, the next log entry after you requested. But the issue is that there are more log entries that come after that, and they can all be different because the manager has complete discretion in how each of those looks. And so you would need to go through every single log entry and check that every single log entry is correct for that idea to work. [00:20:39] **Speaker 5**: What what is the semantic meaning of having multiple updates in a single log entry for a given pseudonym? [00:20:51] **Brendan McMillion**: It having multiple updates for a single label, it essentially means that they're created atomically. So you still have, like, version one, version two, version three. It's just that they all appeared at the same time in the same log entry. [00:21:09] **Speaker 5**: So you would only ever use the last one. So the middle one or the first and second one in that case would never have been valid at any point? [00:21:20] **Brendan McMillion**: You can look up any version of a label that's a valid thing to do. Like, only ever looking at the most recent version of a label is that's like a a subset of the KT functionality. You can look up any version and those requests are all authenticated. [00:21:36] **Speaker 5**: Right. But, like, why why we could just as easily say you're only allowed to do one update per key entry per log entry, and then we don't have this case at all. And so I don't understand what the semantic addition is to do multiple in a single like, I understand what it would mean in the protocol, but, like, what what's the purpose of it? [00:22:06] **Brendan McMillion**: I mean, I'm not sure if I know of, like, a specific application example, but it's something that we can do is create an arbitrary number of new versions of labels in a single login tree. And the update request format supports that. [00:22:24] **Daniel Harkins**: So I'm not sure Daniel Harkins proton. I'm not sure if it applies in your model, but we did have this exact discussion in in key transparency for Proton, and we made this change where originally we had just the latest one. Like, if you make multiple updates to your keys between two epochs, then we would originally just store the latest one in a new epoch. But we made a change to store all changes such that if one client makes a change and then another client makes a change between two epochs such that there are two changes that end up in the new epoch, then both clients can check that their own changes end up in a new epoch. Whereas if one client makes a change and then another makes a client makes a change that overwrites that, then the key transparency log operator could, yeah, only include the second one, and then the first client can't really check whether, you know, stuff happened properly. So they would have to warn the user or something. So, yeah, by including all the changes, it makes it easier to do the self audit in in our model. I I guess the same would apply here maybe. [00:24:11] **Brendan McMillion**: Yeah. It sounds like they probably would apply in a similar case here. Do you wanna talk more about this? Okay. That sounds good. [00:24:26] **Felix Linker**: Yeah. I I think I Felix Linker, I think I understood it now. So and I'll just share my understanding with the working group. I think the problem is actually accountability. Right, Brandon? If the version were unsigned, the log operator could do some shenanigans with the log, which the client would definitely detect. Right? Because there is something going on that they didn't ask for. But then the log operator could blame the service operator, and the service operator could blame the log operator, and both would have a plausible story. Right? So yeah. [00:25:11] **Brendan McMillion**: That sounds about right. I don't agree with the statement that the user would detect it because I don't think the user would detect it, but I think that I would have to, like, work out an example offline to make that case. [00:25:23] **Felix Linker**: Well, if there's an attack by on on the client that by a collusion from a service and log operator, I would presume that attack also exists in the case of where we don't have third party management because the log and the service operator are now the same. So, like, there shouldn't be any attack on the client that the client can't detect no problem. [00:25:48] **Brendan McMillion**: Well, in a context of monitoring deployment mode, we are doing we're having the client do more work to verify that the transparency is behaving correctly. When we have, like, third party management, essentially, there's never any contact monitoring. So a lot of times, clients, if they look up something and it's, in a very recent log entry, the client just says, okay. That's great. And forgets about it because that's the point of having the second trusted party is so that I don't have to maintain the state. [00:26:19] **Felix Linker**: Oh, I didn't know. For me, third part oh, and and never thought of third party management as that. I mean, you know, I don't object against such a deployment, but shouldn't one make it independent because third party management might be nice for some services regardless of whether their clients perform contact monitoring or not? [00:26:41] **Brendan McMillion**: I think the architecture document maybe says something like applications should allow users to turn on contact monitoring. So it's something that you potentially can do, something that you can put something that you potentially can do, but it requires kind of jerry rigging the client to pretend that it's in a different deployment mode than it is. [00:27:06] **Felix Linker**: Okay. I I wouldn't to look at this in more detail, but it seems like a like a no brainer to allow more flexibility. Yeah. Yeah. Yeah. We we don't have to discuss it now. Thanks. Okay. [00:27:24] **Brendan McMillion**: And so I'll go back to to credentials. So we were talking before, about this idea of of recent distinguished log entries. So, applications already have this parameter called the reasonable monitoring window, which they use to configure how recently distinguished log entries are created. Now there's an extra layer on top of that where applications also define some concept of a recent distinguished log entry, which, is basically a subset of the distinguished log entries. So the example I gave was you might have a reasonable monitoring window that is twenty four hours. So we expect one new distinguished log entry every twenty four hours, and then we say that the log entries from the last seven days are recent. So then we have about seven, quote, unquote, recent distinguished log entries. And the idea here is that applications would package up and ship out all of these recent distinguished log entries to all of their users. And then users would have all of these essentially common points of reference that they could use to verify credentials against. And because credentials are all based on some distinguished log entry, what that means is that, a credential is only valid for as long as a distinguished log entry is considered recent and for as long as it's been shipped out. So once distinguished log entry is issued and users know about it, you can issue a credential against that distinguished log entry, and everybody can verify it. As time passes, that distinguished log entry is no longer gonna be considered recent. And then once that happens, any credentials that were based on it essentially are expired and need to be replaced. So that's credentials generally. To dig a little bit deeper into standard credentials, a standard credential is one where the version of the label that we want exists in the specific distinguished login tree that we built our credential on. And here is the kind of structure that shows how our how our credential looks. So it starts with the label for the credential. It's the very first field. And then you have a couple of fields that basically exactly match what you would have in a search response for a label. And then after that, you have the position of the distinguished log entry that the credential is based on just to signal to the verifier which distinguished log entry I'm using. And then the very last part of this is that you have prefix tree lookup that contains a binary ladder from the distinguished log entry that we indicated that identifies the greatest version of the label. And then that is the whole thing. It's essentially a pared down greatest version search. External credentials are are kind of nice because they are actually relatively small, and they're relatively fast to verify. So you'd actually expect a standard credential to be a little bit smaller than an equivalent search response. Standard credentials also will never trigger contact monitoring. So if you successfully verify a standard credential, then that's it. You can kinda move on with your life, which is quite nice. To contrast with that though, we have provisional credentials. A provisional credential is one where the version of the label that we want doesn't exist in the distinguished log entry. Well, it doesn't exist in the distinguished log entry that the credential is based on. That's not to say that it that the version of the label doesn't exist in any distinguished log entry, like, it does. Maybe this is just an old credential or maybe the the user that made the credential intentionally used an old distinguished log entry to maybe mitigate issues with clock skew. But yeah. So the the vast majority of the fields and a provisional credential are exactly the same as in a standard credential. But now instead of that single prefix tree lookup proof, we have a signed tree head and a combined tree proof. So this is a less pared down greatest version search, and you verify it again like a like you would a search request or search response. Provisional credentials are somewhat larger because they have this more verbose proof structure, and they're also a little bit slower to verify. They will also typically trigger contact monitoring, though not always. But what it means when, when a credential triggers contact monitoring, the way that we handle that is with what's called a credential update structure. So so when a user sends a credential to another user and that user knows that verifying the credential would result in a contact monitoring application, That user is required to also within a bounded amount of time send this credential update structure, which is basically just the contact monitoring information that is wrapped up in a little structure that you can send peer to peer. And users are incentivized to actually send their credential update structures when they're supposed to because if they don't, the user that receives the credential, they receive the provisional credential and verified it. The only way for them to maintain their security is to essentially go and request this credential update structure from the transparency log. And that can potentially affect the anonymity of the sending user because now we have the recipient user going to the transparency log and asking about the sending user. It's I mean, I suppose the anonymous way to handle that is just to contact the transparency log over an anonymous channel. But that's, I guess, that's more of an implication specific consideration. But, generally, yeah, this is basically just contact monitoring. It's just in a different structure for credential purposes, and that is it for credentials and moves us on to a new operation. Oh, yes. Ori? [00:34:04] **Ori Steele**: Hi. Ori Steele. I'm sorry that I haven't been able to keep up with all this stuff, but why do we need provisional credentials? Like, you mentioned this clock skew issue, but it's sort of concerning how much operational stuff you'd have to do to maintain the privacy properties with this this thing that you just mentioned. Like, just, like, maybe use case or, like, brief comment on, like, why provisional credentials are needed in this, you know, first version of part of this work. [00:34:37] **Brendan McMillion**: Yeah. So provisional credentials, the purpose of them is that they let you issue a credential for a version of a label sooner than you would otherwise be able to. So in a deployment where your your reasonable monitoring window is, like, twenty four hours, what that means is that anytime you create a new version of a label, it could take up to twenty four hours to have a distinguished log entry that contains that version of the label. And so because of that, you wouldn't be able to have a standard credential until you wait the full twenty four hours. With the provisional credential, you could make a a credential much sooner. So that's the purpose of it. [00:35:15] **Ori Steele**: It's like a trade off between, like, the the timing availability and the privacy properties of the system, basically. [00:35:23] **Brendan McMillion**: Yeah. It's more complicated, but it's a lot faster. And in applications where anonymity is super important and, like, it's not possible to do this in a reasonable way, I think that it would be totally reasonable just to not allow provisional credentials. [00:35:38] **Ori Steele**: Yep. I'm the other just comment I had, you know, is the word provisional makes me, you know, curious about how reliable, you know, the credential will be long term. So I know naming is our favorite topic, but it's yeah. That's it. Thanks. [00:35:53] **Brendan McMillion**: Thank you. [00:35:56] **Timo**: Yes. Think somehow on a similar question, I've seen the slide that, like, you will discuss deployments and etcetera, like, down the line. I do understand, like, the need, I think, for, like, this type of provisional credential. The main question I have is, are the deployments which are asking for it and which, like, would actually be looking into, like, implement it and, like, deploying these? [00:36:22] **Brendan McMillion**: Actually, yes. So if you were to use KT and MLS, credentials are necessary because MLS is entirely credential based. [00:36:32] **Timo**: Okay. So it's more, at the moment, as I understand, some kind of, like, use cases that we foresee that, like, KT could use, but not necessarily, like, seeing that people are like, there's no draft in MLS that, like, would use that. Right? [00:36:48] **Brendan McMillion**: We are obligated to write a draft in this working group that describes how to use QT with MLS. That's kind of been paused for a little bit because there's no, like, interested deployments, and so we might drop that. But yeah. [00:37:09] **Timo**: Okay. Thank you. [00:37:12] **Felix Linker**: So although it's dangerous to speculate to speculate about the state of mind of others, while looking while seeing the updates to the credentials, I started wondering, isn't that all a bit brittle and and a lot of work? For what? I think it and now I speculate maybe Ori and Timo had similar feelings, although they should say that themselves. I was wondering whether it could make sense to spin out credentials and related text into its own draft because it seems it definitely seems valuable. I also could see deployments like Signal using it who have yeah. I don't know how it's called, but they also have this encrypted [00:37:57] **Brendan McMillion**: Field sender. Yeah. It's Yeah. Exactly. It as well. [00:38:00] **Felix Linker**: Definitely makes sense, but the draft is already quite complex. And I think keeping it scoped to the core functionality would make it easier to digest. And since credentials go completely on top anyway, it seems like an easy win to make the draft a bit leaner by, yeah, writing a draft that uses the protocol draft for credentials. What do you think about that, Brandon? [00:38:30] **Brendan McMillion**: I think I would need to address that a little bit more because the text is already in the protocol document, and so I'm a little bit attached to it. But I could maybe see that being a good change. [00:38:45] **Siobhan West**: You could move the text to another document and still be attached to it. Yeah. That that's that's Yeah. [00:38:57] **Felix Linker**: I'm I'm I think it's a it makes design is reasonable, and credentials make [00:39:03] **Brendan McMillion**: sense. Just like a lot of deployments do actually need credentials. Like, if we were to ship a KT protocol that was just the request response flow, that would work for surprisingly few deployments. Like, it wouldn't work for any MLS deployment, for example, like I said. [00:39:19] **Felix Linker**: Yeah. Could be. I mean, we don't need to decide it now. It was my thought. We can see later just as input. Thanks. [00:39:27] **Ori Steele**: Alright. Or it's still I I think, you know, for the the the reason you just mentioned, Brandon, like, a lot of deployments are gonna need credentials. As a reader of the document, I probably would like for them to stay in one, just random person opinion. Thanks. [00:39:47] **Brendan McMillion**: Okay. Cool. Thank you. So yeah. So there's also a new operation that was added. We added a new operation because there was kind of a gap in the protocol's functionality specifically. So first, to verify credentials that we've been talking about, users need to know the full set of recent distinguished login trees. There's also a second point that users that want to use some kind of mechanism to detect forks, like gossiping with other users. They need something specifically that they can compare as a point of reference with other users, and the recent distinguished login trees are kind of perfect to have these kind of comparison points. And then thirdly, as kind of just a purely technical point, users that wanna make an owner init request, and so that's to initialize state to own a label, You need to specify a distinguished log entry in that request for where you want your ownership to start, and you can't do that unless you know a distinguished log entry. And the idea kind of in my head historically was that people could just use owner monitoring to learn about recent distinguished log entries, but that's kind of messy. It also is just funny to say that you need to do owner monitoring to learn about distinguished log entries to make an owner init request. Like, that doesn't that doesn't really make any sense. So the way this operation ends up working was basically it's just a a right to left depth first search for all of the distinguished log entries that meet the application's definition of recent, whatever that is. And then users can also optionally provide a stopping point that represents a distinguished log entry that they already know about. And the point of that is just to say that if we reach this point, I already know about everything to the left of this, so we can just stop the search early. And, also, the text in this portion of this back provides some suggested definitions for recent, including, you know, one of the in rightmost distinguished log entries. That's a very good definition of recent. Or you could say that the log entry time stamp is less than x seconds in the past. That's also a fine definition. It's kind of whatever applications wanna do. [00:42:07] **Shubhav**: Hey, Brandon. Just a time check. So we are at time for your slot, but I think we can go for, like, maybe three, four minutes as long as Felix is okay doing his slot in, like, five minutes. Did we hear from him? Mhmm. And we haven't heard from Guy. So so, you know, it's yeah. Maybe he was planning to hop on later. But, yeah, we can okay. Sounds good, Felix. So maybe we will just give you both the rest of the the time and then ask Guy to give his update next meeting. [00:42:44] **Brendan McMillion**: Okay. That sounds good. These are the the white formats for this new operation. I also added a new section in the appendix. So that's actually something that I requested from last meeting is the document has two similar concepts that interact in very subtle ways. So we have the maximum lifetime, which is the amount of time after which log entries are deleted and users never touch these log entries. We also have the reasonable monitoring window, which is the the general frequency with which users are expected to perform monitoring. And the this sort of new appendix section explains why, among other things, that there's always at least one unexpired distinguished log entry for users to inspect. So there is always some common reference point essentially that users have to look at. It explains why contact monitoring is guaranteed to terminate within one interval of the reasonable monitoring window. And so if you do have to do contact monitoring, you're guaranteed to be able to finish within this very tight bounded amount of time. And, also, a user that is performing monitoring, whether it's contact monitoring or owner monitoring, at least once per every interval of the reasonable monitoring window will never need to monitor an expire an expired log entry. And so, essentially, their monitoring never has a valid reason to fail. Their their monitoring should always be able to succeed as long as they are able to to contact the server. So next steps the only next step is really that I'm probably gonna be asking people to review the document before working group last call so that working group last call can go smoothly. And so if you hear from me, that might be why. And then I quickly also wanted to talk about implementations. So my implementation, KD, is essentially complete. It could be improved with some documentation or some more thorough tests, and that really is my goal for the next couple of weeks is just to make this, like, a very nice productionized open source code base. And kind of as a final thing, I thought that it could possibly be fun to play with some of the cogeneration tools that are getting so much attention and see if that could maybe give me any insight into the quality of the the protocol document. So I basically what I did is I put the architecture document and the protocol document in an empty Git repository, and I loaded up on these tools. And I told it, you know, here's documentation. Please implement the claim in the server and try to see what would happen. And so what did happen is that it read the documents. It worked for about an hour consistently. It consumed about $40 in tokens, which was just, the maximum spend that was configured for for the session. I didn't know that there was a maximum spend, but there was. In that time, it wrote 30 files, 7,000 lines of code, and it actually implemented the vast majority of the protocol document. It only omitted some functionality like credentials, actually. It also found one pretty substantive mistake in the spec and also in my reference implementation. And it found about 10 drafting errors, is what I've been calling them. So kind of like typos or descriptions of things that don't make sense. It it pointed those out. And they find the headline result was that all the code it produced was correct, and it was wire compatible with my reference implementation, at least as far as I've been able to check, which is kinda crazy. And, I mean, I wanna kinda verify this claim a little bit more thoroughly, but yeah. I mean, it seems like this would be a pretty strong signal of that given just the specs and, like, time, it should be possible to get a correct and working implementation. And, hopefully, that's a little bit of validation that we are pretty close to to working group last call with this document as well. And that is all that I have. Thanks so much everyone. [00:47:19] **Prachi Wadhawan**: Alright. Thank you, Brendan. I will go ahead and get your slides up, Felix. [00:47:29] **Siobhan West**: And you're gonna give him the clicker once you bring the slides up. You have to take the slides back, I think. [00:47:41] **Prachi Wadhawan**: Oh, that's why. Nope. Not working. [00:47:54] **Siobhan West**: No. Siobhan. Yeah. Siobhan took it. [00:47:58] **Shubhav**: Good try. [00:48:00] **Siobhan West**: So now open the [00:48:05] **Felix Linker**: Okay. Cool. Thank you. Yeah. I'm going to present progress on the key transparency client implementation, which eventually, hopefully, will have a proof of security with it as well. But today, I'll just report on the implementation itself because it made me develop opinions on the draft. [00:48:22] **Siobhan West**: You don't quite have the clicker yet. Prachi, can you give the clicker to you should be able to do it like you do to a person. There you go. Okay. [00:48:35] **Felix Linker**: Great. So what has been implemented? You see link and QR code to the implementation in a particular branch because it's all very work in progress on the on the slides here. I implemented a client maintaining state, updating their view, and performing greatest version searches. What are some obvious limitations that are that should be mentioned? The client I didn't implement the monitoring yet. The Cypher suite is hardcoded, and my code is not interoperable yet with Guy's implementation, which I'll discuss later. It's also not interoperable with Brenton's implementation because I couldn't figure out how to get search request response pairs. If I can get some test vectors, that would be great. As a side note, the code is proven to be memory safe, so it doesn't panic, and all array accesses will will be within bounds and these kinds of things. I don't think that's too relevant. It's for you. It's nice to have, but it's a requirement for further analysis, and it's very painful to prove code memory safe after the fact. So it's just already done. So today, I want to make three points that were all motivated by me finding the implementation of certain parts of the draft quite hard. I find the prefix proof structure is hard to parse, and I think it could be structured easier. Data structures are often described implicitly, and we are setting us up for noninteroperability. Yeah. These are these are will be my three points, and I'll go and I'll make my case one by one. So what you see here is the information flow of my implementation. Over the wire, you get more things than than what you see here, but it's yeah. These are the essentials. You get an inclusion proof. You get a number of prefix proofs. You get a binary letter structure. And then I first take the inclusion proof and an old stored version of a log tree. I build a log tree. The prefix proofs and the binary letters are used to create the prefix trees, and the log tree also flows into the construction of the prefix tree because while constructing them, I check that the roots of them are correctly inserted into the log tree. And then I use the binary letter to create a what I call a lookups data structure. It's just a helper data structure that will then perform the checks in the prefix tree later. And then the prefix tree and the lookups go to the into the verification algorithm that checks everything. So, yeah, especially the construction of the prefix trees will lead to implementation pain, I think, and I really didn't like the dependency of the prefix tree construction on the binary letter because I found myself going in circles reading first the binary letter, then the prefix tree again. And I think it would be much better for testing and ease of implementation if the prefix proofs were not dependent on the binary letter but self contained. So currently, you the the prefix proof is a data structure that is quite complex and has a couple of branches, and I think we could simplify it. So the prefix proofs omits all information that is included in the binary letter, and that makes sense for reducing the size of what is sent over the wire. But I think this is the main point that leads to the complexity you see on the left. I think what you instead could do is just give the client a number of leaves that come with information about the hashes or the commitments and VRF outputs it can find at a certain depth, and then one should be able to implement the prefix tree construction, and I already I already wrote the code, but it's untested, to to just do a depth first search implicitly over an empty tree, consuming the leaves in this array from left to right, and then put putting them in the prefix tree. Whereas in the current implementation, what you have is to do is you have to merge in the results from the binary letter in the prefix proof. Oh, okay. Maybe you don't have to. That is my implementation. So what my implementation does is it takes a prefix proof, and then it goes over the prefix proof with and the binary letter together and puts the binary letter in the right places in the prefix proof, so it enriches that. Then I create an empty tree. I go over the prefix leaves in the prefix proof, and I insert I force insert them into the branch, and then I do another depth first search from left to right to enter missing hash values, which is possible because I implemented it and I'm interoperable with myself. But it it was very hard. Yeah. It it was very hard, and I think and hard to test also. It it took me a lot of code to get to the point where I could test my code, so it was hard to modularize. And with an easier prefix tree prefix proof structure, I think that would be easier. The problem that I stumbled over was also that a lot of data structures where they are defined are described implicitly. So my witness here is the combined tree proof, and if if you sometimes I just forgot what exactly was in the combined tree proof. Yeah? So what I do is I go to the draft, to the combined tree proof, and I read the text. And then the description of the text I didn't find helpful at that point. So for example, it says the timestamp fields contains the timestamps of specific log entries. Okay? And then graphics proofs contain search proof for the prefix trees of specific log entries, and there is no indication as to the order because they are provided in in the order that the algorithm, the user executing, would request them. I think this is technically underspecified. This refers to some naive implementation or, like, the obvious implementation of the client, but I don't think it's actually specified in what order the client checks the prefix proofs. I mean, I mean, I see there is the obvious order, and I think I implemented it the like, there's an an obvious order to go through this, but technically, it's underspecified. And then there's also a note on the in the timestamps, but that some things that there will be let let me read it. The l m yeah. You there's an order, and then you provide some proof prefix proofs where no search proof was provided. And I I actually find it hard to parse the text on stage right now, but, again, my question was which ones? So I think a lot of the data structures are described in terms of corollaries. So you it says, you know, that, like, if you think about this part of the draft and think about that part of the draft, you can deduce that the prefix proofs included here will be such and such. But I think that for me, this was often nontrivial. I often hypothesized potential invariants of data structures, and then I thought a bit I either asked Brendan, who was very helpful. Thank you for your input, Brendan. I either either asked Brendan, I thought a bit longer, can this be true? Will it be that in this data structure, you will always have the prefix proofs in that structure? And I think we should just make it explicit. That makes it harder for the authors because you need to ensure internal consistency of the document, and if you just refer if you just describe implicitly how how something is structured, you you get out of JF for free, but it makes it much harder for the implementers. And I think it's better to do this job as the authors. Yeah. Brent, go ahead. [00:56:46] **Brendan McMillion**: So I don't think this was meant to be described, like, implicitly, but the structure of the combined tree proof is that it's meant to be almost like a transcript where we have these algorithms to describe where they say, I want this timestamp, and then I wanna look at this timestamp, then I wanna look at this timestamp. And the combined tree proof should be, like, a log of, like, timestamp a and then timestamp b and then timestamp c. And I I didn't I didn't mean to be implicit. It's supposed to be, like, a transcript, you know, if that makes sense. [00:57:17] **Felix Linker**: Yeah. I mean, I think the the data structure is good. Right? I'm not I from the the issues that I've found were that by defining it as a transcript, if you just scratch your head, oh, I wonder what the combined tree proof contains, and you go to the section where it defines it, you don't know. You learn you learn very little about the combined tree proof if you look at this structure. You have to, in your head, think about how the algorithm works and then infer the order of the transcript. I think it would my suggestion is not to change anything about the structure of the combined tree proof here. I think it's it's a good proof. It's a good wire format. But to just make it explicit what you get. So this will introduce some redundancy into the draft, but I think it will make it much easier to implement. And [00:58:13] **Shubhav**: Felix, just time check. You have about two minutes, I think. [00:58:16] **Felix Linker**: Oh, sorry. Yeah. Okay. I'll I'll jump to my last point. Okay. Yeah. This is what I just said. And then for interoperability, Guy was so kind to send me some easy test vectors, and result was unfortunately that our code is not interoperable because he uses protobuf. And then I told him, hey, Guy. Why do you use protobuf? Don't we use TLS? And he said, well, the draft says you can I can do whatever I want? And then I thought, yeah. Okay. That's true, I guess, but that's not ideal. So I think we should suggest a concrete wire format so that if someone just reads the draft and doesn't think about [00:59:01] **Siobhan West**: He can't do the job. [00:59:02] **Felix Linker**: Okay. Sorry. I'll look I'll look at that later. So I think we should agree on a default wire format that we tell everyone to implement. As they say, there is no protocol police, if people wanna use a different wire format, they can do so. But by having a default, we can at least try for as many implementations as possible with as little overhead as possible to be interoperable. [00:59:29] **Timo**: I 100% agree. That's one of the issue we had in the initial implementation that that we did. There's also other issue with protobuf, [00:59:37] **Brendan McMillion**: which is [00:59:38] **Timo**: I would not recommend protobuf if we go to recommend a wire format. But, yeah, 100% agree with this point. [00:59:45] **Felix Linker**: Yeah. And, yeah, that was my summary. So in summary, I suggest these three changes to the document. And is there any discussion on that? [00:59:58] **Shubhav**: Just that we have about thirty seconds. I'll I'll lock the queue now. But, yeah, go ahead, Ori. [01:00:03] **Ori Steele**: Alright. Worst deal. As much as I love, you know, CBOR and JSON and, you know, concrete wire formats, the the CT log did not specify one. The proof structures were all sort of defined as nice labeled binary blobs. I think if you got to this point without having one, it's a bad idea to add one. Just make sure that each of the little binary blobs has a clear name and leave it to someone else to figure out how to pack them into CBOR and JSON. It's my advice. [01:00:34] **Felix Linker**: But one comment on that. I don't think there are any binary blobs. Right? So the the the data structures are defined in TLS language, but that's just the the the definition of the structure. The binary blob could be whatever. [01:00:53] **Siobhan West**: Maybe Ori needs to take an action to read the draft. [01:00:57] **Ori Steele**: That's true. [01:01:00] **Shubhav**: Cool. I think we're out of time. Thank you, Felix, for the presentation. [01:01:11] **Prachi Wadhawan**: Alright. Thank you, everybody. We'll follow-up on the mailing list. [01:01:16] **Shubhav**: Thanks all. Thanks, Deb, for being our in person delegate yet again. [01:01:20] **Siobhan West**: Yep. EG p g. [01:01:22] **Prachi Wadhawan**: And thanks, Yep. [01:01:26] **Shubhav**: Yeah. Thanks, Timo. Perfect. [01:01:33] **Siobhan West**: Getting up at the crack of dawn.