In the absolute worst case, we could give up on encapsulation of fields. I wouldn’t want to do that, but right now, I’d rather do that than accept a non-reflexive ==. But I’m sure there’s a better alternative — let’s find it.
> On Feb 25, 2019, at 4:23 PM, fo...@univ-mlv.fr wrote: > > What i'm saying is that using a component wise test as == as a security > implication, something i was not aware before thinking about it, > and something i'm sure our users don't want to be aware of. > > Having two different meanings for "encapsulation", one for references and one > for values is possible a solution, but it's moving the problem to the users, > by saying, you will have to be careful enough to know that class > encapsulation and value class encapsulation works differently. > The first part of the moto is "code like a class" and not "code like a class > but beware because the encapsulation model is different". > > It also makes the implementation of an interface by to a value class more > hazardous, by example, can a panama Address can be implemented by a value > class ? The answer is not easy because the encapsulation model is leaky. > >> if the constructor is not accessible to the attacker > so a serializable value class is a security liability ? > > And a component wise test is also prone to timing attacks, you can guess the > value of the fields far faster than checking all combinations. > > Rémi > > ----- Mail original ----- >> De: "Brian Goetz" <brian.go...@oracle.com> >> À: "Remi Forax" <fo...@univ-mlv.fr> >> Cc: "valhalla-spec-experts" <valhalla-spec-experts@openjdk.java.net> >> Envoyé: Lundi 25 Février 2019 15:32:18 >> Objet: Re: The substituability test is breaking the encapsulation > >> Good — let’s drill into this. >> >> At a high level, you’re saying there’s a tension between encapsulation and a >> state-based comparison primitive; that the state-based comparison is a side >> channel through which encapsulated state may be leaked. That’s true. (Just >> as >> there is a tension between “values are objects” and “objects have identity”.) >> >> To pick up on John’s note from v-dev over the weekend, value-objects are more >> easily _forgeable_ than identity-objects. There are infinitely many possible >> java.lang.Integers, because of the unique-per-instance identity; there are >> only >> finitely many instances of >> >> value class IntWrapper { public int i; } >> >> and, given access to the constructor, you can construct them all, and readily >> stamp out whatever instance you like, and it is just as good as all other >> instances with that state. >> >> We want value to have as many of the things that classes have, within the >> constraints that values eschew identity. So they can’t have mutability or >> layout polymorphism. But they can have methods, fields, constructors, type >> variables, etc. And we’d like for “encapsulation” to be in this set. >> >> As a trivial observation, the concern you raise here goes away if the >> constructor is not accessible to the attacker. That suggests there are at >> least two paths to plugging this leak; tighten state-based comparison, or >> require classes that want to encapsulate their state to also encapsulate the >> constructors that can produce arbitrary state. >> >> So, rather than blaming ==, or blaming encapsulation, let’s set out some >> expectations for how we want to use encapsulation in values. >> >> (I think this problem may be related to another problem — that of when a >> client >> should be allowed to use `withfield`. For an unencapsulated class like >> Point, >> where the ctor expresses no constraints, it seems desirable to let clients >> say >> “p __with x = 2” (with whatever syntax), without making the author expose yet >> more accessor methods, but clearly for encapsulated values, that’s not OK.) >> >>> On Feb 25, 2019, at 5:11 AM, Remi Forax <fo...@univ-mlv.fr> wrote: >>> >>> Hi all, >>> there is another issue with making the component wide test available for any >>> value types, it's leaking the implementation. >>> >>> Let say we have this class: >>> >>> public value class GuessANumber { >>> private final int value; >>> >>> public GuessANumber(int value) { >>> this.value = value; >>> } >>> >>> public enum Response { LOWER, GREATER, FOUND }; >>> >>> public Response guess(int guess) { >>> if (value < guess) { >>> return Response.LOWER; >>> } >>> if (value > guess) { >>> return Response.GREATER; >>> } >>> return Response.FOUND; >>> } >>> >>> public static GuessANumber random(int seed) { >>> return new GuessANumber(new Random(seed).nextInt(1024)); >>> } >>> } >>> >>> you can naively think that if we have an an instance of GuessANumber >>> var number = GuessANumber.random(0); >>> you have can not get the value of the private field of that instance, >>> but using == you can find it because you can use == to test if number is >>> substituable to a user created GuessANumber. >>> >>> here is how to find the value without using the method guess() >>> System.out.println(IntStream.range(0, 1024).filter(n -> new GuessANumber(n) >>> == >>> number).findFirst()); >>> >>> Rémi