"veyron2/security": BlessingRoots and BlessingStore (part 2)

This CL hooks up BlessingRoots and BlessingStore into Principal.
It also adds additional methods to security.Context as defined
in the new security model.

Change-Id: I3aaf15fd1ded186c0fd57163f9b22806a68d65a3
diff --git a/runtimes/google/ipc/flow_test.go b/runtimes/google/ipc/flow_test.go
index ad24c2c..92a7ff3 100644
--- a/runtimes/google/ipc/flow_test.go
+++ b/runtimes/google/ipc/flow_test.go
@@ -32,20 +32,22 @@
 	errClose      error
 }
 
-func (f *testFlow) Read(b []byte) (int, error)         { return f.r.Read(b) }
-func (f *testFlow) Write(b []byte) (int, error)        { return f.w.Write(b) }
-func (f *testFlow) LocalAddr() net.Addr                { return nil }
-func (f *testFlow) RemoteAddr() net.Addr               { return nil }
-func (f *testFlow) LocalEndpoint() naming.Endpoint     { return nil }
-func (f *testFlow) RemoteEndpoint() naming.Endpoint    { return nil }
-func (f *testFlow) LocalID() security.PublicID         { return testID.PublicID() }
-func (f *testFlow) RemoteID() security.PublicID        { return testID.PublicID() }
-func (f *testFlow) SetReadDeadline(t time.Time) error  { return nil }
-func (f *testFlow) SetWriteDeadline(t time.Time) error { return nil }
-func (f *testFlow) SetDeadline(t time.Time) error      { return nil }
-func (f *testFlow) IsClosed() bool                     { return false }
-func (f *testFlow) Closed() <-chan struct{}            { return nil }
-func (f *testFlow) Cancel()                            {}
+func (f *testFlow) Read(b []byte) (int, error)          { return f.r.Read(b) }
+func (f *testFlow) Write(b []byte) (int, error)         { return f.w.Write(b) }
+func (f *testFlow) LocalAddr() net.Addr                 { return nil }
+func (f *testFlow) RemoteAddr() net.Addr                { return nil }
+func (f *testFlow) LocalEndpoint() naming.Endpoint      { return nil }
+func (f *testFlow) RemoteEndpoint() naming.Endpoint     { return nil }
+func (f *testFlow) LocalID() security.PublicID          { return testID.PublicID() }
+func (f *testFlow) RemoteID() security.PublicID         { return testID.PublicID() }
+func (f *testFlow) LocalPrincipal() security.Principal  { return nil }
+func (f *testFlow) RemoteBlessings() security.Blessings { return nil }
+func (f *testFlow) SetReadDeadline(t time.Time) error   { return nil }
+func (f *testFlow) SetWriteDeadline(t time.Time) error  { return nil }
+func (f *testFlow) SetDeadline(t time.Time) error       { return nil }
+func (f *testFlow) IsClosed() bool                      { return false }
+func (f *testFlow) Closed() <-chan struct{}             { return nil }
+func (f *testFlow) Cancel()                             {}
 
 func (f *testFlow) Close() error {
 	f.numCloseCalls++
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index d699ac7..a13910e 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -878,8 +878,10 @@
 func (fs *flowServer) Suffix() string        { return fs.suffix }
 func (fs *flowServer) Label() security.Label { return fs.label }
 
-func (fs *flowServer) LocalID() security.PublicID      { return fs.flow.LocalID() }
-func (fs *flowServer) RemoteID() security.PublicID     { return fs.authorizedRemoteID }
-func (fs *flowServer) Blessing() security.PublicID     { return fs.blessing }
-func (fs *flowServer) LocalEndpoint() naming.Endpoint  { return fs.flow.LocalEndpoint() }
-func (fs *flowServer) RemoteEndpoint() naming.Endpoint { return fs.flow.RemoteEndpoint() }
+func (fs *flowServer) LocalID() security.PublicID          { return fs.flow.LocalID() }
+func (fs *flowServer) RemoteID() security.PublicID         { return fs.authorizedRemoteID }
+func (fs *flowServer) LocalPrincipal() security.Principal  { return nil }
+func (fs *flowServer) RemoteBlessings() security.Blessings { return nil }
+func (fs *flowServer) Blessing() security.PublicID         { return fs.blessing }
+func (fs *flowServer) LocalEndpoint() naming.Endpoint      { return fs.flow.LocalEndpoint() }
+func (fs *flowServer) RemoteEndpoint() naming.Endpoint     { return fs.flow.RemoteEndpoint() }
diff --git a/runtimes/google/ipc/stream/vc/flow.go b/runtimes/google/ipc/stream/vc/flow.go
index 9b62c4c..254fed4 100644
--- a/runtimes/google/ipc/stream/vc/flow.go
+++ b/runtimes/google/ipc/stream/vc/flow.go
@@ -20,8 +20,10 @@
 	RemoteID() security.PublicID
 }
 
