Skip to content

Commit c2746c5

Browse files
committed
m
1 parent da790a0 commit c2746c5

17 files changed

+375
-335
lines changed

DynamoDbEncryption/dafny/DynamoDbEncryption/src/Beacon.dfy

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@ module BaseBeacon {
4242
//= specification/searchable-encryption/beacons.md#basichash
4343
//= type=implication
4444
//# * basicHash MUST take an [hmac key](./search-config.md#hmac-key-generation), a [beacon length](#beacon-length) and a sequence of bytes as input.
45-
function method {:opaque} hash(val : Bytes, key : Bytes, length : BeaconLength)
45+
function method {:opaque} hash(val : Bytes, key : Bytes, length : BeaconLength, bucket : Bytes)
4646
: (ret : Result<string, Error>)
4747
ensures ret.Success? ==>
4848
//= specification/searchable-encryption/beacons.md#basichash
4949
//= type=implication
5050
//# * basicHash MUST produce a non-empty string as output.
5151
&& |ret.value| > 0
5252

53-
&& getHmac(val, key).Success?
54-
&& var hash := getHmac(val, key).value;
53+
&& getHmac(val+bucket, key).Success?
54+
&& var hash := getHmac(val+bucket, key).value;
5555

5656
//= specification/searchable-encryption/beacons.md#basichash
5757
//= type=implication
@@ -64,19 +64,19 @@ module BaseBeacon {
6464
&& |ret.value| == (((length as uint8) + 3) / 4) as nat
6565

6666
{
67-
var hash :- getHmac(val, key);
67+
var hash :- getHmac(val + bucket, key);
6868
Success(BytesToHex(hash, length))
6969
}
7070

7171
// Get the standard hash for the UTF8 encoded representation of this string.
72-
function method {:opaque} hashStr(val : string, key : Bytes, length : BeaconLength) : (res : Result<string, Error>)
72+
function method {:opaque} hashStr(val : string, key : Bytes, length : BeaconLength, bucket : Bytes) : (res : Result<string, Error>)
7373
ensures res.Success? ==> |res.value| > 0
7474
{
7575
var str := UTF8.Encode(val);
7676
if str.Failure? then
7777
Failure(E(str.error))
7878
else
79-
hash(str.value, key, length)
79+
hash(str.value, key, length, bucket)
8080
}
8181

8282
// calculate the HMAC for some bytes
@@ -142,16 +142,16 @@ module BaseBeacon {
142142
asSet : bool,
143143
share : Option<string>
144144
) {
145-
function method {:opaque} hash(val : Bytes, key : Bytes)
145+
function method {:opaque} hash(val : Bytes, key : Bytes, bucket : Bytes)
146146
: (ret : Result<string, Error>)
147147
ensures ret.Success? ==>
148148
&& |ret.value| > 0
149-
&& base.hash(val, key, length).Success?
150-
&& ret.value == base.hash(val, key, length).value
149+
&& base.hash(val, key, length, bucket).Success?
150+
&& ret.value == base.hash(val, key, length, bucket).value
151151

152152
&& |ret.value| == (((length as uint8) + 3) / 4) as nat
153153
{
154-
base.hash(val, key, length)
154+
base.hash(val, key, length, bucket)
155155
}
156156

157157
// return the name of the hmac key to use
@@ -170,7 +170,7 @@ module BaseBeacon {
170170
//= type=implication
171171
//# * string hash MUST take a string and some [key materials](./search-config.md#get-beacon-key-materials)
172172
//# as input, and produce a string as output.
173-
function method {:opaque} hashStr(val : string, keys : HmacKeyMap) : (res : Result<string, Error>)
173+
function method {:opaque} hashStr(val : string, keys : HmacKeyMap, bucket : Bytes) : (res : Result<string, Error>)
174174
ensures res.Success? ==> |res.value| > 0
175175

176176
//= specification/searchable-encryption/beacons.md#string-hash
@@ -182,28 +182,28 @@ module BaseBeacon {
182182
&& keyName() in keys
183183
&& UTF8.Encode(val).Success?
184184
&& var str := UTF8.Encode(val).value;
185-
&& hash(str, keys[keyName()]).Success?
186-
&& res.value == hash(str, keys[keyName()]).value
185+
&& hash(str, keys[keyName()], bucket).Success?
186+
&& res.value == hash(str, keys[keyName()], bucket).value
187187
{
188188
:- Need(keyName() in keys, E("Internal Error, no key for " + keyName()));
189189
var str := UTF8.Encode(val);
190190
if str.Failure? then
191191
Failure(E(str.error))
192192
else
193-
hash(str.value, keys[keyName()])
193+
hash(str.value, keys[keyName()], bucket)
194194
}
195195

196-
function method {:opaque} ValueToSet(value : DDB.AttributeValue, key : Bytes) : (ret : Result<DDB.AttributeValue, Error>)
196+
function method {:opaque} ValueToSet(value : DDB.AttributeValue, key : Bytes, bucket : Bytes) : (ret : Result<DDB.AttributeValue, Error>)
197197
ensures ret.Success? ==> ret.value.SS?
198198
ensures !value.SS? && !value.NS? && !value.BS? ==> ret.Failure?
199199
ensures ret.Success? ==> HasNoDuplicates(ret.value.SS)
200200
{
201201
reveal HasNoDuplicates();
202202
assert HasNoDuplicates<string>([]);
203203
var beaconSeq :- match value {
204-
case SS(n) => BeaconizeStringSet(n, key)
205-
case NS(n) => BeaconizeNumberSet(n, key)
206-
case BS(n) => BeaconizeBinarySet(n, key)
204+
case SS(n) => BeaconizeStringSet(n, key, bucket)
205+
case NS(n) => BeaconizeNumberSet(n, key, bucket)
206+
case BS(n) => BeaconizeBinarySet(n, key, bucket)
207207
case _ => Failure(E("Beacon " + base.name + " has style AsSet, but attribute has type " + AttrTypeToStr(value) + "."))
208208
};
209209
Success(DDB.AttributeValue.SS(beaconSeq))
@@ -212,22 +212,22 @@ module BaseBeacon {
212212
//= specification/searchable-encryption/beacons.md#value-for-a-standard-beacon
213213
//= type=implication
214214
//# * This operation MUST take an [hmac key](./search-config.md#hmac-key-generation), a record as input, and produce an optional [AttributeValue](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_AttributeValue.html).
215-
function method {:opaque} getHash(item : DDB.AttributeMap, vf : VirtualFieldMap, key : Bytes) : (ret : Result<Option<DDB.AttributeValue>, Error>)
215+
function method {:opaque} getHash(item : DDB.AttributeMap, vf : VirtualFieldMap, key : Bytes, bucket : Bytes) : (ret : Result<Option<DDB.AttributeValue>, Error>)
216216
//= specification/searchable-encryption/beacons.md#value-for-a-standard-beacon
217217
//= type=implication
218218
//# * If this beacon is marked AsSet then this operation MUST return the
219219
//# [set value](#value-for-a-set-standard-beacon),
220220
//# otherwise it MUST return the [non-set value](#value-for-a-non-set-standard-beacon)
221-
ensures asSet ==> ret == getHashSet(item, key)
222-
ensures !asSet ==> ret == getHashNonSet(item, vf, key)
221+
ensures asSet ==> ret == getHashSet(item, key, bucket)
222+
ensures !asSet ==> ret == getHashNonSet(item, vf, key, bucket)
223223
{
224224
if asSet then
225-
getHashSet(item, key)
225+
getHashSet(item, key, bucket)
226226
else
227-
getHashNonSet(item, vf, key)
227+
getHashNonSet(item, vf, key, bucket)
228228
}
229229

230-
function method {:opaque} getHashSet(item : DDB.AttributeMap, key : Bytes) : (ret : Result<Option<DDB.AttributeValue>, Error>)
230+
function method {:opaque} getHashSet(item : DDB.AttributeMap, key : Bytes, bucket : Bytes) : (ret : Result<Option<DDB.AttributeValue>, Error>)
231231
requires asSet
232232
ensures ret.Success? ==>
233233
//= specification/searchable-encryption/beacons.md#value-for-a-set-standard-beacon
@@ -254,10 +254,10 @@ module BaseBeacon {
254254
//= specification/searchable-encryption/beacons.md#asset-initialization
255255
//# * The Standard Beacon MUST be stored in the item as a Set,
256256
//# comprised of the [beacon values](#beacon-value) of all the elements in the original Set.
257-
var setValue :- ValueToSet(value.value, key);
257+
var setValue :- ValueToSet(value.value, key, bucket);
258258
Success(Some(setValue))
259259
}
260-
function method {:opaque} getHashNonSet(item : DDB.AttributeMap, vf : VirtualFieldMap, key : Bytes) : (ret : Result<Option<DDB.AttributeValue>, Error>)
260+
function method {:opaque} getHashNonSet(item : DDB.AttributeMap, vf : VirtualFieldMap, key : Bytes, bucket : Bytes) : (ret : Result<Option<DDB.AttributeValue>, Error>)
261261
requires !asSet
262262
ensures ret.Success? ==>
263263
//= specification/searchable-encryption/beacons.md#value-for-a-non-set-standard-beacon
@@ -276,17 +276,17 @@ module BaseBeacon {
276276
//= type=implication
277277
//# * This operation MUST convert the attribute value of the associated field to
278278
//# a sequence of bytes, as per [attribute serialization](../dynamodb-encryption-client/ddb-attribute-serialization.md).
279-
&& (bytes.Some? ==> ret.value.Some? && hash(bytes.value, key).Success? && ret.value.value == DDB.AttributeValue.S(hash(bytes.value, key).value))
279+
&& (bytes.Some? ==> ret.value.Some? && hash(bytes.value, key, bucket).Success? && ret.value.value == DDB.AttributeValue.S(hash(bytes.value, key, bucket).value))
280280
//= specification/searchable-encryption/beacons.md#value-for-a-non-set-standard-beacon
281281
//= type=implication
282282
//# * This operation MUST return the [basicHash](#basichash) of the resulting bytes and the configured [beacon length](#beacon-length).
283-
&& (bytes.Some? ==> ret.value.Some? && base.hash(bytes.value, key, length).Success? && ret.value.value == DDB.AttributeValue.S(base.hash(bytes.value, key, length).value))
283+
&& (bytes.Some? ==> ret.value.Some? && base.hash(bytes.value, key, length, bucket).Success? && ret.value.value == DDB.AttributeValue.S(base.hash(bytes.value, key, length, bucket).value))
284284
{
285285
var bytes :- VirtToBytes(loc, item, vf);
286286
if bytes.None? then
287287
Success(None)
288288
else
289-
var res :- hash(bytes.value, key);
289+
var res :- hash(bytes.value, key, bucket);
290290
Success(Some(DDB.AttributeValue.S(res)))
291291
}
292292

@@ -303,7 +303,7 @@ module BaseBeacon {
303303
[loc[0].key]
304304
}
305305

306-
function method {:tailrecursion} BeaconizeStringSet(value : DDB.StringSetAttributeValue, key : Bytes, converted : seq<string> := [])
306+
function method {:tailrecursion} BeaconizeStringSet(value : DDB.StringSetAttributeValue, key : Bytes, bucket : Bytes, converted : seq<string> := [])
307307
: (ret : Result<seq<string>, Error>)
308308
requires HasNoDuplicates(converted)
309309
ensures ret.Success? ==> HasNoDuplicates(ret.value)
@@ -312,15 +312,15 @@ module BaseBeacon {
312312
Success(converted)
313313
else
314314
var bytes :- DynamoToStruct.TopLevelAttributeToBytes(DDB.AttributeValue.S(value[0])).MapFailure(e => E(e));
315-
var h :- hash(bytes, key);
315+
var h :- hash(bytes, key, bucket);
316316
if h in converted then
317-
BeaconizeStringSet(value[1..], key, converted)
317+
BeaconizeStringSet(value[1..], key, bucket, converted)
318318
else
319319
reveal HasNoDuplicates();
320-
BeaconizeStringSet(value[1..], key, converted + [h])
320+
BeaconizeStringSet(value[1..], key, bucket, converted + [h])
321321
}
322322

323-
function method {:tailrecursion} BeaconizeNumberSet(value : DDB.NumberSetAttributeValue, key : Bytes, converted : seq<string> := [])
323+
function method {:tailrecursion} BeaconizeNumberSet(value : DDB.NumberSetAttributeValue, key : Bytes, bucket : Bytes, converted : seq<string> := [])
324324
: (ret : Result<seq<string>, Error>)
325325
requires HasNoDuplicates(converted)
326326
ensures ret.Success? ==> HasNoDuplicates(ret.value)
@@ -329,15 +329,15 @@ module BaseBeacon {
329329
Success(converted)
330330
else
331331
var bytes :- DynamoToStruct.TopLevelAttributeToBytes(DDB.AttributeValue.N(value[0])).MapFailure(e => E(e));
332-
var h :- hash(bytes, key);
332+
var h :- hash(bytes, key, bucket);
333333
if h in converted then
334-
BeaconizeNumberSet(value[1..], key, converted)
334+
BeaconizeNumberSet(value[1..], key, bucket, converted)
335335
else
336336
reveal HasNoDuplicates();
337-
BeaconizeNumberSet(value[1..], key, converted + [h])
337+
BeaconizeNumberSet(value[1..], key, bucket, converted + [h])
338338
}
339339

340-
function method {:tailrecursion} BeaconizeBinarySet(value : DDB.BinarySetAttributeValue, key : Bytes, converted : seq<string> := [])
340+
function method {:tailrecursion} BeaconizeBinarySet(value : DDB.BinarySetAttributeValue, key : Bytes, bucket : Bytes, converted : seq<string> := [])
341341
: (ret : Result<seq<string>, Error>)
342342
requires HasNoDuplicates(converted)
343343
ensures ret.Success? ==> HasNoDuplicates(ret.value)
@@ -346,32 +346,32 @@ module BaseBeacon {
346346
Success(converted)
347347
else
348348
var bytes :- DynamoToStruct.TopLevelAttributeToBytes(DDB.AttributeValue.B(value[0])).MapFailure(e => E(e));
349-
var h :- hash(bytes, key);
349+
var h :- hash(bytes, key, bucket);
350350
if h in converted then
351-
BeaconizeBinarySet(value[1..], key, converted)
351+
BeaconizeBinarySet(value[1..], key, bucket, converted)
352352
else
353353
reveal HasNoDuplicates();
354-
BeaconizeBinarySet(value[1..], key, converted + [h])
354+
BeaconizeBinarySet(value[1..], key, bucket, converted + [h])
355355
}
356356

357-
function method GetBeaconValue(value : DDB.AttributeValue, key : Bytes, forContains : bool)
357+
function method GetBeaconValue(value : DDB.AttributeValue, key : Bytes, forContains : bool, bucket : Bytes)
358358
: (ret : Result<DDB.AttributeValue, Error>)
359359
{
360360
// in query, allow beaconization of terminals
361361
if asSet && !value.S? && !value.N? && !value.B? then
362-
ValueToSet(value, key)
362+
ValueToSet(value, key, bucket)
363363
else if forContains && (value.SS? || value.NS? || value.BS?) then
364-
ValueToSet(value, key)
364+
ValueToSet(value, key, bucket)
365365
else
366366
var bytes :- DynamoToStruct.TopLevelAttributeToBytes(value).MapFailure(e => E(e));
367-
var h :- hash(bytes, key);
367+
var h :- hash(bytes, key, bucket);
368368
Success(DDB.AttributeValue.S(h))
369369
}
370370

371371
//= specification/searchable-encryption/beacons.md#getpart-for-a-standard-beacon
372372
//= type=implication
373373
//# * getPart MUST take an [hmac key](./search-config.md#hmac-key-generation), a sequence of bytes as input, and produce a string.
374-
function method {:opaque} getPart(val : Bytes, key : Bytes)
374+
function method {:opaque} getPart(val : Bytes, key : Bytes, bucket : Bytes)
375375
: (ret : Result<string, Error>)
376376
requires 0 < |val|
377377

@@ -382,10 +382,10 @@ module BaseBeacon {
382382
//= specification/searchable-encryption/beacons.md#getpart-for-a-standard-beacon
383383
//= type=implication
384384
//# * getPart MUST return the [basicHash](#basichash) of the input and the configured [beacon length](#beacon-length).
385-
&& base.hash(val, key, length).Success?
386-
&& ret.value == base.hash(val, key, length).value
385+
&& base.hash(val, key, length, bucket).Success?
386+
&& ret.value == base.hash(val, key, length, bucket).value
387387
{
388-
base.hash(val, key, length)
388+
base.hash(val, key, length, bucket)
389389
}
390390
predicate ValidState() {true}
391391
}

0 commit comments

Comments
 (0)