The substituability test is breaking the encapsulation
Brian Goetz
brian.goetz at oracle.com
Mon Feb 25 21:38:58 UTC 2019
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, forax at 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.goetz at oracle.com>
>> À: "Remi Forax" <forax at univ-mlv.fr>
>> Cc: "valhalla-spec-experts" <valhalla-spec-experts at 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 <forax at 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
More information about the valhalla-spec-observers
mailing list