-func (f *flow) LocalEndpoint() naming.Endpoint  { return f.localEndpoint }
-func (f *flow) RemoteEndpoint() naming.Endpoint { return f.remoteEndpoint }
+func (f *flow) LocalPrincipal() security.Principal { return nil }
+func (f *flow) RemoteBlesings() security.Blessings { return nil }
+func (f *flow) LocalEndpoint() naming.Endpoint     { return f.localEndpoint }
+func (f *flow) RemoteEndpoint() naming.Endpoint    { return f.remoteEndpoint }
 
 // implement net.Conn
 func (f *flow) LocalAddr() net.Addr  { return f.localEndpoint }
diff --git a/runtimes/google/ipc/stream/vc/listener_test.go b/runtimes/google/ipc/stream/vc/listener_test.go
index 73020e0..c680027 100644
--- a/runtimes/google/ipc/stream/vc/listener_test.go
+++ b/runtimes/google/ipc/stream/vc/listener_test.go
@@ -42,6 +42,9 @@
 func (*noopFlow) LocalID() security.PublicID  { return testID.PublicID() }
 func (*noopFlow) RemoteID() security.PublicID { return testID.PublicID() }
 
+func (*noopFlow) LocalPrincipal() security.Principal  { return nil }
+func (*noopFlow) RemoteBlessings() security.Blessings { return nil }
+
 func TestListener(t *testing.T) {
 	ln := newListener()
 	f1, f2 := &noopFlow{}, &noopFlow{}
diff --git a/runtimes/google/rt/blessingroots_test.go b/runtimes/google/rt/blessingroots_test.go
index 628dc73..2ce703c 100644
--- a/runtimes/google/rt/blessingroots_test.go
+++ b/runtimes/google/rt/blessingroots_test.go
@@ -7,7 +7,6 @@
 	"fmt"
 	"io/ioutil"
 	"os"
-	"strings"
 	"testing"
 
 	"veyron.io/veyron/veyron2/security"
@@ -15,11 +14,11 @@
 
 type s []string
 
-type tester struct {
+type rootsTester struct {
 	k1, k2, k3 security.PublicKey
 }
 
-func (t *tester) testAdd(br security.BlessingRoots) error {
+func (t *rootsTester) testAdd(br security.BlessingRoots) error {
 	testdata := []struct {
 		root    security.PublicKey
 		pattern security.BlessingPattern
@@ -36,7 +35,7 @@
 	return nil
 }
 
-func (t *tester) testRecognized(br security.BlessingRoots) error {
+func (t *rootsTester) testRecognized(br security.BlessingRoots) error {
 	testdata := []struct {
 		root          security.PublicKey
 		recognized    []string
@@ -69,27 +68,17 @@
 	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 {
+	rootsTester := rootsTester{mkKey(), mkKey(), mkKey()}
+	if err := rootsTester.testAdd(br); err != nil {
 		t.Error(err)
 	}
-	if err := tester.testRecognized(br); err != nil {
+	if err := rootsTester.testRecognized(br); err != nil {
 		t.Error(err)
 	}
 }
+
 func TestPersistingBlessingRoots(t *testing.T) {
 	newTempDir := func(name string) string {
 		dir, err := ioutil.TempDir("", name)
@@ -99,22 +88,22 @@
 		return dir
 	}
 
-	tester := tester{mkKey(), mkKey(), mkKey()}
+	rootsTester := rootsTester{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")
+	signer := newPrincipal(t)
 	br, err := NewPersistingBlessingRoots(dir, signer)
 	if err != nil {
 		t.Fatalf("NewPersistingBlessingRoots failed: %s", err)
 	}
 
-	if err := tester.testAdd(br); err != nil {
+	if err := rootsTester.testAdd(br); err != nil {
 		t.Error(err)
 	}
-	if err := tester.testRecognized(br); err != nil {
+	if err := rootsTester.testRecognized(br); err != nil {
 		t.Error(err)
 	}
 
@@ -124,11 +113,7 @@
 	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 {
+	if err := rootsTester.testRecognized(br); err != nil {
 		t.Error(err)
 	}
 }
diff --git a/runtimes/google/rt/blessingstore.go b/runtimes/google/rt/blessingstore.go
index a5c675c..d095530 100644
--- a/runtimes/google/rt/blessingstore.go
+++ b/runtimes/google/rt/blessingstore.go
@@ -6,7 +6,6 @@
 	"reflect"
 	"sync"
 
-	isecurity "veyron.io/veyron/veyron/runtimes/google/security"
 	"veyron.io/veyron/veyron/security/serialization"
 
 	"veyron.io/veyron/veyron2/security"
@@ -21,7 +20,7 @@
 var errStoreAddMismatch = errors.New("blessing's public key does not match store's public key")
 
 type markedBlessings struct {
-	Blessings security.PublicID
+	Blessings security.Blessings
 	Patterns  []security.BlessingPattern
 }
 
@@ -33,7 +32,7 @@
 	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
+	Default security.Blessings
 }
 
 // blessingStore implements security.BlessingStore.
@@ -45,7 +44,7 @@
 	mu        sync.RWMutex
 }
 
-func (s *blessingStore) Add(blessings security.PublicID, forPeers security.BlessingPattern) error {
+func (s *blessingStore) Add(blessings security.Blessings, forPeers security.BlessingPattern) error {
 	if !reflect.DeepEqual(blessings.PublicKey(), s.publicKey) {
 		return errStoreAddMismatch
 	}
@@ -86,11 +85,11 @@
 	return nil
 }
 
-func (s *blessingStore) ForPeer(peerBlessings ...string) security.PublicID {
+func (s *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
 	s.mu.RLock()
 	defer s.mu.RUnlock()
 
-	var matchingBlessings []security.PublicID
+	var matchingBlessings []security.Blessings
 	for _, mb := range s.state.Store {
 		for _, p := range mb.Patterns {
 			if p.MatchedBy(peerBlessings...) {
@@ -100,16 +99,16 @@
 		}
 	}
 
-	blessings, err := isecurity.NewSetPublicID(matchingBlessings...)
+	blessings, err := security.UnionOfBlessings(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)
+		vlog.Errorf("BlessingStore: %s is broken, could union Blessings obtained from it: %s", s, err)
 		return nil
 	}
 	return blessings
 }
 
-func (s *blessingStore) Default() security.PublicID {
+func (s *blessingStore) Default() security.Blessings {
 	s.mu.RLock()
 	defer s.mu.RUnlock()
 	if s.state.Default != nil {
@@ -118,7 +117,7 @@
 	return s.ForPeer()
 }
 
-func (s *blessingStore) SetDefault(blessings security.PublicID) error {
+func (s *blessingStore) SetDefault(blessings security.Blessings) error {
 	s.mu.Lock()
 	defer s.mu.Unlock()
 	if !reflect.DeepEqual(blessings.PublicKey(), s.publicKey) {
diff --git a/runtimes/google/rt/blessingstore_test.go b/runtimes/google/rt/blessingstore_test.go
index f071017..6699f58 100644
--- a/runtimes/google/rt/blessingstore_test.go
+++ b/runtimes/google/rt/blessingstore_test.go
@@ -2,233 +2,126 @@
 
 import (
 	"bytes"
+	"fmt"
 	"io/ioutil"
 	"os"
 	"reflect"
-	"sort"
-	"strings"
 	"testing"
-	"time"
 
-	isecurity "veyron.io/veyron/veyron/runtimes/google/security"
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/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
+type storeTester struct {
+	t                                         *testing.T
+	bForAll, bForGoogle, bForVeyron, bDefault security.Blessings
 }
 
-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
-	}
+func (t *storeTester) testAdd(s security.BlessingStore) error {
 	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()
+		p      = newPrincipal(t.t)
+		bOther = blessSelf(t.t, p, "irrelevant")
 	)
-
-	s := NewInMemoryBlessingStore(pkey)
-
-	testDataForAdd := []struct {
-		blessings []security.PublicID
-		patterns  []security.BlessingPattern
+	testdata := []struct {
+		blessings security.Blessings
+		pattern   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 BlessingPattern",
-		},
+		{t.bForAll, "...", ""},
+		{t.bForGoogle, "google/...", ""},
+		{t.bForVeyron, "veyron", ""},
+		{bOther, "...", "public key does not match"},
+		{t.bForAll, "", "invalid BlessingPattern"},
+		{t.bForAll, "foo...", "invalid BlessingPattern"},
+		{t.bForAll, "...foo", "invalid BlessingPattern"},
+		{t.bForAll, "foo/.../bar", "invalid BlessingPattern"},
 	}
-	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)
-				}
-			}
+	for _, d := range testdata {
+		if err := matchesError(s.Add(d.blessings, d.pattern), d.wantErr); err != nil {
+			return fmt.Errorf("Add(%v, %q): %v", d.blessings, p, err)
 		}
 	}
-	testDataForSetDefault := []struct {
-		blessings []security.PublicID
+	return nil
+}
+
+func (t *storeTester) testSetDefault(s security.BlessingStore, currentDefault security.Blessings) error {
+	if got := s.Default(); !reflect.DeepEqual(got, currentDefault) {
+		return fmt.Errorf("Default(): got: %v, want: %v", got, currentDefault)
+	}
+	testdata := []struct {
+		blessings security.Blessings
 		wantErr   string
 	}{
-		{
-			blessings: []security.PublicID{cAlicePub, cVeyronAlice, sAlice},
-		},
-		{
-			blessings: []security.PublicID{cBobPub},
-			wantErr:   "public key does not match",
-		},
+		{t.bDefault, ""},
+		{blessSelf(t.t, newPrincipal(t.t), "irrelevant"), "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)
-			}
+	for _, d := range testdata {
+		if err := matchesError(s.SetDefault(d.blessings), d.wantErr); err != nil {
+			return fmt.Errorf("SetDefault(%v): %v", d.blessings, err)
+		}
+		if got, want := s.Default(), t.bDefault; !reflect.DeepEqual(got, want) {
+			return fmt.Errorf("Default(): got: %v, want: %v", got, want)
 		}
 	}
+	return nil
 }
 
-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
+func (t *storeTester) testForPeer(s security.BlessingStore) error {
+	testdata := []struct {
+		peers     []string
+		blessings security.Blessings
 	}{
-		{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"}},
+		{nil, t.bForAll},
+		{[]string{"foo"}, t.bForAll},
+		{[]string{"google"}, unionOfBlessings(t.t, t.bForAll, t.bForGoogle)},
+		{[]string{"veyron"}, unionOfBlessings(t.t, t.bForAll, t.bForVeyron)},
+		{[]string{"google/foo"}, unionOfBlessings(t.t, t.bForAll, t.bForGoogle)},
+		{[]string{"veyron/baz"}, t.bForAll},
+		{[]string{"google/foo/bar"}, unionOfBlessings(t.t, t.bForAll, t.bForGoogle)},
+		{[]string{"veyron/foo", "google"}, unionOfBlessings(t.t, t.bForAll, t.bForGoogle)},
+		{[]string{"veyron", "google"}, unionOfBlessings(t.t, t.bForAll, t.bForGoogle, t.bForVeyron)},
 	}
-	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)
+	for _, d := range testdata {
+		if got, want := s.ForPeer(d.peers...), d.blessings; !reflect.DeepEqual(got, want) {
+			return fmt.Errorf("ForPeer(%v): got: %v, want: %v", d.peers, got, want)
 		}
 	}
-
-	// 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)
-	}
+	return nil
 }
 
-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)
-		}
-	}
+func newStoreTester(t *testing.T) (*storeTester, security.PublicKey) {
 	var (
-		// test principals
-		cAlice       = newChain("alice")
-		cVeyronAlice = bless(cAlice.PublicID(), cVeyron, "alice", nil)
+		// root principals
+		v      = newPrincipal(t)
+		g      = newPrincipal(t)
+		veyron = blessSelf(t, v, "veyron")
+		google = blessSelf(t, g, "google")
 
-		pkey = cAlice.PublicID().PublicKey()
+		// test principal
+		p    = newPrincipal(t)
+		pkey = p.PublicKey()
 	)
+	s := &storeTester{
+		t:          t,
+		bForAll:    bless(t, v, pkey, veyron, "alice"),
+		bForGoogle: bless(t, g, pkey, google, "alice"),
+		bDefault:   bless(t, g, pkey, google, "aliceDefault"),
+	}
+	s.bForVeyron = unionOfBlessings(t, s.bForAll, s.bForGoogle)
+	return s, pkey
+}
 
-	// Create a new BlessingStore add the blessings cVeyronAlice to it twice.
+func TestInMemoryBlessingStore(t *testing.T) {
+	tester, pkey := newStoreTester(t)
 	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)
+	if err := tester.testAdd(s); err != nil {
+		t.Error(err)
+	}
+	if err := tester.testForPeer(s); err != nil {
+		t.Error(err)
+	}
+	if err := tester.testSetDefault(s, tester.bForAll); err != nil {
+		t.Error(err)
 	}
 }
 
@@ -241,72 +134,70 @@
 		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()
-	)
+	tester, pkey := newStoreTester(t)
 
 	// Create a new persisting BlessingStore.
 	dir := newTempDir("blessingstore")
 	defer os.RemoveAll(dir)
-
+	signer := newPrincipal(t)
 	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)
+		t.Fatalf("NewPersistingBlessingStore failed: %v", err)
 	}
 
+	if err := tester.testAdd(s); err != nil {
+		t.Error(err)
+	}
+	if err := tester.testForPeer(s); err != nil {
+		t.Error(err)
+	}
+	if err := tester.testSetDefault(s, tester.bForAll); err != nil {
+		t.Error(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)
+		t.Fatalf("NewPersistingBlessingStore failed: %v", err)
 	}
-
-	if got, want := s.PublicKey(), pkey; !reflect.DeepEqual(got, want) {
-		t.Errorf("%v.PublicKey(): got: %v, want: %v", s, got, want)
+	if err := tester.testForPeer(s); err != nil {
+		t.Error(err)
 	}
-
-	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)
+	if got, want := s.Default(), tester.bDefault; !reflect.DeepEqual(got, want) {
+		t.Fatalf("Default(): got: %v, want: %v", got, want)
 	}
 }
 
-func init() {
-	isecurity.TrustIdentityProviders(cVeyron)
-	isecurity.TrustIdentityProviders(cGoogle)
+func TestBlessingStoreDuplicates(t *testing.T) {
+	roundTrip := func(blessings security.Blessings) security.Blessings {
+		var b bytes.Buffer
+		if err := vom.NewEncoder(&b).Encode(blessings); err != nil {
+			t.Fatalf("could not VOM-Encode Blessings: %v", err)
+		}
+		var decodedBlessings security.Blessings
+		if err := vom.NewDecoder(&b).Decode(&decodedBlessings); err != nil {
+			t.Fatalf("could not VOM-Decode Blessings: %v", err)
+		}
+		return decodedBlessings
+	}
+	add := func(s security.BlessingStore, blessings security.Blessings, forPeers security.BlessingPattern) {
+		if err := s.Add(blessings, forPeers); err != nil {
+			t.Fatalf("Add(%v, %q) failed unexpectedly: %v", blessings, forPeers, err)
+		}
+	}
+	var (
+		// root principal
+		// test blessings
+		p     = newPrincipal(t)
+		alice = blessSelf(t, p, "alice")
+
+		pkey = p.PublicKey()
+	)
+	s := NewInMemoryBlessingStore(pkey)
+	add(s, alice, "...")
+	add(s, roundTrip(alice), "...")
+
+	if got, want := s.ForPeer(), alice; !reflect.DeepEqual(got, want) {
+		t.Fatalf("ForPeer(): got: %v, want: %v", got, want)
+	}
 }
diff --git a/runtimes/google/rt/util_test.go b/runtimes/google/rt/util_test.go
new file mode 100644
index 0000000..7974fbe
--- /dev/null
+++ b/runtimes/google/rt/util_test.go
@@ -0,0 +1,62 @@
+package rt
+
+import (
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"fmt"
+	"strings"
+	"testing"
+
+	"veyron.io/veyron/veyron2/security"
+)
+
+func matchesError(got error, want string) error {
+	if (got == nil) && len(want) == 0 {
+		return nil
+	}
+	if got == nil {
+		return fmt.Errorf("Got nil error, wanted to match %q", want)
+	}
+	if !strings.Contains(got.Error(), want) {
+		return fmt.Errorf("Got error %q, wanted to match %q", got, want)
+	}
+	return nil
+}
+
+func newPrincipal(t *testing.T) security.Principal {
+	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		t.Fatalf("Failed to create private key for principal: %v", err)
+	}
+	signer := security.NewInMemoryECDSASigner(key)
+	p, err := security.CreatePrincipal(signer, NewInMemoryBlessingStore(signer.PublicKey()), NewInMemoryBlessingRoots())
+	if err != nil {
+		t.Fatalf("security.CreatePrincipal failed: %v", err)
+	}
+	return p
+}
+
+func blessSelf(t *testing.T, p security.Principal, name string) security.Blessings {
+	b, err := p.BlessSelf(name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	return b
+}
+
+func bless(t *testing.T, p security.Principal, key security.PublicKey, with security.Blessings, extension string) security.Blessings {
+	b, err := p.Bless(key, with, extension, security.UnconstrainedUse())
+	if err != nil {
+		t.Fatal(err)
+	}
+	return b
+}
+
+func unionOfBlessings(t *testing.T, blessings ...security.Blessings) security.Blessings {
+	b, err := security.UnionOfBlessings(blessings...)
+	if err != nil {
+		t.Fatal(err)
+	}
+	return b
+}
diff --git a/runtimes/google/security/identity_chain.go b/runtimes/google/security/identity_chain.go
index 2855a36..e582278 100644
--- a/runtimes/google/security/identity_chain.go
+++ b/runtimes/google/security/identity_chain.go
@@ -232,15 +232,7 @@
 
 func (id *chainPrivateID) MintDischarge(cav security.ThirdPartyCaveat, ctx security.Context, duration time.Duration, dischargeCaveats []security.Caveat) (security.Discharge, error) {
 	// TODO(ashankar): HACK using new API to fit into old. This will go away anyway when we get rid of PrivateID and PublicID before release.
-	principal, err := security.CreatePrincipal(id.signer)
-	if err != nil {
-		return nil, err
-	}
-	expiry, err := security.ExpiryCaveat(time.Now().Add(duration))
-	if err != nil {
-		return nil, err
-	}
-	return principal.MintDischarge(cav, ctx, expiry, dischargeCaveats...)
+	return security.MintDischargeForPrivateID(id.signer, cav, ctx, duration, dischargeCaveats)
 }
 
 func (id *chainPrivateID) Sign(message []byte) (security.Signature, error) {
diff --git a/runtimes/google/security/util.go b/runtimes/google/security/util.go
index 2d51108..812a1ba 100644
--- a/runtimes/google/security/util.go
+++ b/runtimes/google/security/util.go
@@ -29,6 +29,10 @@
 
 // ContextArgs holds the arguments for creating a new security.Context for an IPC.
 type ContextArgs struct {
+	// LocalPrincipal is the principal at the local end of a request.
+	LocalPrincipal security.Principal
+	// RemoteBlessings is the blessings held by the remote end of a request.
+	RemoteBlessings security.Blessings
 	// LocalID, RemoteID are the identities at the local and remote ends of a request
 	// respectively.
 	LocalID, RemoteID security.PublicID
@@ -99,6 +103,8 @@
 func (c *context) Discharges() map[string]security.Discharge { return c.ContextArgs.Discharges }
 func (c *context) LocalID() security.PublicID                { return c.ContextArgs.LocalID }
 func (c *context) RemoteID() security.PublicID               { return c.ContextArgs.RemoteID }
+func (c *context) LocalPrincipal() security.Principal        { return c.ContextArgs.LocalPrincipal }
+func (c *context) RemoteBlessings() security.Blessings       { return c.ContextArgs.RemoteBlessings }
 func (c *context) LocalEndpoint() naming.Endpoint            { return c.ContextArgs.LocalEndpoint }
 func (c *context) RemoteEndpoint() naming.Endpoint           { return c.ContextArgs.RemoteEndpoint }
 
diff --git a/security/acl_authorizer_test.go b/security/acl_authorizer_test.go
index e286d8b..3d7fbfe 100644
--- a/security/acl_authorizer_test.go
+++ b/security/acl_authorizer_test.go
@@ -28,6 +28,8 @@
 func (c *context) Discharges() map[string]security.Discharge { return c.discharges }
 func (c *context) LocalID() security.PublicID                { return c.localID }
 func (c *context) RemoteID() security.PublicID               { return c.remoteID }
+func (c *context) LocalPrincipal() security.Principal        { return nil }
+func (c *context) RemoteBlessings() security.Blessings       { return nil }
 func (c *context) LocalEndpoint() naming.Endpoint            { return nil }
 func (c *context) RemoteEndpoint() naming.Endpoint           { return nil }
 
diff --git a/security/audit/id_test.go b/security/audit/id_test.go
index 0af44df..d3e9bf9 100644
--- a/security/audit/id_test.go
+++ b/security/audit/id_test.go
@@ -256,6 +256,8 @@
 func (context) Discharges() map[string]security.Discharge { return nil }
 func (context) LocalID() security.PublicID                { return nil }
 func (context) RemoteID() security.PublicID               { return nil }
+func (context) LocalPrincipal() security.Principal        { return nil }
+func (context) RemoteBlessings() security.Blessings       { return nil }
 func (context) LocalEndpoint() naming.Endpoint            { return nil }
 func (context) RemoteEndpoint() naming.Endpoint           { return nil }