Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: simplify structured encryption #866

Merged
merged 46 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
4255ee1
feat: simplify structured encryption
ajewellamz Mar 27, 2024
7cc2b24
AuthenticateAction
ajewellamz Mar 28, 2024
563bf22
StructuredData
ajewellamz Mar 28, 2024
8375a60
verification time
ajewellamz Mar 28, 2024
fd9992b
verification time
ajewellamz Mar 28, 2024
0140e8c
verification speed
ajewellamz Mar 28, 2024
90acfc4
specs
ajewellamz Mar 29, 2024
e904b71
revert Paths.dfy
ajewellamz Mar 29, 2024
4b31c89
move to sequence of Path
ajewellamz Apr 11, 2024
e5bc34b
cleanup
ajewellamz Apr 11, 2024
5ff1c22
verification
ajewellamz Apr 11, 2024
ee7c679
format
ajewellamz Apr 11, 2024
0a81f47
verification
ajewellamz Apr 11, 2024
917c6d4
verification
ajewellamz Apr 11, 2024
8ab7586
m
ajewellamz Apr 12, 2024
c1c6d5b
fix
ajewellamz Apr 12, 2024
4ee5581
m
ajewellamz Apr 14, 2024
44dbc81
verification
ajewellamz Apr 21, 2024
ca9c757
merge from main
ajewellamz Apr 21, 2024
6f3b8a8
merge from main
ajewellamz Apr 21, 2024
cc942d0
m
ajewellamz Apr 21, 2024
5be8142
m
ajewellamz Apr 21, 2024
f3a7973
verify
ajewellamz Apr 21, 2024
f48dc0a
format
ajewellamz Apr 21, 2024
535a3bf
duvet and specs
ajewellamz Apr 23, 2024
59f7001
format
ajewellamz Apr 23, 2024
313555c
repolymorph
ajewellamz Apr 23, 2024
f6d6e37
verify
ajewellamz Apr 23, 2024
d042829
m
ajewellamz Apr 24, 2024
2223ee2
Merge branch 'main' into ajewell/simplify
ajewellamz Apr 24, 2024
5e8c2d5
m
ajewellamz Apr 24, 2024
4fb4544
m
ajewellamz Apr 24, 2024
920fa16
Merge branch 'main' into ajewell/simplify
ajewellamz Apr 25, 2024
b69f2f5
Merge branch 'main' into ajewell/simplify
ajewellamz Apr 30, 2024
f94a464
clean up spec
ajewellamz Apr 30, 2024
77242bc
m
ajewellamz Apr 30, 2024
782d91f
changes documents
ajewellamz Apr 30, 2024
e54400c
ResolveAuthActions
ajewellamz May 6, 2024
e8c98bb
m
ajewellamz May 6, 2024
52a2183
Merge branch 'main' into ajewell/simplify
ajewellamz May 6, 2024
ebd4c14
duvet
ajewellamz May 7, 2024
e5f998e
cleanup
ajewellamz May 7, 2024
f8e9f27
m
ajewellamz May 7, 2024
ae87387
PR feedback
ajewellamz May 8, 2024
8eb5745
m
ajewellamz May 8, 2024
b597e30
Merge branch 'main' into ajewell/simplify
ajewellamz May 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DynamoDbEncryption/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ ImplementationFromDafny.cs
TestsFromDafny.cs
**/bin
**/obj
node_modules
project.properties
5 changes: 5 additions & 0 deletions DynamoDbEncryption/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,8 @@ SERVICE_DEPS_DynamoDbEncryptionTransforms := \

format_net:
pushd runtimes/net && dotnet format DynamoDbEncryption.csproj && popd

