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

wip: provisional biscuit v2 protobuf #76

Closed
wants to merge 2 commits into from

Conversation

divarvel
Copy link
Collaborator

@divarvel divarvel commented Sep 2, 2021

Propositions for the biscuit v2 wire format. See #73

  • support for new crypto scheme
  • cleanup of V0 stuff
  • support for signature operations

idk if there are more things to cleanup, based on the experience with biscuit v0 and v1

--- schema.proto	2021-04-17 12:43:36.306961544 +0200
+++ schema2.proto	2021-09-02 14:59:55.822623022 +0200
@@ -3,194 +3,56 @@
 package biscuit.format.schema;
 
 message Biscuit {
-  required bytes authority = 1;
-  repeated bytes blocks = 2;
-  repeated bytes keys = 3;
-  required Signature signature = 4;
+  optional uint32 rootKeyId = 1;
+  required SignedBlock authority = 2;
+  repeated SignedBlock blocks = 3;
+  required Proof proof = 4;
 }
 
-message SealedBiscuit {
-  required bytes authority = 1;
-  repeated bytes blocks = 2;
+message SignedBlock {
+  required bytes block = 1;
+  required bytes nextKey = 2;
   required bytes signature = 3;
 }
 
-message Signature {
-  repeated bytes parameters = 1;
-  required bytes z = 2;
+message Proof {
+  oneof Content {
+    bytes nextSecret = 1;
+    bytes finalSignature = 2;
+  }
 }
 
 message Block {
   required uint32 index = 1;
+  // ^ is this still useful?
   repeated string symbols = 2;
-  repeated FactV0 facts_v0 = 3;
-  repeated RuleV0 rules_v0 = 4;
-  repeated CaveatV0 caveats_v0 = 5;
-  optional string context = 6;
-  optional uint32 version = 7;
-  repeated FactV1 facts_v1 = 8;
-  repeated RuleV1 rules_v1 = 9;
-  repeated CheckV1 checks_v1 = 10;
+  optional string context = 3;
+  optional uint32 version = 4;
+  repeated FactV2 facts_v2 = 5;
+  repeated RuleV2 rules_v2 = 6;
+  repeated CheckV2 checks_v2 = 7;
 }
 
-message FactV0 {
-  required PredicateV0 predicate = 1;
+message FactV2 {
+  required PredicateV2 predicate = 1;
 }
 
-message RuleV0 {
-  required PredicateV0 head = 1;
-  repeated PredicateV0 body = 2;
-  repeated ConstraintV0 constraints = 3;
+message RuleV2 {
+  required PredicateV2 head = 1;
+  repeated PredicateV2 body = 2;
+  repeated ExpressionV2 expressions = 3;
 }
 
-message CaveatV0 {
-  repeated RuleV0 queries = 1;
+message CheckV2 {
+  repeated RuleV2 queries = 1;
 }
 
-message PredicateV0 {
+message PredicateV2 {
   required uint64 name = 1;
-  repeated IDV0 ids = 2;
-}
-
-message IDV0 {
-  enum Kind {
-    SYMBOL = 0;
-    VARIABLE = 1;
-    INTEGER = 2;
-    STR = 3;
-    DATE = 4;
-    BYTES = 5;
-  }
-
-  required Kind kind = 1;
-  optional uint64 symbol = 2;
-  optional uint32 variable = 3;
-  optional int64 integer = 4;
-  optional string str = 5;
-  optional uint64 date = 6;
-  optional bytes bytes = 7;
-}
-
-message ConstraintV0 {
-  required uint32 id = 1;
-
-  enum Kind {
-    INT = 0;
-    STRING = 1;
-    DATE = 2;
-    SYMBOL = 3;
-    BYTES = 4;
-  }
-
-  required Kind kind = 2;
-
-  optional IntConstraintV0 int = 3;
-  optional StringConstraintV0 str = 4;
-  optional DateConstraintV0 date = 5;
-  optional SymbolConstraintV0 symbol = 6;
-  optional BytesConstraintV0 bytes = 7;
+  repeated IDV2 ids = 2;
 }
 
-message IntConstraintV0 {
-  enum Kind {
-    LOWER = 0;
-    LARGER = 1;
-    LOWER_OR_EQUAL = 2;
-    LARGER_OR_EQUAL = 3;
-    EQUAL = 4;
-    IN = 5;
-    NOT_IN = 6;
-  }
-
-  required Kind kind = 1;
-
-  optional int64 lower = 2;
-  optional int64 larger = 3;
-  optional int64 lower_or_equal = 4;
-  optional int64 larger_or_equal = 5;
-  optional int64 equal = 6;
-  repeated int64 in_set = 7 [packed=true];
-  repeated int64 not_in_set = 8 [packed=true];
-}
-
-message StringConstraintV0 {
-  enum Kind {
-    PREFIX = 0;
-    SUFFIX = 1;
-    EQUAL = 2;
-    IN = 3;
-    NOT_IN = 4;
-    REGEX = 5;
-  }
-
-  required Kind kind = 1;
-
-  optional string prefix = 2;
-  optional string suffix = 3;
-  optional string equal = 4;
-  repeated string in_set = 5;
-  repeated string not_in_set = 6;
-  optional string regex = 7;
-}
-
-message DateConstraintV0 {
-  enum Kind {
-    BEFORE = 0;
-    AFTER = 1;
-  }
-
-  required Kind kind = 1;
-
-  optional uint64 before = 2;
-  optional uint64 after = 3;
-}
-
-message SymbolConstraintV0 {
-  enum Kind {
-    IN = 0;
-    NOT_IN = 1;
-  }
-
-  required Kind kind = 1;
-
-  repeated uint64 in_set = 2;
-  repeated uint64 not_in_set = 3;
-}
-
-message BytesConstraintV0 {
-  enum Kind {
-    EQUAL = 0;
-    IN = 1;
-    NOT_IN = 2;
-  }
-
-  required Kind kind = 1;
-
-  optional bytes equal = 2;
-  repeated bytes in_set = 3;
-  repeated bytes not_in_set = 4;
-}
-
-message FactV1 {
-  required PredicateV1 predicate = 1;
-}
-
-message RuleV1 {
-  required PredicateV1 head = 1;
-  repeated PredicateV1 body = 2;
-  repeated ExpressionV1 expressions = 3;
-}
-
-message CheckV1 {
-  repeated RuleV1 queries = 1;
-}
-
-message PredicateV1 {
-  required uint64 name = 1;
-  repeated IDV1 ids = 2;
-}
-
-message IDV1 {
+message IDV2 {
   oneof Content {
     uint64 symbol = 1;
     uint32 variable = 2;
@@ -204,22 +66,22 @@
 }
 
 message IDSet {
-  repeated IDV1 set = 1;
+  repeated IDV2 set = 1;
 }
 
-message ConstraintV1 {
+message ConstraintV2 {
   required uint32 id = 1;
 
   oneof Constraint {
-    IntConstraintV1 int = 2;
-    StringConstraintV1 string = 3;
-    DateConstraintV1 date = 4;
-    SymbolConstraintV1 symbol = 5;
-    BytesConstraintV1 bytes = 6;
+    IntConstraintV2 int = 2;
+    StringConstraintV2 string = 3;
+    DateConstraintV2 date = 4;
+    SymbolConstraintV2 symbol = 5;
+    BytesConstraintV2 bytes = 6;
   }
 }
 
-message IntConstraintV1 {
+message IntConstraintV2 {
   oneof Constraint {
     int64 less_than = 1;
     int64 greater_than = 2;
@@ -235,7 +97,7 @@
   repeated int64 set = 7 [packed=true];
 }
 
-message StringConstraintV1 {
+message StringConstraintV2 {
   oneof Constraint {
     string prefix = 1;
     string suffix = 2;
@@ -250,14 +112,14 @@
   repeated string set = 1;
 }
 
-message DateConstraintV1 {
+message DateConstraintV2 {
   oneof Constraint {
     uint64 before = 1;
     uint64 after = 2;
   }
 }
 
-message SymbolConstraintV1 {
+message SymbolConstraintV2 {
   oneof Constraint {
     SymbolSet in_set = 1;
     SymbolSet not_in_set = 2;
@@ -268,7 +130,7 @@
   repeated uint64 set = 1 [packed=true];
 }
 
-message BytesConstraintV1 {
+message BytesConstraintV2 {
   oneof Constraint {
     bytes equal = 1;
     BytesSet in_set = 2;
@@ -280,15 +142,16 @@
   repeated bytes set = 1;
 }
 
-message ExpressionV1 {
+message ExpressionV2 {
   repeated Op ops = 1;
 }
 
 message Op {
   oneof Content {
-    IDV1 value = 1;
+    IDV2 value = 1;
     OpUnary unary = 2;
     OpBinary Binary = 3;
+    OpTernary Ternary = 4;
   }
 }
 
@@ -321,6 +184,15 @@
     Or = 14;
     Intersection = 15;
     Union = 16;
+    SignEd25519 = 17;
+  }
+
+  required Kind kind = 1;
+}
+
+message OpTernary {
+  enum Kind {
+    VerifyEd25519Signature = 0;
   }
 
   required Kind kind = 1;
@@ -332,15 +204,15 @@
     Deny = 1;
   }
 
-  repeated RuleV1 queries = 1;
+  repeated RuleV2 queries = 1;
   required Kind kind = 2;
 }
 
 message VerifierPolicies {
   repeated string symbols = 1;
   optional uint32 version = 2;
-  repeated FactV1 facts = 3;
-  repeated RuleV1 rules = 4;
-  repeated CheckV1 checks = 5;
+  repeated FactV2 facts = 3;
+  repeated RuleV2 rules = 4;
+  repeated CheckV2 checks = 5;
   repeated Policy policies = 6;
 }


message Block {
required uint32 index = 1;
// ^ is this still useful?
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems redundant with the block index in the list. What should be done if there is a discrepancy between explicit indices and the position in the list?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the field can be removed, since now the signatures guarantee the order

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

required Kind kind = 1;
}

message OpTernary {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there was talk of n-ary operations, but with a stack model, I think it's better to have the arity explicit. In any case, adding new operations will be backwards-compatible wrt to the wire format

Or = 14;
Intersection = 15;
Union = 16;
SignEd25519 = 17;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there was agreement on supporting signature operations. there was no clear decision on the API. Here i think supporting the same alg that's used for the token itself is a good choice, and making it explicit in the tokens is also a good choice, while we decide if and how we'd want to have configurable signature algorithms.

@divarvel
Copy link
Collaborator Author

divarvel commented Sep 3, 2021

The 2.0 changes have been integrated in the relevant branch. The ed25519 operations can be done later, as they're completely unrelated to the rest.

@divarvel divarvel closed this Sep 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants