"veyron2/security": Added BlessingRoots and BlessingStore

Added the BlessingRoots and BlessingStore interfaces from
https://veyron-review.googlesource.com/#/c/4102/ and
implemented them in veyron/runtimes/google/rt

At the moment the interfaces are not used anywhere, the next CL
will replace PublicIDStore and the current TrustedKeys map
with BlessingStore and BlessingRoots respectively.

Change-Id: I8f16d739098b51cb82ebbd25a17cee30547c80f5
diff --git a/runtimes/google/rt/blessingroots.go b/runtimes/google/rt/blessingroots.go
new file mode 100644
index 0000000..bff2c08
--- /dev/null
+++ b/runtimes/google/rt/blessingroots.go
@@ -0,0 +1,113 @@
+package rt
+
+import (
+	"crypto/sha256"
+	"errors"
+	"sync"
+
+	"veyron/security/serialization"
+
+	"veyron2/security"
+)
+
+const (
+	blessingRootsDataFile = "blessingroots.data"
+	blessingRootsSigFile  = "blessingroots.sig"
+)
+
+// blessingRoots implements security.BlessingRoots.
+type blessingRoots struct {
+	store  map[string][]security.BlessingPattern // GUARDED_BY(mu)
+	dir    string
+	signer serialization.Signer
+	mu     sync.RWMutex
+}
+
+func storeMapKey(root security.PublicKey) (string, error) {
+	rootBytes, err := root.MarshalBinary()
+	if err != nil {
+		return "", err
+	}
+	rootBytesHash := sha256.Sum256(rootBytes)
+	return string(rootBytesHash[:]), nil
+}
+
+func (br *blessingRoots) Add(root security.PublicKey, pattern security.BlessingPattern) error {
+	key, err := storeMapKey(root)
+	if err != nil {
+		return err
+	}
+
+	br.mu.Lock()
+	defer br.mu.Unlock()
+	patterns := br.store[key]
+	for _, p := range patterns {
+		if p == pattern {
+			return nil
+		}
+	}
+	br.store[key] = append(patterns, pattern)
+
+	if err := br.save(); err != nil {
+		br.store[key] = patterns[:len(patterns)-1]
+		return err
+	}
+	return nil
+}
+
+func (br *blessingRoots) Recognized(root security.PublicKey, blessing string) error {
+	key, err := storeMapKey(root)
+	if err != nil {
+		return err
+	}
+
+	br.mu.RLock()
+	defer br.mu.RUnlock()
+	for _, p := range br.store[key] {
+		if p.MatchedBy(blessing) {
+			return nil
+		}
+	}
+	return errors.New("PublicKey is not a recognized root for this blessing")
+}
+
+func (br *blessingRoots) save() error {
+	if (br.signer == nil) && (br.dir == "") {
+		return nil
+	}
+	return encodeAndStore(br.store, br.dir, blessingRootsDataFile, blessingRootsSigFile, br.signer)
+}
+
+// NewInMemoryBlessingRoots returns an in-memory security.BlessingRoots.
+//
+// The returned BlessingRoots is initialized with an empty set of keys.
+func NewInMemoryBlessingRoots() security.BlessingRoots {
+	return &blessingRoots{
+		store: make(map[string][]security.BlessingPattern),
+	}
+}
+
+// NewPersistingBlessingRoots returns a security.BlessingRoots that signs
+// and persists all updates to the provided directory. Signing is carried
+// out using the provided signer.
+//
+// The returned BlessingRoots is initialized from the existing data present
+// in the directory. The data is verified to have been written by a persisting
+// BlessingRoots object constructed from the same signer.
+//
+// Any errors obtained in reading or verifying the data are returned.
+func NewPersistingBlessingRoots(directory string, signer serialization.Signer) (security.BlessingRoots, error) {
+	if directory == "" || signer == nil {
+		return nil, errors.New("directory or signer is not specified")
+	}
+	br := &blessingRoots{
+		store:  make(map[string][]security.BlessingPattern),
+		dir:    directory,
+		signer: signer,
+	}
+
+	if err := decodeFromStorage(&br.store, br.dir, blessingRootsDataFile, blessingRootsSigFile, br.signer.PublicKey()); err != nil {
+		return nil, err
+	}
+	return br, nil
+}
diff --git a/runtimes/google/rt/blessingroots_test.go b/runtimes/google/rt/blessingroots_test.go
new file mode 100644
index 0000000..39d823a
--- /dev/null
+++ b/runtimes/google/rt/blessingroots_test.go
@@ -0,0 +1,134 @@
+package rt
+
+import (
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"strings"
+	"testing"
+
+	"veyron2/security"
+)
+
+type s []string
+
+type tester struct {
+	k1, k2, k3 security.PublicKey
+}
+
+func (t *tester) testAdd(br security.BlessingRoots) error {
+	testdata := []struct {
+		root    security.PublicKey
+		pattern security.BlessingPattern
+	}{
+		{t.k1, "veyron/..."},
+		{t.k2, "google/foo/..."},
+		{t.k1, "google"},
+	}
+	for _, d := range testdata {
+		if err := br.Add(d.root, d.pattern); err != nil {
+			return fmt.Errorf("%v.Add(%v, %q) failed: %s", br, d.root, d.pattern, err)
+		}
+	}
+	return nil
+}
+
+func (t *tester) testRecognized(br security.BlessingRoots) error {
+	testdata := []struct {
+		root          security.PublicKey
+		recognized    []string
+		notRecognized []string
+	}{
+		{t.k1, s{"veyron", "veyron/foo", "veyron/foo/bar", "google"}, s{"google/foo", "foo", "foo/bar"}},
+		{t.k2, s{"google", "google/foo", "google/foo/bar"}, s{"google/bar", "veyron", "veyron/foo", "foo", "foo/bar"}},
+		{t.k3, s{}, s{"veyron", "veyron/foo", "veyron/bar", "google", "google/foo", "google/bar", "foo", "foo/bar"}},
+	}
+	for _, d := range testdata {
+		for _, b := range d.recognized {
+			if err := br.Recognized(d.root, b); err != nil {
+				return fmt.Errorf("%v.Recognized(%v, %q): got: %v, want nil", br, d.root, b, err)
+			}
+		}
+		for _, b := range d.notRecognized {
+			if err := matchesError(br.Recognized(d.root, b), "not a recognized root"); err != nil {
+				return fmt.Errorf("%v.Recognized(%v, %q): %v", br, d.root, b, err)
+			}
+		}
+	}
+	return nil
+}
+
+func mkKey() security.PublicKey {
+	s, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		panic(err)
+	}
+	return security.NewECDSAPublicKey(&s.PublicKey)
+}
+
+func matchesError(err error, pattern string) error {
+	retErr := fmt.Errorf("got error: %v, want to match: %v", err, pattern)
+	if (len(pattern) == 0) != (err == nil) {
+		return retErr
+	}
+	if (err != nil) && (strings.Index(err.Error(), pattern) < 0) {
+		return retErr
+	}
+	return nil
+}
+
+func TestInMemoryBlessingRoots(t *testing.T) {
+	br := NewInMemoryBlessingRoots()
+	tester := tester{mkKey(), mkKey(), mkKey()}
+	if err := tester.testAdd(br); err != nil {
+		t.Error(err)
+	}
+	if err := tester.testRecognized(br); err != nil {
+		t.Error(err)
+	}
+}
+func TestPersistingBlessingRoots(t *testing.T) {
+	newTempDir := func(name string) string {
+		dir, err := ioutil.TempDir("", name)
+		if err != nil {
+			t.Fatal(err)
+		}
+		return dir
+	}
+
+	tester := tester{mkKey(), mkKey(), mkKey()}
+
+	// Create a new persisting BlessingRoots and add key k1 as an authority over
+	// blessings matching "veyron/...".
+	dir := newTempDir("blessingstore")
+	defer os.RemoveAll(dir)
+	signer := newChain("signer")
+	br, err := NewPersistingBlessingRoots(dir, signer)
+	if err != nil {
+		t.Fatalf("NewPersistingBlessingRoots failed: %s", err)
+	}
+
+	if err := tester.testAdd(br); err != nil {
+		t.Error(err)
+	}
+	if err := tester.testRecognized(br); err != nil {
+		t.Error(err)
+	}
+
+	// Test that all mutations are appropriately reflected in a BlessingRoots
+	// constructed from same directory and signer.
+	br, err = NewPersistingBlessingRoots(dir, signer)
+	if err != nil {
+		t.Fatalf("NewPersistingBlessingRoots failed: %s", err)
+	}
+
+	if err := tester.testAdd(br); err != nil {
+		t.Error(err)
+	}
+	if err := tester.testRecognized(br); err != nil {
+		t.Error(err)
+	}
+}
diff --git a/runtimes/google/rt/blessingstore.go b/runtimes/google/rt/blessingstore.go
new file mode 100644
index 0000000..f353111
--- /dev/null
+++ b/runtimes/google/rt/blessingstore.go
@@ -0,0 +1,212 @@
+package rt
+
+import (
+	"errors"
+	"fmt"
+	"reflect"
+	"strings"
+	"sync"
+
+	isecurity "veyron/runtimes/google/security"
+	"veyron/security/serialization"
+
+	"veyron2/security"
+	"veyron2/vlog"
+)
+
+const (
+	blessingStoreDataFile = "blessingstore.data"
+	blessingStoreSigFile  = "blessingstore.sig"
+)
+
+var errStoreAddMismatch = errors.New("blessing's public key does not match store's public key")
+
+type markedBlessings struct {
+	Blessings security.PublicID
+	Patterns  []security.BlessingPattern
+}
+
+type persistentState struct {
+	// Store contains a set of Blessings marked with a set of BlessingsPatterns.
+	// These blessings are intended to be shared with peers whose blessings
+	// match the corresponding pattern. All Blessings in the store must have
+	// the same public key.
+	Store []markedBlessings
+	// Default is the default Blessings to be shared with peers for which
+	// no other information is available to select blessings.
+	Default security.PublicID
+}
+
+// blessingStore implements security.BlessingStore.
+type blessingStore struct {
+	state     persistentState // GUARDED_BY(mu)
+	publicKey security.PublicKey
+	dir       string
+	signer    serialization.Signer
+	mu        sync.RWMutex
+}
+
+func (s *blessingStore) Add(blessings security.PublicID, forPeers security.BlessingPattern) error {
+	if !reflect.DeepEqual(blessings.PublicKey(), s.publicKey) {
+		return errStoreAddMismatch
+	}
+	if err := validateBlessingPattern(forPeers); err != nil {
+		return err
+	}
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	var entry *markedBlessings
+	for i, mb := range s.state.Store {
+		if !reflect.DeepEqual(mb.Blessings, blessings) {
+			continue
+		}
+		entry = &s.state.Store[i]
+		for _, p := range mb.Patterns {
+			if p == forPeers {
+				return nil
+			}
+		}
+		break
+	}
+	if entry == nil {
+		s.state.Store = append(s.state.Store, markedBlessings{blessings, []security.BlessingPattern{forPeers}})
+	} else {
+		entry.Patterns = append(entry.Patterns, forPeers)
+	}
+
+	if err := s.save(); err != nil {
+		if entry == nil {
+			s.state.Store = s.state.Store[:len(s.state.Store)-1]
+		} else {
+			entry.Patterns = entry.Patterns[:len(entry.Patterns)-1]
+		}
+		return err
+	}
+	return nil
+}
+
+func (s *blessingStore) ForPeer(peerBlessings ...string) security.PublicID {
+	s.mu.RLock()
+	defer s.mu.RUnlock()
+
+	var matchingBlessings []security.PublicID
+	for _, mb := range s.state.Store {
+		for _, p := range mb.Patterns {
+			if p.MatchedBy(peerBlessings...) {
+				matchingBlessings = append(matchingBlessings, mb.Blessings)
+				break
+			}
+		}
+	}
+
+	blessings, err := isecurity.NewSetPublicID(matchingBlessings...)
+	if err != nil {
+		// This case should never be hit.
+		vlog.Errorf("BlessingStore: %s is broken, could not combine PublicIDs from it: %s", s, err)
+		return nil
+	}
+	return blessings
+}
+
+func (s *blessingStore) Default() security.PublicID {
+	s.mu.RLock()
+	defer s.mu.RUnlock()
+	if s.state.Default != nil {
+		return s.state.Default
+	}
+	return s.ForPeer()
+}
+
+func (s *blessingStore) SetDefault(blessings security.PublicID) error {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+	if !reflect.DeepEqual(blessings.PublicKey(), s.publicKey) {
+		return errStoreAddMismatch
+	}
+	oldDefault := s.state.Default
+	s.state.Default = blessings
+	if err := s.save(); err != nil {
+		s.state.Default = oldDefault
+	}
+	return nil
+}
+
+func (s *blessingStore) PublicKey() security.PublicKey {
+	return s.publicKey
+}
+
+func (s *blessingStore) String() string {
+	return fmt.Sprintf("{state: %v, publicKey: %v, dir: %v}", s.state, s.publicKey, s.dir)
+}
+
+func (s *blessingStore) save() error {
+	if (s.signer == nil) && (s.dir == "") {
+		return nil
+	}
+	return encodeAndStore(s.state, s.dir, blessingStoreDataFile, blessingStoreSigFile, s.signer)
+}
+
+// TODO(ataly): Use ValidateBlessingPattern from "veyron2/security" when available.
+func validateBlessingPattern(pattern security.BlessingPattern) error {
+	errInvalidPattern := func(pattern security.BlessingPattern) error {
+		return fmt.Errorf("invalid blessing pattern:%q", pattern)
+	}
+
+	patternParts := strings.Split(string(pattern), security.ChainSeparator)
+	for i, p := range patternParts {
+		if p == "" {
+			return errInvalidPattern(pattern)
+		}
+		glob := string(security.AllPrincipals)
+		if p != glob && strings.Contains(p, glob) {
+			return errInvalidPattern(pattern)
+		}
+		if p == glob && (i < len(patternParts)-1) {
+			return errInvalidPattern(pattern)
+		}
+	}
+	return nil
+}
+
+// NewInMemoryBlessingStore returns an in-memory security.BlessingStore for a
+// principal with the provided PublicKey.
+//
+// The returned BlessingStore is initialized with an empty set of blessings.
+func NewInMemoryBlessingStore(publicKey security.PublicKey) security.BlessingStore {
+	return &blessingStore{
+		publicKey: publicKey,
+	}
+}
+
+// NewPersistingBlessingStore returns a security.BlessingStore for a principal
+// with the provided PublicKey that signs and persists all updates to the
+// specified directory. Signing is carried out using the provided signer.
+//
+// The returned BlessingStore is initialized from the existing data present in
+// the directory. The data is verified to have been written by a persisting
+// BlessingStore object constructed from the same PublicKey and signer.
+//
+// Any errors obtained in reading or verifying the data are returned.
+func NewPersistingBlessingStore(publicKey security.PublicKey, directory string, signer serialization.Signer) (security.BlessingStore, error) {
+	if directory == "" || signer == nil {
+		return nil, errors.New("directory or signer is not specified")
+	}
+	s := &blessingStore{
+		publicKey: publicKey,
+		dir:       directory,
+		signer:    signer,
+	}
+
+	if err := decodeFromStorage(&s.state, s.dir, blessingStoreDataFile, blessingStoreSigFile, s.signer.PublicKey()); err != nil {
+		return nil, err
+	}
+
+	for _, mb := range s.state.Store {
+		if !reflect.DeepEqual(mb.Blessings.PublicKey(), publicKey) {
+			return nil, fmt.Errorf("directory contains Blessings: %v that are not for the provided PublicKey: %v", mb.Blessings, publicKey)
+		}
+	}
+	return s, nil
+}
diff --git a/runtimes/google/rt/blessingstore_test.go b/runtimes/google/rt/blessingstore_test.go
new file mode 100644
index 0000000..05395f1
--- /dev/null
+++ b/runtimes/google/rt/blessingstore_test.go
@@ -0,0 +1,312 @@
+package rt
+
+import (
+	"bytes"
+	"io/ioutil"
+	"os"
+	"reflect"
+	"sort"
+	"strings"
+	"testing"
+	"time"
+
+	isecurity "veyron/runtimes/google/security"
+	"veyron2/security"
+	"veyron2/vom"
+)
+
+var (
+	cVeyron = newChain("veyron")
+	cGoogle = newChain("google")
+)
+
+func newChain(name string) security.PrivateID {
+	id, err := isecurity.NewPrivateID(name, nil)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+func newSetPublicID(ids ...security.PublicID) security.PublicID {
+	id, err := isecurity.NewSetPublicID(ids...)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+func bless(blessee security.PublicID, blessor security.PrivateID, name string, caveats []security.Caveat) security.PublicID {
+	blessed, err := blessor.Bless(blessee, name, 5*time.Minute, caveats)
+	if err != nil {
+		panic(err)
+	}
+	return blessed
+}
+
+func verifyBlessingsAndPublicKey(blessings security.PublicID, wantBlessings []string, wantPublicKey security.PublicKey) bool {
+	if blessings == nil {
+		return len(wantBlessings) == 0
+	}
+	gotBlessings := blessings.Names()
+	sort.Strings(gotBlessings)
+	sort.Strings(wantBlessings)
+	return reflect.DeepEqual(gotBlessings, wantBlessings) && reflect.DeepEqual(blessings.PublicKey(), wantPublicKey)
+}
+
+func TestStoreSetters(t *testing.T) {
+	matchesErrorPattern := func(err error, pattern string) bool {
+		if (len(pattern) == 0) != (err == nil) {
+			return false
+		}
+		return err == nil || strings.Index(err.Error(), pattern) >= 0
+	}
+	var (
+		// test principals
+		cAlice       = newChain("alice")
+		cAlicePub    = cAlice.PublicID()
+		cBobPub      = newChain("bob").PublicID()
+		cVeyronAlice = bless(cAlice.PublicID(), cVeyron, "alice", nil)
+		sAlice       = newSetPublicID(cAlicePub, cVeyronAlice)
+
+		pkey = cAlicePub.PublicKey()
+	)
+
+	s := NewInMemoryBlessingStore(pkey)
+
+	testDataForAdd := []struct {
+		blessings []security.PublicID
+		patterns  []security.BlessingPattern
+		wantErr   string
+	}{
+		{
+			blessings: []security.PublicID{cAlicePub, cVeyronAlice, sAlice},
+			patterns:  []security.BlessingPattern{"...", "foo", "foo/bar"},
+		},
+		{
+			blessings: []security.PublicID{cBobPub},
+			patterns:  []security.BlessingPattern{"...", "foo", "foo/bar"},
+			wantErr:   "public key does not match",
+		},
+		{
+			blessings: []security.PublicID{cAlicePub, cVeyronAlice, sAlice},
+			patterns:  []security.BlessingPattern{"", "foo...", "...foo", "/bar", "foo/", "foo/.../bar"},
+			wantErr:   "invalid blessing pattern",
+		},
+	}
+	for _, d := range testDataForAdd {
+		for _, b := range d.blessings {
+			for _, p := range d.patterns {
+				if got := s.Add(b, p); !matchesErrorPattern(got, d.wantErr) {
+					t.Errorf("%v.Add(%v, %q): got error: %v, want to match: %q", s, b, p, got, d.wantErr)
+				}
+			}
+		}
+	}
+	testDataForSetDefault := []struct {
+		blessings []security.PublicID
+		wantErr   string
+	}{
+		{
+			blessings: []security.PublicID{cAlicePub, cVeyronAlice, sAlice},
+		},
+		{
+			blessings: []security.PublicID{cBobPub},
+			wantErr:   "public key does not match",
+		},
+	}
+	for _, d := range testDataForSetDefault {
+		for _, b := range d.blessings {
+			if got := s.SetDefault(b); !matchesErrorPattern(got, d.wantErr) {
+				t.Errorf("%v.SetDefault(%v): got error: %v, want to match: %q", s, b, got, d.wantErr)
+			}
+		}
+	}
+}
+
+func TestStoreGetters(t *testing.T) {
+	add := func(s security.BlessingStore, blessings security.PublicID, forPeers security.BlessingPattern) {
+		if err := s.Add(blessings, forPeers); err != nil {
+			t.Fatalf("%v.Add(%v, %q) failed unexpectedly: %s", s, blessings, forPeers, err)
+		}
+	}
+	var (
+		// test principals
+		cAlice       = newChain("alice")
+		cVeyronAlice = bless(cAlice.PublicID(), cVeyron, "alice", nil)
+		cGoogleAlice = bless(cAlice.PublicID(), cGoogle, "alice", nil)
+		sAlice       = newSetPublicID(cVeyronAlice, cGoogleAlice)
+
+		pkey = cAlice.PublicID().PublicKey()
+	)
+
+	// Create a new BlessingStore for Alice and add her blessings to it.
+	s := NewInMemoryBlessingStore(pkey)
+
+	add(s, cVeyronAlice, "veyron/foo/...")
+	add(s, cGoogleAlice, "veyron/bar")
+	add(s, sAlice, "google")
+
+	// Test ForPeer
+	testDataForPeer := []struct {
+		peerBlessings []string
+		blessings     []string
+	}{
+		{nil, nil},
+		{[]string{"foo"}, nil},
+		{[]string{"google"}, []string{"veyron/alice", "google/alice"}},
+		{[]string{"veyron"}, []string{"veyron/alice", "google/alice"}},
+		{[]string{"google/foo"}, nil},
+		{[]string{"veyron/baz"}, nil},
+		{[]string{"veyron/foo"}, []string{"veyron/alice"}},
+		{[]string{"veyron/bar"}, []string{"google/alice"}},
+		{[]string{"foo", "veyron/bar"}, []string{"google/alice"}},
+		{[]string{"veyron/foo/bar", "veyron/bar"}, []string{"veyron/alice", "google/alice"}},
+		{[]string{"veyron/foo/bar", "veyron/bar/baz"}, []string{"veyron/alice"}},
+	}
+	for _, d := range testDataForPeer {
+		if got := s.ForPeer(d.peerBlessings...); !verifyBlessingsAndPublicKey(got, d.blessings, pkey) {
+			t.Errorf("%v.ForPeer(%v): got: %q, want Blessings: %q", s, d.peerBlessings, got, d.blessings)
+		}
+	}
+
+	// Test Default
+	// Default should return nil as SetDefault has not been invoked and no blessing
+	// has been marked for all peers.
+	if got := s.Default(); got != nil {
+		t.Errorf("%v.Default(): got: %v, want: nil", s, got)
+	}
+
+	// Mark the blessings: cVeyronAlice and cGoogleAlice for all peers, and check that
+	// Default returns the union of those blessings
+	add(s, cVeyronAlice, security.AllPrincipals)
+	add(s, cGoogleAlice, security.AllPrincipals)
+	defaultBlessings := []string{"veyron/alice", "google/alice"}
+	if got := s.Default(); !verifyBlessingsAndPublicKey(got, defaultBlessings, pkey) {
+		t.Errorf("%v.Default(): got: %v, want Blessings: %v", s, got, defaultBlessings)
+	}
+
+	// Set the blessing cVeyronAlice as default and check that Default returns it.
+	if err := s.SetDefault(cVeyronAlice); err != nil {
+		t.Fatalf("%v.SetDefault(%v) failed: %s", s, cVeyronAlice, err)
+	}
+	if got, want := s.Default(), cVeyronAlice; !reflect.DeepEqual(got, want) {
+		t.Errorf("%v.Default(): got: %v, want: %v", s, got, want)
+	}
+}
+
+func TestBlessingStoreDuplicates(t *testing.T) {
+	roundTrip := func(blessings security.PublicID) security.PublicID {
+		var b bytes.Buffer
+		if err := vom.NewEncoder(&b).Encode(blessings); err != nil {
+			t.Fatalf("could not VOM-Encode Blessings: %s", err)
+		}
+		var decodedBlessings security.PublicID
+		if err := vom.NewDecoder(&b).Decode(&decodedBlessings); err != nil {
+			t.Fatalf("could not VOM-Decode Blessings: %s", err)
+		}
+		return decodedBlessings
+	}
+	add := func(s security.BlessingStore, blessings security.PublicID, forPeers security.BlessingPattern) {
+		if err := s.Add(blessings, forPeers); err != nil {
+			t.Fatalf("%v.Add(%v, %q) failed unexpectedly: %s", s, blessings, forPeers, err)
+		}
+	}
+	var (
+		// test principals
+		cAlice       = newChain("alice")
+		cVeyronAlice = bless(cAlice.PublicID(), cVeyron, "alice", nil)
+
+		pkey = cAlice.PublicID().PublicKey()
+	)
+
+	// Create a new BlessingStore add the blessings cVeyronAlice to it twice.
+	s := NewInMemoryBlessingStore(pkey)
+	add(s, cVeyronAlice, "google")
+	add(s, roundTrip(cVeyronAlice), "google/foo")
+
+	peer := "google"
+	wantBlessings := []string{"veyron/alice"}
+	if got := s.ForPeer(peer); !verifyBlessingsAndPublicKey(got, wantBlessings, pkey) {
+		t.Errorf("%v.ForPeer(%v): got: %q, want Blessings: %q", s, peer, got, wantBlessings)
+	}
+}
+
+func TestPersistingBlessingStore(t *testing.T) {
+	newTempDir := func(name string) string {
+		dir, err := ioutil.TempDir("", name)
+		if err != nil {
+			t.Fatal(err)
+		}
+		return dir
+	}
+
+	var (
+		signer = newChain("signer")
+
+		cAlice       = newChain("alice")
+		cVeyronAlice = bless(cAlice.PublicID(), cVeyron, "alice", nil)
+		cGoogleAlice = bless(cAlice.PublicID(), cGoogle, "alice", nil)
+
+		pkey = cAlice.PublicID().PublicKey()
+	)
+
+	// Create a new persisting BlessingStore.
+	dir := newTempDir("blessingstore")
+	defer os.RemoveAll(dir)
+
+	s, err := NewPersistingBlessingStore(pkey, dir, signer)
+	if err != nil {
+		t.Fatalf("NewPersistingBlessingStore failed: %s", err)
+	}
+	if err := s.Add(cVeyronAlice, "veyron/..."); err != nil {
+		t.Fatalf("%v.Add(%v, ...) failed: %s", s, cVeyronAlice, err)
+	}
+	if err := s.SetDefault(cGoogleAlice); err != nil {
+		t.Fatalf("%v.SetDefault(%v) failed: %s", s, cGoogleAlice, err)
+	}
+
+	// Test that all mutations are appropriately reflected in a BlessingStore constructed
+	// from same public key, directory and signer.
+	s, err = NewPersistingBlessingStore(pkey, dir, signer)
+	if err != nil {
+		t.Fatalf("NewPersistingBlessingStore failed: %s", err)
+	}
+
+	if got, want := s.PublicKey(), pkey; !reflect.DeepEqual(got, want) {
+		t.Errorf("%v.PublicKey(): got: %v, want: %v", s, got, want)
+	}
+
+	testDataForPeer := []struct {
+		peerBlessings []string
+		blessings     []string
+	}{
+		{peerBlessings: nil, blessings: nil},
+		{peerBlessings: []string{"google"}, blessings: nil},
+		{peerBlessings: []string{"veyron"}, blessings: []string{"veyron/alice"}},
+		{peerBlessings: []string{"veyron/foo"}, blessings: []string{"veyron/alice"}},
+		{peerBlessings: []string{"google", "veyron/foo"}, blessings: []string{"veyron/alice"}},
+	}
+	for _, d := range testDataForPeer {
+		if got := s.ForPeer(d.peerBlessings...); !verifyBlessingsAndPublicKey(got, d.blessings, pkey) {
+			t.Errorf("%v.ForPeer(%s): got: %q, want Blessings: %q", s, d.peerBlessings, got, d.blessings)
+		}
+	}
+
+	if got, want := s.Default(), cGoogleAlice; !reflect.DeepEqual(got, want) {
+		t.Errorf("%v.Default(): got: %v, want: %v", s, got, want)
+	}
+
+	// Test that constructing a BlesssingStore from the same directory and signer, but for a different
+	// publicKey fails
+	pkey = newChain("irrelevant").PublicID().PublicKey()
+	_, err = NewPersistingBlessingStore(pkey, dir, signer)
+	if err == nil {
+		t.Fatalf("NewPersistingBlessingStore(%v, %v, %v) passed uneexpectedly", pkey, dir, signer)
+	}
+}
+
+func init() {
+	isecurity.TrustIdentityProviders(cVeyron)
+	isecurity.TrustIdentityProviders(cGoogle)
+}
diff --git a/runtimes/google/rt/util.go b/runtimes/google/rt/util.go
new file mode 100644
index 0000000..d8bfbd1
--- /dev/null
+++ b/runtimes/google/rt/util.go
@@ -0,0 +1,67 @@
+package rt
+
+import (
+	"io/ioutil"
+	"os"
+	"path"
+
+	"veyron/security/serialization"
+
+	"veyron2/security"
+	"veyron2/vom"
+)
+
+func encodeAndStore(obj interface{}, dir, dataFile, sigFile string, signer serialization.Signer) error {
+	// Save the object to temporary data and signature files, and then move
+	// those files to the actual data and signature file. This reduces the
+	// risk of loosing all saved data on disk in the event of a Write failure.
+	data, err := ioutil.TempFile(dir, "data")
+	if err != nil {
+		return err
+	}
+	defer os.Remove(data.Name())
+	sig, err := ioutil.TempFile(dir, "sig")
+	if err != nil {
+		return err
+	}
+	defer os.Remove(sig.Name())
+
+	swc, err := serialization.NewSigningWriteCloser(data, sig, signer, nil)
+	if err != nil {
+		return err
+	}
+	if err := vom.NewEncoder(swc).Encode(obj); err != nil {
+		swc.Close()
+		return err
+	}
+	if err := swc.Close(); err != nil {
+		return err
+	}
+
+	if err := os.Rename(data.Name(), path.Join(dir, dataFile)); err != nil {
+		return err
+	}
+	return os.Rename(sig.Name(), path.Join(dir, sigFile))
+}
+
+func decodeFromStorage(obj interface{}, dir, dataFile, sigFile string, publicKey security.PublicKey) error {
+	data, dataErr := os.Open(path.Join(dir, dataFile))
+	defer data.Close()
+	sig, sigErr := os.Open(path.Join(dir, sigFile))
+	defer sig.Close()
+
+	switch {
+	case os.IsNotExist(dataErr) && os.IsNotExist(sigErr):
+		return nil
+	case dataErr != nil:
+		return dataErr
+	case sigErr != nil:
+		return sigErr
+	}
+
+	vr, err := serialization.NewVerifyingReader(data, sig, publicKey)
+	if err != nil {
+		return err
+	}
+	return vom.NewDecoder(vr).Decode(obj)
+}