polymorph:
export DAFNY_VERSION=4.2
npm i --no-save prettier@3 [email protected]
make polymorph_code_gen PROJECT_DEPENDENCIES=
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ list ConstructorPartList {
//= specification/searchable-encryption/virtual.md#virtual-field-initialization
//= type=implication
//# On initialization of a Virtual Field, the caller MUST provide:
//# * A name -- a string
//# * A list of [Virtual Parts](#virtual-part-initialization)
//# - A name -- a string
//# - A list of [Virtual Parts](#virtual-part-initialization)

@javadoc("The configuration for a Virtual Field. A Virtual Field is a field constructed from parts of other fields for use with beacons, but never itself stored on items.")
structure VirtualField {
Expand Down Expand Up @@ -383,8 +383,8 @@ structure GetSuffix {
//= specification/searchable-encryption/virtual.md#getsubstring-transform-initialization
//= type=implication
//# On initialization of a GetSubstring Transform, the caller MUST provide:
//# * low : an integer [position](#position-definition)
//# * high : an integer [position](#position-definition)
//# - low : an integer [position](#position-definition)
//# - high : an integer [position](#position-definition)

// return range of characters, 0-based counting
// low is inclusive, high is exclusive
Expand All @@ -405,8 +405,8 @@ structure GetSubstring {
//= specification/searchable-encryption/virtual.md#getsegment-transform-initialization
//= type=implication
//# On initialization of a GetSegment Transform, the caller MUST provide:
//# * split : an character
//# * index : an integer [position](#position-definition)
//# - split : an character
//# - index : an integer [position](#position-definition)

// split string on character, then return one piece.
// 'index' has the same semantics as 'low' in GetSubstring
Expand All @@ -423,9 +423,9 @@ structure GetSegment {
//= specification/searchable-encryption/virtual.md#getsegments-transform-initialization
//= type=implication
//# On initialization of a GetSegments Transform, the caller MUST provide:
//# * split : an character
//# * low : an integer [position](#position-definition)
//# * high : an integer [position](#position-definition)
//# - split : an character
//# - low : an integer [position](#position-definition)
//# - high : an integer [position](#position-definition)

// split string on character, then return range of pieces.
// 'low' and 'high' have the same semantics as GetSubstring
Expand All @@ -445,14 +445,14 @@ structure GetSegments {
//= specification/searchable-encryption/virtual.md#virtual-transform-initialization
//= type=implication
//# On initialization of a Virtual Transform, the caller MUST provide exactly one of
//# * an [Upper](#upper-transform-initialization) transform
//# * a [Lower](#lower-transform-initialization) transform
//# * an [Insert](#insert-transform-initialization) transform
//# * a [GetPrefix](#getprefix-transform-initialization) transform
//# * a [GetSuffix](#getsuffix-transform-initialization) transform
//# * a [GetSubstring](#getsubstring-transform-initialization) transform
//# * a [GetSegment](#getsegment-transform-initialization) transform
//# * a [GetSegments](#getsegments-transform-initialization) transform
//# - an [Upper](#upper-transform-initialization) transform
//# - a [Lower](#lower-transform-initialization) transform
//# - an [Insert](#insert-transform-initialization) transform
//# - a [GetPrefix](#getprefix-transform-initialization) transform
//# - a [GetSuffix](#getsuffix-transform-initialization) transform
//# - a [GetSubstring](#getsubstring-transform-initialization) transform
//# - a [GetSegment](#getsegment-transform-initialization) transform
//# - a [GetSegments](#getsegments-transform-initialization) transform

union VirtualTransform {
upper: Upper,
Expand Down Expand Up @@ -507,10 +507,10 @@ structure SharedSet {
//= type=implication
//# On initialization of a Beacon Style, the caller MUST provide exactly one of
//#
//# * a [PartOnly](#partonly-initialization)
//# * a [Shared](#shared-initialization)
//# * an [AsSet](#asset-initialization)
//# * a [SharedSet](#sharedset-initialization)
//# - a [PartOnly](#partonly-initialization)
//# - a [Shared](#shared-initialization)
//# - an [AsSet](#asset-initialization)
//# - a [SharedSet](#sharedset-initialization)

union BeaconStyle {
partOnly: PartOnly,
Expand All @@ -522,8 +522,8 @@ union BeaconStyle {
//= specification/searchable-encryption/beacons.md#encrypted-part-initialization
//= type=implication
//# On initialization of a [encrypted part](#encrypted-part-initialization), the caller MUST provide:
//# * A name -- a string, the name of a standard beacon
//# * A prefix -- a string
//# - A name -- a string, the name of a standard beacon
//# - A prefix -- a string

@javadoc("A part of a Compound Beacon that contains a beacon over encrypted data.")
structure EncryptedPart {
Expand All @@ -538,8 +538,8 @@ structure EncryptedPart {
//= specification/searchable-encryption/beacons.md#signed-part-initialization
//= type=implication
//# On initialization of a [signed part](#signed-part-initialization), the caller MUST provide:
//# * A name -- a string
//# * A prefix -- a string
//# - A name -- a string
//# - A prefix -- a string

//= specification/searchable-encryption/beacons.md#signed-part-initialization
//= type=implication
Expand All @@ -561,7 +561,7 @@ structure SignedPart {
//= specification/searchable-encryption/beacons.md#constructor-initialization
//= type=implication
//# On initialization of a constructor, the caller MUST provide:
//# * A non-empty list of [Constructor parts](#constructor-part-initialization)
//#- A non-empty list of [Constructor parts](#constructor-part-initialization)
ajewellamz marked this conversation as resolved.
Show resolved Hide resolved

@javadoc("The configuration for a particular Compound Beacon construction.")
structure Constructor {
Expand All @@ -573,8 +573,8 @@ structure Constructor {
//= specification/searchable-encryption/beacons.md#constructor-part-initialization
//= type=implication
//# On initialization of a constructor part, the caller MUST provide:
//# * A name -- a string
//# * A required flag -- a boolean
//#- A name -- a string
//#- A required flag -- a boolean

@javadoc("A part of a Compound Becaon Construction.")
structure ConstructorPart {
Expand All @@ -589,13 +589,13 @@ structure ConstructorPart {
//= specification/searchable-encryption/beacons.md#standard-beacon-initialization
//= type=implication
//# On initialization of a Standard Beacon, the caller MUST provide:
//# * A name -- a string
//# * A `length` -- a [beacon length](#beacon-length)
//#- A name -- a string
//#- A `length` -- a [beacon length](#beacon-length)

//= specification/searchable-encryption/beacons.md#standard-beacon-initialization
//= type=implication
//# On initialization of a Standard Beacon, the caller MAY provide:
//# * a [terminal location](virtual.md#terminal-location) -- a string
//#- a [terminal location](virtual.md#terminal-location) -- a string

@javadoc("The configuration for a Standard Beacon.")
structure StandardBeacon {
Expand All @@ -614,15 +614,15 @@ structure StandardBeacon {
//= specification/searchable-encryption/beacons.md#compound-beacon-initialization
//= type=implication
//# On initialization of a Compound Beacon, the caller MUST provide:
//# * A name -- a string
//# * A split character -- a character
//#- A name -- a string
//#- A split character -- a character

//= specification/searchable-encryption/beacons.md#compound-beacon-initialization
//= type=implication
//# On initialization of a Compound Beacon, the caller MAY provide:
//# * A list of [encrypted parts](#encrypted-part-initialization)
//# * A list of [signed parts](#signed-part-initialization)
//# * A list of constructors
//#- A list of [encrypted parts](#encrypted-part-initialization)
//#- A list of [signed parts](#signed-part-initialization)
//#- A list of constructors

@javadoc("The configuration for a Compound Beacon.")
structure CompoundBeacon {
Expand Down Expand Up @@ -681,8 +681,8 @@ structure MultiKeyStore {
//= specification/searchable-encryption/search-config.md#beacon-key-source
//= type=implication
//# On initialization of a Beacon Key Source, the caller MUST provide exactly one of
//# * a [Single Key Store](#single-key-store-initialization)
//# * a [Multi Key Store](#multi-key-store-initialization)
//#- a [Single Key Store](#single-key-store-initialization)
//#- a [Multi Key Store](#multi-key-store-initialization)

union BeaconKeySource {
single : SingleKeyStore,
Expand Down Expand Up @@ -732,8 +732,8 @@ structure BeaconVersion {
//= specification/searchable-encryption/search-config.md#initialization
//= type=implication
//# On initialization of the Search Config, the caller MUST provide:
//# - A list of [beacon versions](#beacon-version-initialization)
//# - The [version number](#version-number) of the [beacon versions](#beacon-version) to be used for writing.
//#- A list of [beacon versions](#beacon-version-initialization)
//#- The [version number](#version-number) of the [beacon versions](#beacon-version-initialization) to be used for writing.

@javadoc("The configuration for searchable encryption.")
structure SearchConfig {
Expand Down Expand Up @@ -796,7 +796,7 @@ operation CreateDynamoDbEncryptionBranchKeyIdSupplier {

//= specification/dynamodb-encryption-client/ddb-encryption-branch-key-id-supplier.md#input
//= type=implication
//# This operation MUST take in a [DynamoDbKeyBranchKeyIdSupplier](#dynamodb-key-branch-key-id-supplier) as input.
//# This operation MUST take in a [DynamoDbKeyBranchKeyIdSupplier](#dynamodbkeybranchkeyidsupplier) as input.
@javadoc("Inputs for creating a Branch Key Supplier from a DynamoDB Key Branch Key Id Supplier")
structure CreateDynamoDbEncryptionBranchKeyIdSupplierInput {
@required
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ module SearchConfigToInfo {

//= specification/searchable-encryption/search-config.md#initialization
//= type=implication
//# Initialization MUST fail if the length of the list of [beacon versions](#beacon-version) is not 1.
//# Initialization MUST fail if the length of the list of [beacon versions](#beacon-version-initialization) is not 1.
ensures outer.search.Some? && |outer.search.value.versions| != 1 ==> output.Failure?
{
if outer.search.None? {
Expand Down Expand Up @@ -738,7 +738,7 @@ module SearchConfigToInfo {

//= specification/searchable-encryption/beacons.md#initialization-failure
//= type=implication
//# Initialization MUST fail if any [constructor](#constructor) is configured with a field name
//# Initialization MUST fail if any [constructor](#constructor-initialization) is configured with a field name
//# that is not a defined [part](#part).
ensures ret.Success? && 0 < |c| ==>
exists p : CB.BeaconPart | p in parts :: p.getName() == c[0].name
Expand Down Expand Up @@ -773,14 +773,14 @@ module SearchConfigToInfo {
ensures ret.Success? ==> |ret.value| == origSize
//= specification/searchable-encryption/beacons.md#initialization-failure
//= type=implication
//# Initialization MUST fail if any [constructor](#constructor) is configured without at least one
//# Initialization MUST fail if any [constructor](#constructor-initialization) is configured without at least one
//# required part.
ensures ret.Success? && 0 < |constructors| ==>
0 < SeqCount((p : ConstructorPart) => p.required, constructors[0].parts)

//= specification/searchable-encryption/beacons.md#initialization-failure
//= type=implication
//# Initialization MUST fail if two [constructors](#constructor) are configured
//# Initialization MUST fail if two [constructors](#constructor-initialization) are configured
//# with the same set of required parts.
ensures ret.Success? && 0 < |constructors| ==>
&& MakeConstructor(constructors[0], parts).Success?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,12 @@ module DynamoToStruct {

type Error = AwsCryptographyDbEncryptionSdkDynamoDbTypes.Error

type StructuredDataTerminalType = x : StructuredData | x.content.Terminal? witness *
type TerminalDataMap = map<AttributeName, StructuredDataTerminalType>
type TerminalDataMap = map<AttributeName, StructuredDataTerminal>

// This file exists for these two functions : ItemToStructured and StructuredToItem
// which provide conversion between an AttributeMap and a StructuredDataMap

// Convert AttributeMap to StructuredDataMap
//= specification/dynamodb-encryption-client/ddb-item-conversion.md#convert-ddb-item-to-structured-data
//= type=implication
//# - MUST be a [Structured Data Map](../structured-encryption/structures.md#structured-data-map).
function method {:opaque} ItemToStructured(item : AttributeMap) : (ret : Result<TerminalDataMap, Error>)

//= specification/dynamodb-encryption-client/ddb-item-conversion.md#convert-ddb-item-to-structured-data
Expand All @@ -39,30 +35,19 @@ module DynamoToStruct {
//# for each attribute on the DynamoDB Item, and no others.
ensures ret.Success? ==> ret.value.Keys == item.Keys

//= specification/dynamodb-encryption-client/ddb-item-conversion.md#convert-ddb-item-to-structured-data
//= type=implication
//# - MUST NOT have [Structured Data Attributes](../structured-encryption/structures.md#structured-data-attributes).
ensures ret.Success? ==> forall v <- ret.value.Values :: v.content.Terminal?

//= specification/dynamodb-encryption-client/ddb-item-conversion.md#convert-ddb-item-to-structured-data
//= type=implication
//# - The [Terminal Type ID](../structured-encryption/structures.md#terminal-type-id) for each attribute MUST
//# be the [Type ID](./ddb-attribute-serialization.md#type-id) of the [serialization](./ddb-attribute-serialization.md) of this Attribute Value.
ensures ret.Success? ==> forall kv <- ret.value.Items :: kv.1.content.Terminal.typeId == AttrToTypeId(item[kv.0])

//= specification/dynamodb-encryption-client/ddb-item-conversion.md#convert-ddb-item-to-structured-data
//= type=implication
//# - The Structured Data Terminal MUST be located at the top level of the Structured Data,
//# string indexed by the Attribute Name.
ensures ret.Success? ==> forall kv <- ret.value.Items :: kv.0 in ret.value.Keys && ret.value[kv.0].content.Terminal?
ensures ret.Success? ==> forall kv <- ret.value.Items :: kv.1.typeId == AttrToTypeId(item[kv.0])

//= specification/dynamodb-encryption-client/ddb-item-conversion.md#convert-ddb-item-to-structured-data
//= type=implication
//# - The [Terminal Value](../structured-encryption/structures.md#terminal-value) for each attribute MUST
//# be the [Value](./ddb-attribute-serialization.md#type-id) of the [serialization](./ddb-attribute-serialization.md) of this Attribute Value.
ensures ret.Success? ==> forall kv <- ret.value.Items ::
&& TopLevelAttributeToBytes(item[kv.0]).Success?
&& kv.1.content.Terminal.value == TopLevelAttributeToBytes(item[kv.0]).value
&& kv.1.value == TopLevelAttributeToBytes(item[kv.0]).value

{
var structuredMap := map k <- item :: k := AttrToStructured(item[k]);
Expand All @@ -71,10 +56,7 @@ module DynamoToStruct {
}

// Convert StructuredDataMap to AttributeMap
//= specification/dynamodb-encryption-client/ddb-item-conversion.md#convert-structured-data-to-ddb-item
//= type=implication
//# - MUST be a [Structured Data Map](../structured-encryption/structures.md#structured-data-map).
function method {:opaque} StructuredToItem(s : StructuredDataMap) : (ret : Result<AttributeMap, Error>)
function method {:opaque} StructuredToItem(s : TerminalDataMap) : (ret : Result<AttributeMap, Error>)
//= specification/dynamodb-encryption-client/ddb-item-conversion.md#convert-structured-data-to-ddb-item
//= type=implication
//# - MUST contain an Attribute for every [Structured Data Terminal](../structured-encryption/structures.md#structured-data-terminal)
Expand Down Expand Up @@ -125,12 +107,12 @@ module DynamoToStruct {
}

// Prove round trip. A work in progress
lemma RoundTripFromStructured(s : StructuredData)
ensures StructuredToAttr(s).Success? && s.content.Terminal.typeId == SE.BINARY ==>
lemma RoundTripFromStructured(s : StructuredDataTerminal)
ensures StructuredToAttr(s).Success? && s.typeId == SE.BINARY ==>
&& AttrToStructured(StructuredToAttr(s).value).Success?
ensures StructuredToAttr(s).Success? && s.content.Terminal.typeId == SE.BOOLEAN ==>
ensures StructuredToAttr(s).Success? && s.typeId == SE.BOOLEAN ==>
&& AttrToStructured(StructuredToAttr(s).value).Success?
ensures StructuredToAttr(s).Success? && s.content.Terminal.typeId == SE.NULL ==>
ensures StructuredToAttr(s).Success? && s.typeId == SE.NULL ==>
&& AttrToStructured(StructuredToAttr(s).value).Success?
{
reveal AttrToStructured();
Expand Down Expand Up @@ -161,34 +143,18 @@ module DynamoToStruct {
AttrToBytes(a, false)
}

function method {:opaque} AttrToStructured(item : AttributeValue) : (ret : Result<StructuredData, string>)
ensures ret.Success? ==> ret.value.content.Terminal?
ensures ret.Success? ==> ret.value.content.Terminal.typeId == AttrToTypeId(item)
function method {:opaque} AttrToStructured(item : AttributeValue) : (ret : Result<StructuredDataTerminal, string>)
ensures ret.Success? ==> ret.value.typeId == AttrToTypeId(item)
ensures ret.Success? ==>
&& TopLevelAttributeToBytes(item).Success?
&& ret.value.content.Terminal.value == TopLevelAttributeToBytes(item).value
&& ret.value.value == TopLevelAttributeToBytes(item).value
{
var body :- TopLevelAttributeToBytes(item);
Success(StructuredData(content := Terminal(StructuredDataTerminal(value := body, typeId := AttrToTypeId(item))), attributes := None))
Success(StructuredDataTerminal(value := body, typeId := AttrToTypeId(item)))
}

function method {:opaque} StructuredToAttr(s : StructuredData) : (ret : Result<AttributeValue, string>)
//= specification/dynamodb-encryption-client/ddb-item-conversion.md#convert-structured-data-to-ddb-item
//= type=implication
//# - This [Structured Data Map](../structured-encryption/structures.md#structured-data-map),
//# if not empty,
//# MUST only contain [Structured Data Terminals](../structured-encryption/structures.md#structured-data-terminal).
ensures ret.Success? ==> s.content.Terminal?

//= specification/dynamodb-encryption-client/ddb-item-conversion.md#convert-structured-data-to-ddb-item
//= type=implication
//# - MUST NOT have [Structured Data Attributes](../structured-encryption/structures.md#structured-data-attributes).
ensures ret.Success? ==> s.attributes.None?
function method {:opaque} StructuredToAttr(s : StructuredDataTerminal) : (ret : Result<AttributeValue, string>)
{
:- Need(s.attributes.None?, "attributes must be None");
:- Need(s.content.Terminal?, "StructuredData to AttributeValue only works on Terminal data");

var Terminal(s) := s.content;
:- Need(|s.typeId| == 2, "Type ID must be two bytes");
var attrValueAndLength :- BytesToAttr(s.value, s.typeId, false);
:- Need(attrValueAndLength.len == |s.value|, "Mismatch between length of encoded data and length of data");
Expand Down
Loading
Loading