 Thank you very much. So yeah, this is a joint work with my former and recently graduated student, Vinicent, who unfortunately couldn't make it here to give the talk. So broadly, this work is about designing functions that are moderately hard to compute and in addition to being hard to invert. These are, of course, useful in particular in the context of hashing passwords, but also be used, say, for proofs of work in cryptocurrencies. And moderate hardness here means that on the one hand, the function should be sufficiently expensive to compute, for example, to slow down brute force password cracking attacks, but on the other hand, it should not be excessively expensive to slow down or to affect the performance of a system using it, right? And hence the balancing act. So also these moderate hardness should be somewhat egalitarian. So we will wish that dedicated hardware should not give significant benefit in evaluating the function. And not that this property is really not obvious to enforce, for example, legacy password hashing algorithms do not satisfy it. And so in an effort to satisfy this property, the notion of memory hard functions was proposed. And a memory hard function, or MHF for short, is a moderately hard function that is subject to a time memory trade-off in its evaluation. So what I mean by that is that moderately fast evaluation requires large memory, whereas with small memory, devaluation should be slow. And this should imply a high area time cost, for example, in hardware, which in turn implies a high dollar cost for fabrication of the hardware. And so the goal of memory hardness was present in a number of practical designs for password hashing, including S-Crypt and Argon II, the winner of the password hashing competition. And also there was a substantial effort in the theoretical end to validate the memory hardness of this design, which has led to a large number of papers over the last few years. And if your paper is not up here, it really just because they ran out of space. There are really many papers in this corner. But a common denominator of all of these works, which is the starting point of this work, is that they all treat memory hard functions as modes of operation of some underlying monolithical hash function. As you will see, this is not really an accurate model for reality. But before I get there, just to be a little bit more concrete, let me first introduce the large class of memory hard functions that we will deal with in this work, which is that of data-independent memory hard functions, or IMHFs, which include most designs to date. So an IMHF is defined by a direct acyclic graph, or DAG, G, which is a certain number of vertices, and one of more sources than things. So in this example, it's one each. And the evaluation of the function proceeds by assigning labels to vertices. And in particular, this is implicit here and in the rest of the talk. But the source labels are going to be some value dependent on the actual input to the function. And every other label of a vertex is the output of a so-called labeling function applied to the labels of the predecessors. And finally, the output of the function is the label of the sync. Now, in all of these analysis I mentioned before, the labeling function is a monolithic hash function, which in security proofs is modeled as a random oracle. And so a method theorem here will tell you that if the graph has some good combinatoria property, then the function is memory hard in the random oracle model. So here we want to have a closer look at this assumption that the labeling function is a random oracle. And in particular, if you look at concrete distanciations of memory hard function actual designs, what we see is that the labels are usually very large. So we're talking about thousands of bits. And so it's already very hard to use an off-the-shelf hash function. And plus you might want some more properties that we'll see later. And so what designers do instead is they come up with a dock constructions, I mean, usually based on some underlying primitive. Here it's a permutation. And these designs are usually not random oracles at all, even if you assume that the underlying primitive behaves ideally. So this is an example of a design which is inspired from what Esprit does, but I could have put here the design of Argon2. Jeremiah's going to talk about in the next talk, and it's a similar story. And so we would like to understand what's happening under the hood here. And this was really not done, and it's not clear whether existing analysis apply to actual constructions. So I should mention here that Jeremiah in the next talk is going to talk about some concurrent work that also started looking under the hood and see what happens within actual constructions of labeling functions. Okay, so the main goal of this work was really to initiate the study, and it's really mostly at a theoretical level, as you will see, of the security of constructions of labeling functions and the memory hard functions they're used in when they are built out of simple primitives. And we are going to look at permutations. We also look at constructions from block ciphers and compression functions. Now there are really two main challenges when doing this. The first one is dealing with the primitives themselves. So even if we model them as ideal, so as random permutation or ideal ciphers, as we do in proofs, the techniques that we have so far are really inherently tied to using monolithic random molecules, so we need new proofs. And also understanding what is a good construction of a labeling function is really a hard task to start with. In particular, we don't have any good notions. You might think, for example, that using the notion of indifferentiability that tells us when a construction is a good random molecule in an ideal model would work, but actually memory harness deals with memory-bounded adversaries and the resulting security games are multi-stage games, and we know that indifferentiability doesn't apply to them. So we don't really even know where to start. So in further talk, we'll specifically focus just on the case of permutations. I think it's the most important one. So these are efficiently computable and efficiently invertible keyless permutations. So this is the case as far as I know in most practical designs. And also permutations are attractive, for example, because you might think to instantiate them from fixed key AES and build a memory-hard function out of that. And one attractive feature of that is that your CPU mostly comes with hardware-based efficient implementation of AES, and this will help you already, already the primitive level, reduce the gap between a software and a hardware implementation. Okay, so the general blueprint here is that we start from some DAG, and now we want to build a memory-hard function out of it by instantiating the labeling function from some underlying permutation. And technically, we really have to look at two distinct cases here. The first one is what I refer to as the small block case. This is the case where the labels assigned to the vertices have length which is equal to the input-output length of the underlying permutation. And then another case, which is what most commonly happen in practice, is the white block case where the labels are actually much larger by a multiplicative factor K. And then so we have to build something which will make multiple calls to the underlying permutation. And we'll start with the simpler small block case. Now, a little bit more concretely, the way we will formalize memory-harness in this talk is by looking at the cumulative memory complexity which was introduced by Avan and Serbinenko which looks at the memory usage at every point in time during the evaluation of the function and then sums these memory usages up. Okay, and a little bit more formally, we will consider an adversary that will need to evaluate the function on an input M and its execution will proceed in rounds and at every round, the adversary will make queries to the permutation which we model as a random permutation and in particular, we'll make a vector of parallel queries which might be both forward and backward queries and then produce a state for the next step. And in the next step, the adversary will get the state and the answers to these queries and then these over and over until in the final step when ready, the adversary will output the output of the function on input M. Now, and here the cumulative memory complexity of an execution is just the sum of the sizes of the state. Now, a related quantity is that of the cumulative pebbling complexity of a graph. So here we look at a DAC that might define an MHF and we consider a combinatorial game where the adversary at any point in time can place a pebble on a vertex if all of the predecessor vertices have a pebble on them and also in the same step can remove any of the pebbles. And the goal is to place a pebble on the sink of the graph. So if we look at the strategy, we want to characterize its complexity and what we're gonna do, we're gonna look at the size of the different pebbling configurations. So for example, we might have a strategy or it places an initial pebble on the source. This can be done at any time. It has no predecessors and then might continue by placing another pebble. So now we have two pebbles on the graph. Then we can place one on three but remove one on one. We're gonna have two pebbles and so on. Now we have three pebbles. Now we have three pebbles. Now we only have two. And finally, we place a pebble on the sink. And if we now sum up these numbers, what we get is the cumulative pebbling complexity of this strategy. And now you can naturally have a quantity associated with a DAC, which will be 14 here. We can have a quantity which is the pebbling complexity of the graph which is just the pebbling complexity of the best strategy, the lowest one. And we know by prior works that we can, for example, give graphs or family of graphs with constant degree or even degree two which have optimal CPC, cumulative pebbling complexity of n square over log n. So now intuitively, if you look at the case where the labeling function is a random oracle, the pebbling complexity gives you already measure is correlated directly with the cumulative memory complexity for those strategies that only store exactly labels in memory. However, a general strategy might try to do something clever and compress information on the way stores exers of labels or whatnot. But a result by Alvin and Serbinenko shows that essentially that's the best that it can be done, up to some term that we're actually hiding here for simplicity. Let me, with high probability over the choice of a random oracle, the cumulative memory complexity of an adversary is lower bounded by the pebbling complexity of the graph times the length of the labels which here is the random oracle output length. And so our first result for the small block case will show something analogous for the case of random permutation where we instantiate the small labeling function with a function that simply takes the XOR of two labels. So this is specific for the case of in degree two. And then applies permutation which is invertible. And so to eliminate this invertibility with an XOR, the XOR of the labels to the output again. And the proof of this result follows a similar blueprint as the prior proofs in this domain using something called an expo spark to pebbling argument. But the real challenge which I'm not going to go into due to time is actually to deal with inversion queries in the proof. So the adversary can query the permutation both forward and backward. And this is what makes the proof much harder. Now, but let me go back for the second part of the talk to the white block case. So remember now, our labels are gonna have size K times L where L is the input output length of the permutation. And we want to build a more complex labeling function out of the permutation. And the first question you should actually ask is why should we actually even care? So actually one answer is that this is done in practice but now we actually have a result that shows us a lower bound on the CMC based on the pebbling complexity. So if you want to force a certain lower bound here just choose a sufficiently good graph and large enough to have large pebbling complexity until you meet what you want. But the key point here on one key point that I think also motivated practitioners but I'm not entirely sure is that if we use a permutation our length L the input output length of the permutation might actually be small. So say up to down to 128 bits for AES. And so if we want to achieve a certain large CMC then we need a large graph. And in many cases this also implies a large description of this graph. Some of these graphs are picked by choosing random edges so that will take space. So if we instead we can prove a lower bound that additionally depends on K and in fact we can hope to even have something super linear in K then we might be able to achieve the same lower bound but with a smaller graph description. So it's really about minimizing the description here. Okay, so what we're gonna do here is we're gonna look at wide block labeling functions that are also built out of DAGs. So in particular they say that the label size is K times L and we look at graphs with some in-degree delta. And now we are gonna build our labeling function from a gadget DAG H which is going to have K times delta sources and K designated nodes that are XC nodes and will correspond to the outputs and then we'll actually have constant in-degree two. And then we will compile this into an actual labeling function by using the small block labeling function we defined before. And the advantage of doing this is if now we look at the memory hard function defined by a base graph G with this wide block labeling function this is equivalent to a function defined by a composed graph with the basic graph and the gadget graph for the small block labeling function which we can study with the theorem we had before. And then the goal of course is to find such a gadget graph that will maximize the pebbling complexity. And what is composition here? It's quite natural but just to be precise. So we say we look at our base graph and it has some in-degree say here three and what we do is that first we blow up every vertex by K. So every vertex is mapped to K vertices, so here three. And then for every subgraph which is made by an inner vertex and its predecessors we are going to map it to an instance of the gadget graph in the composed graph. And then we do this of course all over the graph and now we get a new graph which is the composed graph which now has actually also a constant in-degree two. And now we would like to prove something about it and give a concrete instantiation of the gadget graph. So in the paper we give a family of instantiations for gadget graph that we initiate this study and this is an example of such a family. So it has delta times K sources at the bottom, K exit knots at the right hand and the number of vertices here is quadratic in K. So we will expect now to prove something of this form where we'll overbound the public complexity of the composed graph as by the public complexity of the base graph times something which depends on K and delta and ideally should be as large as possible like quadratic in the size of the graph. So unfortunately we don't quite know how to do it. What we do is we do the second best thing we can do and we observe that in almost all cases lower bounds on the public complexity for good graphs are proved via the notion of that robustness. And in particular we say that a graph is D E W robust. If whenever you remove up to E vertices from this deck the graph still has a long path of length at least D in the rest of the graph. And D E W robustness implies in particular that the graph has pebbling complexity at least D times E. And so what we show is that our composed graph as the property that if the base graph is D E W robust then the composed graph has also some good that robustness which is gonna give us a lower bound than from the cumulative pebbling complexity. And the idea of the proof here, I mean I won't read all through all of this but essentially what we wanna do is we wanna map a set of vertices in the composed graph back to a set of vertices in the base graph and use which is not larger than E and then use the existence of a long path in the rest to build a longer path back in the composed graph. And to do this what we need to crucially use as the following property of our gadget graph which is that whenever you now remove from this graph a subset of its vertices which is not too large say at most K over four. This is way larger than K over four but I just did it for dramatization purposes here. Then what we have is that for every possible source of the graph there is always going to be an exit node on the right hand side such that there exists a long path of length omega of delta times K square between the source and the exit nodes or something like this which I have highlighted here. So now what do we get out of this construction? So it's important now to go slowly through the end result. So what we can hope to get here if we get a graph with optimal pebbling complexity say n square over log n and say constant in degree because our final graph we have we'll have roughly n times K square vertices so what we can hope to have is something of the type a CMC which is at least n square times K to the fourth over log n times L. What we get here is something slightly worse namely we get n square times K to the third over log n. Now a question we might ask is this any good? Right, it's not clear what it means here to be good. So this is really a question we haven't asked before. We were just assuming that these random articles were costing you one to call them. No extra memory, nothing. Suddenly we look into it and it's really not clear what we want, okay? So a first thing we might want to do which has been done in several prior works is just to consider the ratio between the efficiency of the sequential strategy that honest user might use to evaluate the efficiency of the sequential strategy that honest users might use to evaluate the function and the CMC lower bound. And if we do that and we look what is the best existing strategy that you will actually implement you get a ratio which is generically log n and for some graphs can even be made constant and this is analog to the best result we had for monolithic random molecules. That's already a good baseline to satisfy but actually this is not really a hard to meet goal you could do it with much simpler constructions. So a better thing we might want to look at is how high the CMC is as a function of the running time of the sequential strategy. So you're given a certain budget of time to hash passwords and you want to get CMC which is as high as possible. And here what we see is that if we've right now the running time is n the number of vertices times the time to evaluate the labeling function we just built which is roughly k square. And then we compare it with our CMC lower bound then the ratio is roughly sort of the order n times square root of t lambda times l. And again ideally we will hope to achieve n times t lambda times l but I'm really not sure whether this is feasible with a simple construction. So it's a great open question but it seems it's at least as hard as again looking inside your labeling function and making it again a memory hard function plus more. So this might not be exactly what you're looking for. And another interesting question here is that we had this quadratic blow up from k to k square complexity. Maybe we can build something which is linear although the running times and what does it even mean? Okay but it's important here that we are doing something non-trivial. If for example you use something like based on Merkel-Darmgart to instantiate your labeling function and then you try to prove something about it but you will have gotten there was a ratio of n times l that will not depend on the actual time to evaluate your Merkel-Darmgart. So we are achieving something far from three by using this extra term in the ratio so the ratio goes up. Okay so as you see I think in this work we open more question that we actually solved. So this is really mostly the goal was to prove some basic theorems and to attract the attention to the problem and start giving you some theoretical designs. But I think it's a very important question and something that has been overlooked just because it's not easy. In prior works on memory hard functions but there are a lot of problems. I mean one open problem. So one of them is of course that I really consider only CMC. There is a lot of work on considering other metric and other aspect like bandwidth harness, like space sustained space complexity and much more. So we would like to extend it to that. Also it would be like one would of course like to look at practical design and prove something about them whether they're secure or not and we actually don't really have a good sense. Many of them do not fit in the framework that I used there in a graph theoretic framework. Also exactly for that reason we would like to have some more generic high level properties of these labeling functions that are sufficient. And also at the end we would really want to understand all of these parameter trade-offs and what they really mean. So if I make this labeling function even slower and so on what do I really want and how easy it is to represent these graphs and much more. All right so thank you. So this ends my talk. So we are kind of working on an extended full version of the paper that hopefully is going to appear soon where we want to highlight a bit better these open questions and parameter issues and so on. So I'm happy to answer any questions. Thank you Stefano. If anyone has a question please come to the microphones at the front. Long walk. Long path. Let's have a quick easy question. So I'm just curious why the cumulative memory complexity is the right measure rather than the maximum for example? Oh I see so yeah so the point is that you want to differentiate between strategies that for example require a lot of memory just because there is a peak where you're using memory just at one point and then you don't need it. So what it becomes important is for example when you do mass evaluation and you want to evaluate multiple instances then you could use that free memory for. Let's thank Stefano again.