Skip to content

Commit

Permalink
add biscuit test samples 1-9 (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
daeMOn63 authored Aug 24, 2020
1 parent e7c8f8e commit c6e6e72
Show file tree
Hide file tree
Showing 15 changed files with 178 additions and 30 deletions.
11 changes: 8 additions & 3 deletions datalog/datalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type Variable uint32
func (Variable) Type() IDType { return IDTypeVariable }

func (v Variable) String() string {
return fmt.Sprintf("%d?", v)
return fmt.Sprintf("$%d", v)
}

type Integer int64
Expand Down Expand Up @@ -331,7 +331,7 @@ func (c Constraint) Check(name Variable, id ID) bool {
}

func (c Constraint) String() string {
return fmt.Sprintf("%v? %v", c.Name, c.Checker)
return fmt.Sprintf("%v %v", c.Name, c.Checker)
}

type Rule struct {
Expand Down Expand Up @@ -714,7 +714,12 @@ func (d SymbolDebugger) Rule(r Rule) string {
constraints[i] = c.String()
}

return fmt.Sprintf("%s <- %s | %s", head, strings.Join(preds, " && "), strings.Join(constraints, " && "))
var constraintStart string
if len(constraints) > 0 {
constraintStart = " @ "
}

return fmt.Sprintf("*%s <- %s%s%s", head, strings.Join(preds, ", "), constraintStart, strings.Join(constraints, ", "))
}

func (d SymbolDebugger) Caveat(c Caveat) string {
Expand Down
14 changes: 10 additions & 4 deletions proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,18 +194,21 @@ func tokenConstraintToProtoConstraint(input datalog.Constraint) *pb.Constraint {
switch input.Name.Type() {
case datalog.IDTypeDate:
pbConstraint = &pb.Constraint{
Id: uint32(input.Name),
Kind: pb.Constraint_DATE,
Date: tokenDateConstraintToProtoDateConstraint(input.Checker.(datalog.DateComparisonChecker)),
}
case datalog.IDTypeInteger:
switch input.Checker.(type) {
case datalog.IntegerComparisonChecker:
pbConstraint = &pb.Constraint{
Id: uint32(input.Name),
Kind: pb.Constraint_INT,
Int: tokenIntConstraintToProtoIntConstraint(input.Checker.(datalog.IntegerComparisonChecker)),
}
case datalog.IntegerInChecker:
pbConstraint = &pb.Constraint{
Id: uint32(input.Name),
Kind: pb.Constraint_INT,
Int: tokenIntInConstraintToProtoIntConstraint(input.Checker.(datalog.IntegerInChecker)),
}
Expand All @@ -216,6 +219,7 @@ func tokenConstraintToProtoConstraint(input datalog.Constraint) *pb.Constraint {
switch input.Checker.(type) {
case datalog.StringComparisonChecker:
pbConstraint = &pb.Constraint{
Id: uint32(input.Name),
Kind: pb.Constraint_STRING,
Str: tokenStrConstraintToProtoStrConstraint(input.Checker.(datalog.StringComparisonChecker)),
}
Expand All @@ -226,6 +230,7 @@ func tokenConstraintToProtoConstraint(input datalog.Constraint) *pb.Constraint {
}
case *datalog.StringRegexpChecker:
pbConstraint = &pb.Constraint{
Id: uint32(input.Name),
Kind: pb.Constraint_STRING,
Str: &pb.StringConstraint{
Kind: pb.StringConstraint_REGEX,
Expand All @@ -237,6 +242,7 @@ func tokenConstraintToProtoConstraint(input datalog.Constraint) *pb.Constraint {
}
case datalog.IDTypeSymbol:
pbConstraint = &pb.Constraint{
Id: uint32(input.Name),
Kind: pb.Constraint_SYMBOL,
Symbol: tokenSymbolConstraintToProtoSymbolConstraint(input.Checker.(datalog.SymbolInChecker)),
}
Expand All @@ -252,22 +258,22 @@ func protoConstraintToTokenConstraint(input *pb.Constraint) datalog.Constraint {
switch input.Kind {
case pb.Constraint_DATE:
constraint = datalog.Constraint{
Name: datalog.Variable(datalog.IDTypeDate),
Name: datalog.Variable(input.Id),
Checker: protoDateConstraintToTokenDateConstraint(input.Date),
}
case pb.Constraint_INT:
constraint = datalog.Constraint{
Name: datalog.Variable(datalog.IDTypeInteger),
Name: datalog.Variable(input.Id),
Checker: protoIntConstraintToTokenIntConstraint(input.Int),
}
case pb.Constraint_STRING:
constraint = datalog.Constraint{
Name: datalog.Variable(datalog.IDTypeString),
Name: datalog.Variable(input.Id),
Checker: protoStrConstraintToTokenStrConstraint(input.Str),
}
case pb.Constraint_SYMBOL:
constraint = datalog.Constraint{
Name: datalog.Variable(datalog.IDTypeSymbol),
Name: datalog.Variable(input.Id),
Checker: protoSymbolConstraintToTokenSymbolConstraint(input.Symbol),
}
default:
Expand Down
1 change: 1 addition & 0 deletions samples/root_key
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
y�=��.?����ruō��4�E�x:Z���k�
1 change: 1 addition & 0 deletions samples/root_key.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
R�x(�����w턔�zEDí��A�=�iX
125 changes: 119 additions & 6 deletions samples/samples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,143 @@ package samples
import (
"io/ioutil"
"testing"
"time"

"github.com/flynn/biscuit-go"
"github.com/flynn/biscuit-go/sig"
"github.com/stretchr/testify/require"
)

func TestSample1Basic(t *testing.T) {
token, err := ioutil.ReadFile("test1_basic.bc")
require.NoError(t, err)
func TestSample1_Basic(t *testing.T) {
token := loadSampleToken(t, "test1_basic.bc")

b, err := biscuit.Unmarshal(token)
require.NoError(t, err)

s, err := b.Serialize()
pubkey := loadRootPublicKey(t)

verifier, err := b.Verify(pubkey)
require.NoError(t, err)

verifier.AddOperation("read")
verifier.AddResource("file1")
require.NoError(t, verifier.Verify())

verifier.Reset()
verifier.AddOperation("read")
verifier.AddResource("file2")
require.NoError(t, verifier.Verify())

verifier.Reset()
verifier.AddOperation("write")
verifier.AddResource("file1")
require.Error(t, verifier.Verify())

s, err := b.Serialize()
require.NoError(t, err)
require.Equal(t, len(token), len(s))
}

func TestInvalidSignature(t *testing.T) {
token, err := ioutil.ReadFile("test5_invalid_signature.bc")
func TestSample2_DifferentRootKey(t *testing.T) {
token, err := ioutil.ReadFile("test2_different_root_key.bc")
require.NoError(t, err)

b, err := biscuit.Unmarshal(token)
require.NoError(t, err)

v, err := b.Verify(loadRootPublicKey(t))
require.Equal(t, biscuit.ErrUnknownPublicKey, err)
require.Nil(t, v)
}

func TestSample3_InvalidSignatureFormat(t *testing.T) {
token, err := ioutil.ReadFile("test3_invalid_signature_format.bc")
require.NoError(t, err)

b, err := biscuit.Unmarshal(token)
require.Equal(t, sig.ErrInvalidZSize, err)
require.Nil(t, b)
}

func TestSample4_RandomBlock(t *testing.T) {
token, err := ioutil.ReadFile("test4_random_block.bc")
require.NoError(t, err)

_, err = biscuit.Unmarshal(token)
require.Equal(t, sig.ErrInvalidSignature, err)
}

func TestSample5_InvalidSignature(t *testing.T) {
token := loadSampleToken(t, "test5_invalid_signature.bc")

b, err := biscuit.Unmarshal(token)
require.Equal(t, sig.ErrInvalidSignature, err)
require.Nil(t, b)
}

func TestSample6_ReorderedBlocks(t *testing.T) {
token := loadSampleToken(t, "test6_reordered_blocks.bc")

_, err := biscuit.Unmarshal(token)
require.Equal(t, biscuit.ErrInvalidBlockIndex, err)
}

func TestSample7_InvalidBlockFactAuthority(t *testing.T) {
token := loadSampleToken(t, "test7_invalid_block_fact_authority.bc")

b, err := biscuit.Unmarshal(token)
require.NoError(t, err)

_, err = b.Verify(loadRootPublicKey(t))
require.Equal(t, biscuit.ErrInvalidBlockFact, err)
}

func TestSample8_InvalidBlockFactAmbient(t *testing.T) {
token := loadSampleToken(t, "test8_invalid_block_fact_ambient.bc")

b, err := biscuit.Unmarshal(token)
require.NoError(t, err)

_, err = b.Verify(loadRootPublicKey(t))
require.Equal(t, biscuit.ErrInvalidBlockFact, err)
}

func TestSample9_ExpiredToken(t *testing.T) {
token := loadSampleToken(t, "test9_expired_token.bc")

b, err := biscuit.Unmarshal(token)
require.NoError(t, err)

v, err := b.Verify(loadRootPublicKey(t))
require.NoError(t, err)

v.AddOperation("read")
v.AddResource("file1")
v.SetTime(time.Now())
require.Error(t, v.Verify())

v.Reset()
expireTime, err := time.Parse(time.RFC3339, "2018-12-20T01:00:00+01:00")
require.NoError(t, err)

v.AddOperation("read")
v.AddResource("file1")
v.SetTime(expireTime)
require.NoError(t, v.Verify())
}

func loadSampleToken(t *testing.T, path string) []byte {
token, err := ioutil.ReadFile(path)
require.NoError(t, err)

return token
}

func loadRootPublicKey(t *testing.T) sig.PublicKey {
pk, err := ioutil.ReadFile("root_key.pub")
require.NoError(t, err)
pubkey, err := sig.NewPublicKey(pk)
require.NoError(t, err)

return pubkey
}
Binary file added samples/test2_different_root_key.bc
Binary file not shown.
Binary file added samples/test3_invalid_signature_format.bc
Binary file not shown.
Binary file added samples/test4_random_block.bc
Binary file not shown.
Binary file added samples/test6_reordered_blocks.bc
Binary file not shown.
Binary file added samples/test7_invalid_block_fact_authority.bc
Binary file not shown.
Binary file added samples/test8_invalid_block_fact_ambient.bc
Binary file not shown.
Binary file added samples/test9_expired_token.bc
Binary file not shown.
12 changes: 10 additions & 2 deletions sig/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,11 @@ func (s *TokenSignature) Sign(rng io.Reader, k Keypair, msg []byte) *TokenSignat
return s
}

// ErrInvalidSignature indicates that signature verification failed.
var ErrInvalidSignature = errors.New("sig: invalid signature")
var (
// ErrInvalidSignature indicates that signature verification failed.
ErrInvalidSignature = errors.New("sig: invalid signature")
ErrInvalidZSize = errors.New("sig: invalid Z size")
)

var ristrettoIdentity = r255.NewElement()

Expand Down Expand Up @@ -160,6 +163,11 @@ func Decode(params [][]byte, z []byte) (*TokenSignature, error) {
decodedParams[i] = e
}

// Avoid Decode panic
if len(z) != 32 {
return nil, ErrInvalidZSize
}

decodedZ := &r255.Scalar{}
if err := decodedZ.Decode(z); err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion types.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,5 +285,5 @@ type Date time.Time

func (a Date) Type() AtomType { return AtomTypeDate }
func (a Date) convert(symbols *datalog.SymbolTable) datalog.ID {
return datalog.String(time.Time(a).UnixNano())
return datalog.Date(time.Time(a).Unix())
}
42 changes: 28 additions & 14 deletions verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@ package biscuit
import (
"errors"
"fmt"
"strings"
"time"

"github.com/flynn/biscuit-go/datalog"
)

var (
ErrMissingSymbols = errors.New("biscuit: missing symbols")
ErrFailedVerifierCaveat = errors.New("biscuit: failed to verify verifier caveats")
ErrFailedBlockCaveat = errors.New("biscuit: failed to verify block caveats")
ErrMissingSymbols = errors.New("biscuit: missing symbols")
)

type Verifier interface {
AddResource(res string)
AddOperation(op string)
AddRule(rule *Rule)
AddCaveat(caveat *Caveat)
SetTime(t time.Time)
AddRule(rule Rule)
AddCaveat(caveat Caveat)
Verify() error
Reset()
PrintWorld() string
Expand All @@ -29,7 +30,7 @@ type verifier struct {
baseSymbols *datalog.SymbolTable
world *datalog.World
symbols *datalog.SymbolTable
caveats []*Caveat
caveats []Caveat
}

var _ Verifier = (*verifier)(nil)
Expand All @@ -46,7 +47,7 @@ func NewVerifier(b *Biscuit) (Verifier, error) {
baseSymbols: b.symbols.Clone(),
world: baseWorld.Clone(),
symbols: b.symbols.Clone(),
caveats: []*Caveat{},
caveats: []Caveat{},
}, nil
}

Expand Down Expand Up @@ -76,11 +77,24 @@ func (v *verifier) AddOperation(op string) {
v.world.AddFact(fact.convert(v.symbols))
}

func (v *verifier) AddRule(rule *Rule) {
func (v *verifier) SetTime(t time.Time) {
fact := Fact{
Predicate: Predicate{
Name: "time",
IDs: []Atom{
Symbol("ambient"),
Date(t),
},
},
}
v.world.AddFact(fact.convert(v.symbols))
}

func (v *verifier) AddRule(rule Rule) {
v.world.AddRule(rule.convert(v.symbols))
}

func (v *verifier) AddCaveat(caveat *Caveat) {
func (v *verifier) AddCaveat(caveat Caveat) {
v.caveats = append(v.caveats, caveat)
}

Expand Down Expand Up @@ -131,11 +145,11 @@ func (v *verifier) Verify() error {
}

if len(errs) > 0 {
var errMsg string
for _, e := range errs {
errMsg = fmt.Sprintf("%s %v, ", errMsg, e)
errMsg := make([]string, len(errs))
for i, e := range errs {
errMsg[i] = e.Error()
}
return fmt.Errorf("biscuit: verification failed: %s", errMsg)
return fmt.Errorf("biscuit: verification failed: %s", strings.Join(errMsg, ", "))
}

return nil
Expand All @@ -150,7 +164,7 @@ func (v *verifier) PrintWorld() string {
}

func (v *verifier) Reset() {
v.caveats = []*Caveat{}
v.caveats = []Caveat{}
v.world = v.baseWorld.Clone()
v.symbols = v.baseSymbols.Clone()
}

0 comments on commit c6e6e72

Please sign in to comment.