Merge "veyron/runtimes/google/security: Preparation for moving identity implementation to the public API and to VDL."
diff --git a/runtimes/google/security/identity_chain.go b/runtimes/google/security/identity_chain.go
index 0c03280..a15d1de 100644
--- a/runtimes/google/security/identity_chain.go
+++ b/runtimes/google/security/identity_chain.go
@@ -129,15 +129,16 @@
 func (id *chainPrivateID) String() string { return fmt.Sprintf("PrivateID:%v", id.publicID) }
 
 func (id *chainPrivateID) VomEncode() (*wire.ChainPrivateID, error) {
-	var err error
-	w := &wire.ChainPrivateID{Secret: id.privateKey.D.Bytes()}
-	w.PublicID, err = id.publicID.VomEncode()
-	return w, err
+	pub, err := id.publicID.VomEncode()
+	if err != nil {
+		return nil, err
+	}
+	return &wire.ChainPrivateID{Secret: id.privateKey.D.Bytes(), PublicID: *pub}, nil
 }
 
 func (id *chainPrivateID) VomDecode(w *wire.ChainPrivateID) error {
 	id.publicID = new(chainPublicID)
-	if err := id.publicID.VomDecode(w.PublicID); err != nil {
+	if err := id.publicID.VomDecode(&w.PublicID); err != nil {
 		return err
 	}
 	id.privateKey = &ecdsa.PrivateKey{
@@ -184,21 +185,28 @@
 	}, nil
 }
 
-// Derive returns a new PrivateID that contains the PrivateID's private key and the
-// provided PublicID. The provided PublicID must have the same public key as the public
-// key of the PrivateID's PublicID.
 func (id *chainPrivateID) Derive(pub security.PublicID) (security.PrivateID, error) {
 	if !reflect.DeepEqual(pub.PublicKey(), id.publicID.publicKey) {
 		return nil, errDeriveMismatch
 	}
-	chainPub, ok := pub.(*chainPublicID)
-	if !ok {
-		return nil, fmt.Errorf("PrivateID of type %T cannot be obtained from PublicID of type %T", id, pub)
+	switch p := pub.(type) {
+	case *chainPublicID:
+		return &chainPrivateID{
+			publicID:   p,
+			privateKey: id.privateKey,
+		}, nil
+	case *setPublicID:
+		privs := make([]security.PrivateID, len(*p))
+		var err error
+		for ix, ip := range *p {
+			if privs[ix], err = id.Derive(ip); err != nil {
+				return nil, fmt.Errorf("Derive failed for public id %d of %d in set: %v", ix, len(*p), err)
+			}
+		}
+		return setPrivateID(privs), nil
+	default:
+		return nil, fmt.Errorf("PrivateID of type %T cannot be used to Derive from PublicID of type %T", id, pub)
 	}
-	return &chainPrivateID{
-		publicID:   chainPub,
-		privateKey: id.privateKey,
-	}, nil
 }
 
 func (id *chainPrivateID) MintDischarge(cav security.ThirdPartyCaveat, duration time.Duration, dischargeCaveats []security.ServiceCaveat) (security.ThirdPartyDischarge, error) {
diff --git a/runtimes/google/security/identity_set.go b/runtimes/google/security/identity_set.go
new file mode 100644
index 0000000..05dd296
--- /dev/null
+++ b/runtimes/google/security/identity_set.go
@@ -0,0 +1,227 @@
+package security
+
+import (
+	"crypto/ecdsa"
+	"errors"
+	"fmt"
+	"reflect"
+	"strings"
+	"time"
+
+	"veyron2/security"
+	"veyron2/vom"
+)
+
+type setPublicID []security.PublicID
+
+var (
+	errEmptySet         = errors.New("suspected manipulation of identity: empty set")
+	errSingleElementSet = errors.New("suspected manipulation of identity: single element set")
+	errNoNilsInSet      = errors.New("suspected manipulation of identity: nil element in set")
+	errMismatchedKeys   = errors.New("mismatched keys in elements of set")
+)
+
+// NewSetPublicID returns a security.PublicID containing the combined credentials of ids.
+// It requires that all elements of ids have the same public key.
+func NewSetPublicID(ids ...security.PublicID) (security.PublicID, error) {
+	// All public keys must match
+	switch len(ids) {
+	case 0:
+		return nil, nil
+	case 1:
+		return ids[0], nil
+	default:
+		for i := 1; i < len(ids); i++ {
+			if !reflect.DeepEqual(ids[0].PublicKey(), ids[i].PublicKey()) {
+				return nil, errMismatchedKeys
+			}
+		}
+		set := setPublicID(ids)
+		return &set, nil
+	}
+}
+
+func (s *setPublicID) Names() []string {
+	names := make([]string, 0, len(*s))
+	for _, id := range *s {
+		names = append(names, id.Names()...)
+	}
+	if len(names) == 0 {
+		return nil
+	}
+	return names
+}
+
+func (s *setPublicID) Match(pattern security.PrincipalPattern) bool {
+	for _, id := range *s {
+		if id.Match(pattern) {
+			return true
+		}
+	}
+	return false
+}
+
+func (s *setPublicID) PublicKey() *ecdsa.PublicKey {
+	return (*s)[0].PublicKey()
+}
+
+func (s *setPublicID) Authorize(context security.Context) (security.PublicID, error) {
+	var authids []security.PublicID
+	var errs []error
+	for _, id := range *s {
+		if aid, err := id.Authorize(context); err != nil && len(authids) == 0 {
+			errs = append(errs, err)
+		} else if aid != nil {
+			authids = append(authids, aid)
+		}
+	}
+	if len(authids) == 0 {
+		return nil, joinerrs(errs)
+	}
+	return NewSetPublicID(authids...)
+}
+
+func (s *setPublicID) ThirdPartyCaveats() []security.ServiceCaveat {
+	set := make(map[security.ThirdPartyCaveatID]security.ServiceCaveat)
+	for _, id := range *s {
+		for _, c := range id.ThirdPartyCaveats() {
+			if tp, ok := c.Caveat.(security.ThirdPartyCaveat); ok {
+				set[tp.ID()] = c
+			}
+			// else { This should not be possible! }
+		}
+	}
+	if len(set) == 0 {
+		return nil
+	}
+	ret := make([]security.ServiceCaveat, 0, len(set))
+	for _, c := range set {
+		ret = append(ret, c)
+	}
+	return ret
+}
+
+func (s *setPublicID) String() string {
+	strs := make([]string, len(*s))
+	for ix, id := range *s {
+		strs[ix] = fmt.Sprintf("%v", id)
+	}
+	return strings.Join(strs, "#")
+}
+
+func (s *setPublicID) VomEncode() ([]security.PublicID, error) {
+	return []security.PublicID(*s), nil
+}
+
+func (s *setPublicID) VomDecode(ids []security.PublicID) error {
+	switch len(ids) {
+	case 0:
+		return errEmptySet
+	case 1:
+		return errSingleElementSet
+	}
+	if ids[0] == nil {
+		return errNoNilsInSet
+	}
+	for i := 1; i < len(ids); i++ {
+		if ids[i] == nil {
+			return errNoNilsInSet
+		}
+		if !reflect.DeepEqual(ids[0].PublicKey(), ids[i].PublicKey()) {
+			return errMismatchedKeys
+		}
+	}
+	*s = setPublicID(ids)
+	return nil
+}
+
+type setPrivateID []security.PrivateID
+
+// NewSetPrivateID returns a security.PrivateID contiaining the combined credentials of ids.
+// It requires that all ids have the same private key.
+func NewSetPrivateID(ids ...security.PrivateID) (security.PrivateID, error) {
+	switch len(ids) {
+	case 0:
+		return nil, nil
+	case 1:
+		return ids[0], nil
+	default:
+		for i := 1; i < len(ids); i++ {
+			if !reflect.DeepEqual(ids[0].PrivateKey(), ids[i].PrivateKey()) {
+				return nil, errMismatchedKeys
+			}
+		}
+		return setPrivateID(ids), nil
+	}
+}
+
+func (s setPrivateID) PublicID() security.PublicID {
+	pubs := make([]security.PublicID, len(s))
+	for ix, id := range s {
+		pubs[ix] = id.PublicID()
+	}
+	set := setPublicID(pubs)
+	return &set
+}
+
+func (s setPrivateID) PrivateKey() *ecdsa.PrivateKey { return s[0].PrivateKey() }
+
+func (s setPrivateID) Bless(blessee security.PublicID, blessingName string, duration time.Duration, caveats []security.ServiceCaveat) (security.PublicID, error) {
+	pubs := make([]security.PublicID, len(s))
+	for ix, id := range s {
+		var err error
+		if pubs[ix], err = id.Bless(blessee, blessingName, duration, caveats); err != nil {
+			return nil, err
+		}
+	}
+	return NewSetPublicID(pubs...)
+}
+
+func (s setPrivateID) Derive(pub security.PublicID) (security.PrivateID, error) {
+	if !reflect.DeepEqual(pub.PublicKey(), &s.PrivateKey().PublicKey) {
+		return nil, errDeriveMismatch
+	}
+	var err error
+	switch p := pub.(type) {
+	case *chainPublicID:
+		return s[0].Derive(p)
+	case *setPublicID:
+		privs := make([]security.PrivateID, len(*p))
+		for ix, ip := range *p {
+			if privs[ix], err = s.Derive(ip); err != nil {
+				return nil, fmt.Errorf("Derive failed for %d of %d id in set", ix, len(*p))
+			}
+		}
+		return setPrivateID(privs), nil
+	default:
+		return nil, fmt.Errorf("PrivateID of type %T cannot be used to Derive from PublicID of type %T", s, pub)
+	}
+}
+
+func (s setPrivateID) MintDischarge(cav security.ThirdPartyCaveat, duration time.Duration, dischargeCaveats []security.ServiceCaveat) (security.ThirdPartyDischarge, error) {
+	for _, id := range s {
+		if d, err := id.MintDischarge(cav, duration, dischargeCaveats); err == nil {
+			return d, nil
+		}
+	}
+	return nil, fmt.Errorf("discharge cannot be constructed for %T from %T", cav, s)
+}
+
+func joinerrs(errs []error) error {
+	switch len(errs) {
+	case 0:
+		return nil
+	case 1:
+		return errs[0]
+	}
+	strs := make([]string, len(errs))
+	for i, err := range errs {
+		strs[i] = err.Error()
+	}
+	return fmt.Errorf("none of the blessings in the set are authorized: %v", strings.Join(strs, ", "))
+}
+
+func init() {
+	vom.Register(setPrivateID(nil))
+	vom.Register(setPublicID(nil))
+}
diff --git a/runtimes/google/security/identity_test.go b/runtimes/google/security/identity_test.go
index a5d7c7b..0f2200f 100644
--- a/runtimes/google/security/identity_test.go
+++ b/runtimes/google/security/identity_test.go
@@ -1,13 +1,17 @@
 package security
 
 import (
+	"bytes"
+	"fmt"
 	"reflect"
+	"sort"
 	"testing"
 	"time"
 
 	"veyron/runtimes/google/security/caveat"
 	"veyron/runtimes/google/security/wire"
 	"veyron2/security"
+	"veyron2/vom"
 )
 
 type S []string
@@ -17,28 +21,25 @@
 		cUnknownAlice    = newChain("alice").PublicID()
 		cTrustedAlice    = bless(cUnknownAlice, veyronChain, "alice", nil)
 		cMistrustedAlice = bless(cUnknownAlice, newChain("veyron"), "alice", nil)
+		cGoogleAlice     = bless(cUnknownAlice, googleChain, "alice", nil)
 
-		tUntrustedAlice  = newTree("alice").PublicID()
-		tTrustedAlice    = bless(tUntrustedAlice, veyronTree, "alice", nil)
-		tMistrustedAlice = bless(tUntrustedAlice, newTree("veyron"), "alice", nil)
+		sAlice       = newSetPublicID(cTrustedAlice, cGoogleAlice)
+		sBadAlice    = newSetPublicID(cUnknownAlice, cMistrustedAlice)
+		sGoogleAlice = newSetPublicID(cMistrustedAlice, cGoogleAlice)
 	)
 	testdata := []struct {
-		id        security.PublicID
-		names     []string
-		authErr   string
-		authNames []string
+		id    security.PublicID
+		names []string
+		err   string
 	}{
 		{id: cUnknownAlice},
-		{id: cTrustedAlice, names: S{"veyron/alice"}, authNames: S{"veyron/alice"}},
-		{id: cMistrustedAlice, authErr: "Mistrusted"},
-		{id: tUntrustedAlice},
-		{id: tTrustedAlice, names: S{"veyron/alice"}, authNames: S{"veyron/alice"}},
-		{id: tMistrustedAlice},
+		{id: cTrustedAlice, names: S{"veyron/alice"}},
+		{id: cMistrustedAlice, err: "Mistrusted"},
+		{id: sAlice, names: S{"veyron/alice", "google/alice"}},
+		{id: sBadAlice},
+		{id: sGoogleAlice, names: S{"google/alice"}},
 	}
 	for _, d := range testdata {
-		if len(d.authNames) != 0 && len(d.authErr) != 0 {
-			t.Fatalf("Bad testdata. At most one of authNames and authErr must be non-empty: %q", d)
-		}
 		if got, want := d.id.Names(), d.names; !reflect.DeepEqual(got, want) {
 			t.Errorf("%q(%T).Names(): got: %q, want: %q", d.id, d.id, got, want)
 		}
@@ -47,16 +48,17 @@
 			t.Errorf("%q.Authorize returned: (%v, %v), exactly one return value must be nil", d.id, authID, err)
 			continue
 		}
-		if !matchesErrorPattern(err, d.authErr) {
-			t.Errorf("%q.Authorize returned error: %v, want to match: %q", d.id, err, d.authErr)
+		if !matchesErrorPattern(err, d.err) {
+			t.Errorf("%q.Authorize returned error: %v, want to match: %q", d.id, err, d.err)
 		}
-		if err := verifyAuthorizedID(d.id, authID, d.authNames); err != nil {
+		if err := verifyAuthorizedID(d.id, authID, d.names); err != nil {
 			t.Error(err)
 		}
 	}
 }
 
 func TestMatch(t *testing.T) {
+	alice := newChain("alice")
 	type matchInstance struct {
 		pattern security.PrincipalPattern
 		want    bool
@@ -67,17 +69,7 @@
 	}{
 		{
 			// self-signed alice chain, not a trusted identity provider so should only match "*"
-			id: newChain("alice").PublicID(),
-			matchData: []matchInstance{
-				{pattern: "*", want: true},
-				{pattern: "alice", want: false},
-				{pattern: "alice/*", want: false},
-				{pattern: "untrusted/alice/*", want: false},
-			},
-		},
-		{
-			// self-blessed alice tree, not a trusted identity provider so should only match "*"
-			id: newTree("alice").PublicID(),
+			id: alice.PublicID(),
 			matchData: []matchInstance{
 				{pattern: "*", want: true},
 				{pattern: "alice", want: false},
@@ -102,11 +94,10 @@
 		},
 		{
 			// alice#veyron/alice#google/alice: two trusted identity providers
-			id: bless(bless(newTree("alice").PublicID(), veyronTree, "alice", nil), googleTree, "alice", nil),
+			id: newSetPublicID(alice.PublicID(), bless(alice.PublicID(), veyronChain, "alice", nil), bless(alice.PublicID(), googleChain, "alice", nil)),
 			matchData: []matchInstance{
 				{pattern: "*", want: true},
-				// Since alice is not a trusted identity
-				// provider, the tree's self-blessed identity
+				// Since alice is not a trusted identity provider, the self-blessed identity
 				// should not match "alice/*"
 				{pattern: "alice", want: false},
 				{pattern: "alice/*", want: false},
@@ -135,26 +126,34 @@
 	}
 }
 
-func TestExpiredIdentity(t *testing.T) {
-	testdata := []struct {
-		blessor security.PrivateID
-		blessee security.PublicID
-	}{
-		{veyronChain, newChain("alice").PublicID()},
-		{veyronTree, newTree("alice").PublicID()},
+func TestExpiredIdentityChain(t *testing.T) {
+	id, err := veyronChain.Bless(newChain("immaterial").PublicID(), "alice", time.Millisecond, nil)
+	if err != nil {
+		t.Fatal(err)
 	}
-	for _, d := range testdata {
-		id, err := d.blessor.Bless(d.blessee, "alice", time.Millisecond, nil)
-		if err != nil {
-			t.Errorf("%q.Bless(%q, ...) failed: %v", d.blessor, d.blessee, err)
-			continue
-		}
-		time.Sleep(time.Millisecond)
-		if authID, _ := id.Authorize(NewContext(ContextArgs{})); authID != nil {
-			if got := authID.Names(); got != nil {
-				t.Errorf("%q.Names(): got: %q, want: nil", got)
-			}
-		}
+	time.Sleep(time.Millisecond)
+	if authid, _ := id.Authorize(NewContext(ContextArgs{})); authid != nil && len(authid.Names()) != 0 {
+		t.Errorf("%q.Authorize returned %v, wanted empty slice", id, authid)
+	}
+}
+
+func TestExpiredIdentityInSet(t *testing.T) {
+	var (
+		alice       = newChain("alice").PublicID()
+		googleAlice = bless(alice, googleChain, "googler", nil)
+	)
+	veyronAlice, err := veyronChain.Bless(alice, "veyroner", time.Millisecond, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	time.Sleep(time.Millisecond)
+	setid := newSetPublicID(alice, googleAlice, veyronAlice)
+	authid, _ := setid.Authorize(NewContext(ContextArgs{}))
+	if authid == nil {
+		t.Fatalf("%q.Authorize returned nil, expected google/alice", setid)
+	}
+	if got, want := authid.Names(), "google/googler"; len(got) != 1 || got[0] != want {
+		t.Errorf("Got %v want [%v]", got, want)
 	}
 }
 
@@ -172,95 +171,77 @@
 	}
 }
 
-func TestTamperedIdentityTree(t *testing.T) {
-	alice := newTree("alice").PublicID().(*treePublicID)
-	// Tamper with the alice's public key
-	alice.publicKey.Y.SetInt64(1)
-	// Check that integrity verification fails
-	if _, err := roundTrip(alice); err != wire.ErrNoIntegrity {
-		t.Errorf("Got %v want %v from roundTrip(%v)", err, wire.ErrNoIntegrity, alice)
-	}
-}
-
 func TestBless(t *testing.T) {
 	var (
 		cAlice       = newChain("alice")
-		cBob         = newChain("bob")
+		cBob         = newChain("bob").PublicID()
 		cVeyronAlice = derive(bless(cAlice.PublicID(), veyronChain, "alice", nil), cAlice)
+		cGoogleAlice = derive(bless(cAlice.PublicID(), googleChain, "alice", nil), cAlice)
+		cVeyronBob   = bless(cBob, veyronChain, "bob", nil)
 
-		tAlice       = newTree("alice")
-		tBob         = newTree("bob")
-		tVeyronAlice = derive(bless(tAlice.PublicID(), veyronTree, "alice", nil), tAlice)
+		sVeyronAlice = newSetPrivateID(cAlice, cVeyronAlice, cGoogleAlice)
+		sVeyronBob   = newSetPublicID(cBob, cVeyronBob)
 	)
 	testdata := []struct {
-		blessor      security.PrivateID
-		blessee      security.PublicID
-		blessing     string   // name provided to security.PublicID.Bless
-		blessedNames []string // names of the blessed identity. Empty if the Bless operation should have failed
-		err          string
+		blessor  security.PrivateID
+		blessee  security.PublicID
+		blessing string   // name provided to security.PublicID.Bless
+		blessed  []string // names of the blessed identity. Empty if the Bless operation should have failed
+		err      string
 	}{
+		// Blessings from veyron/alice (chain implementation)
 		{
-			blessor: veyronChain,
-			blessee: cAlice.PublicID(),
+			blessor: cVeyronAlice,
+			blessee: cBob,
 			err:     `invalid blessing name:""`,
 		},
 		{
-			blessor:  veyronChain,
-			blessee:  cAlice.PublicID(),
+			blessor:  cVeyronAlice,
+			blessee:  cBob,
 			blessing: "alice/bob",
 			err:      `invalid blessing name:"alice/bob"`,
 		},
 		{
-			blessor:      veyronChain,
-			blessee:      cAlice.PublicID(),
-			blessing:     "alice",
-			blessedNames: S{"veyron/alice"},
-		},
-		{
-			blessor:      cVeyronAlice,
-			blessee:      cBob.PublicID(),
-			blessing:     "friend_bob",
-			blessedNames: S{"veyron/alice/friend_bob"},
-		},
-		{
-			blessor:  cAlice,
-			blessee:  cBob.PublicID(),
+			blessor:  cVeyronAlice,
+			blessee:  cBob,
 			blessing: "friend_bob",
+			blessed:  S{"veyron/alice/friend_bob"},
 		},
 		{
-			blessor: veyronTree,
-			blessee: tAlice.PublicID(),
+			blessor:  cVeyronAlice,
+			blessee:  sVeyronBob,
+			blessing: "friend_bob",
+			blessed:  S{"veyron/alice/friend_bob"},
+		},
+		// Blessings from alice#google/alice#veyron/alice
+		{
+			blessor: sVeyronAlice,
+			blessee: cBob,
 			err:     `invalid blessing name:""`,
 		},
 		{
-			blessor:  veyronTree,
-			blessee:  tAlice.PublicID(),
+			blessor:  sVeyronAlice,
+			blessee:  cBob,
 			blessing: "alice/bob",
 			err:      `invalid blessing name:"alice/bob"`,
 		},
 		{
-			blessor:      veyronTree,
-			blessee:      tAlice.PublicID(),
-			blessing:     "alice",
-			blessedNames: S{"veyron/alice"},
+			blessor:  sVeyronAlice,
+			blessee:  cBob,
+			blessing: "friend_bob",
+			blessed:  S{"veyron/alice/friend_bob", "google/alice/friend_bob"},
 		},
 		{
-			blessor:      tVeyronAlice,
-			blessee:      tBob.PublicID(),
-			blessing:     "friend_bob",
-			blessedNames: S{"veyron/alice/friend_bob"},
-		},
-		{
-			blessor:      googleTree,
-			blessee:      tVeyronAlice.PublicID(),
-			blessing:     "googler",
-			blessedNames: S{"veyron/alice", "google/googler"},
+			blessor:  sVeyronAlice,
+			blessee:  sVeyronBob,
+			blessing: "friend_bob",
+			blessed:  S{"veyron/alice/friend_bob", "google/alice/friend_bob"},
 		},
 	}
 
 	for _, d := range testdata {
-		if len(d.blessedNames) != 0 && len(d.err) != 0 {
-			t.Fatalf("Bad testdata. At most one of blessedNames and err must be non-empty: %q", d)
+		if (len(d.blessed) == 0) == (len(d.err) == 0) {
+			t.Fatalf("Bad testdata. Exactly one of blessed and err must be non-empty: %+v", d)
 		}
 		blessed, err := d.blessor.Bless(d.blessee, d.blessing, 1*time.Minute, nil)
 		// Exactly one of (blessed, err) should be nil
@@ -276,7 +257,7 @@
 			continue
 		}
 		// Compare names
-		if got, want := blessed.Names(), d.blessedNames; !reflect.DeepEqual(got, want) {
+		if got, want := blessed.Names(), d.blessed; !reflect.DeepEqual(got, want) {
 			t.Errorf("%q.Names(): got: %q, want: %q", blessed, got, want)
 		}
 		// Public keys should match for blessed and blessee
@@ -292,19 +273,14 @@
 
 func TestAuthorizeWithCaveats(t *testing.T) {
 	var (
-		// Alice's chain and tree identities
+		// alice
 		pcAlice = newChain("alice")
 		cAlice  = pcAlice.PublicID().(*chainPublicID)
-		ptAlice = newTree("alice")
-		tAlice  = ptAlice.PublicID().(*treePublicID)
 
 		// veyron/alice/tv
 		cVeyronAliceTV = bless(newChain("tv").PublicID(),
 			derive(bless(cAlice, veyronChain, "alice", nil), pcAlice),
 			"tv", nil).(*chainPublicID)
-		tVeyronAliceTV = bless(newTree("tv").PublicID(),
-			derive(bless(tAlice, veyronTree, "alice", nil), ptAlice),
-			"tv", nil).(*treePublicID)
 
 		// Some random server called bob
 		bob = newChain("bob").PublicID()
@@ -335,66 +311,43 @@
 			tests: []rpc{
 				{server: bob, method: "Hello", authNames: S{"veyron/alice"}},
 				{server: bob, authNames: S{"veyron/alice"}},
-				{server: googleTree.PublicID(), method: "Hello", authErr: "caveat.MethodRestriction{\"Play\"} forbids invocation of method Hello"},
-				{server: googleTree.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
-				{server: googleTree.PublicID(), authNames: S{"veyron/alice"}},
+				{server: googleChain.PublicID(), method: "Hello", authErr: `caveat.MethodRestriction{"Play"} forbids invocation of method Hello`},
+				{server: googleChain.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
+				{server: googleChain.PublicID(), authNames: S{"veyron/alice"}},
 			},
 		},
 		{
 			client: bless(cAlice, veyronChain, "alice", cavOnlyGoogle),
 			tests: []rpc{
-				{server: bob, method: "Hello", authErr: "caveat.PeerIdentity{\"google\"} forbids RPCing with peer"},
-				{server: googleTree.PublicID(), method: "Hello", authNames: S{"veyron/alice"}},
-				{server: googleTree.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
+				{server: bob, method: "Hello", authErr: `caveat.PeerIdentity{"google"} forbids RPCing with peer`},
+				{server: googleChain.PublicID(), method: "Hello", authNames: S{"veyron/alice"}},
+				{server: googleChain.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
 			},
 		},
 		{
 			client: bless(cAlice, veyronChain, "alice", append(cavOnlyGoogle, cavOnlyPlayAtGoogle...)),
 			tests: []rpc{
-				{server: bob, method: "Hello", authErr: "caveat.PeerIdentity{\"google\"} forbids RPCing with peer"},
-				{server: googleTree.PublicID(), method: "Hello", authErr: "caveat.MethodRestriction{\"Play\"} forbids invocation of method Hello"},
-				{server: googleTree.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
+				{server: bob, method: "Hello", authErr: `caveat.PeerIdentity{"google"} forbids RPCing with peer`},
+				{server: googleChain.PublicID(), method: "Hello", authErr: `caveat.MethodRestriction{"Play"} forbids invocation of method Hello`},
+				{server: googleChain.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
 			},
 		},
 		{
 			client: bless(cAlice, veyronChain, "alice", cavOnlyPublicProfile),
 			tests: []rpc{
-				{server: cVeyronAliceTV, method: "PrivateProfile", authErr: "caveat.MethodRestriction{\"PublicProfile\"} forbids invocation of method PrivateProfile"},
+				{server: cVeyronAliceTV, method: "PrivateProfile", authErr: `caveat.MethodRestriction{"PublicProfile"} forbids invocation of method PrivateProfile`},
 				{server: cVeyronAliceTV, method: "PublicProfile", authNames: S{"veyron/alice"}},
 			},
 		},
-		// client has a tree identity
+		// client has multiple blessings
 		{
-			client: bless(tAlice, veyronTree, "alice", cavOnlyPlayAtGoogle),
+			client: newSetPublicID(bless(cAlice, veyronChain, "valice", append(cavOnlyPlayAtGoogle, cavOnlyPublicProfile...)), bless(cAlice, googleChain, "galice", cavOnlyGoogle)),
 			tests: []rpc{
-				{server: bob, method: "Hello", authNames: S{"veyron/alice"}},
-				{server: bob, authNames: S{"veyron/alice"}},
-				{server: googleTree.PublicID(), method: "Hello"},
-				{server: googleTree.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
-				{server: googleTree.PublicID(), authNames: S{"veyron/alice"}},
-			},
-		},
-		{
-			client: bless(tAlice, veyronTree, "alice", cavOnlyGoogle),
-			tests: []rpc{
-				{server: bob, method: "Hello"},
-				{server: googleTree.PublicID(), method: "Hello", authNames: S{"veyron/alice"}},
-				{server: googleTree.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
-			},
-		},
-		{
-			client: bless(tAlice, veyronTree, "alice", append(cavOnlyGoogle, cavOnlyPlayAtGoogle...)),
-			tests: []rpc{
-				{server: bob, method: "Hello"},
-				{server: googleTree.PublicID(), method: "Hello"},
-				{server: googleTree.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
-			},
-		},
-		{
-			client: bless(tAlice, veyronTree, "alice", cavOnlyPublicProfile),
-			tests: []rpc{
-				{server: tVeyronAliceTV, method: "PrivateProfile"},
-				{server: tVeyronAliceTV, method: "PublicProfile", authNames: S{"veyron/alice"}},
+				{server: bob, method: "Hello", authNames: S{"veyron/valice"}},
+				{server: googleChain.PublicID(), method: "Play", authNames: S{"veyron/valice", "google/galice"}},
+				{server: googleChain.PublicID(), method: "Buy", authNames: S{"google/galice"}},
+				{server: cVeyronAliceTV, method: "PublicProfile", authNames: S{"veyron/valice"}},
+				{server: cVeyronAliceTV, method: "PrivateProfile", authErr: "none of the blessings in the set are authorized"},
 			},
 		},
 	}
@@ -405,8 +358,8 @@
 			continue
 		}
 		for _, test := range d.tests {
-			if len(test.authNames) != 0 && len(test.authErr) != 0 {
-				t.Fatalf("Bad testdata. At most one of authNames and authErr must be non-empty: %q, %+v", d.client, test)
+			if (len(test.authNames) == 0) == (len(test.authErr) == 0) {
+				t.Fatalf("Bad testdata. Exactly one of authNames and authErr must be non-empty: %+q/%+v", d.client, test)
 			}
 			ctx := NewContext(ContextArgs{LocalID: test.server, RemoteID: d.client, Method: test.method})
 			authID, err := d.client.Authorize(ctx)
@@ -414,51 +367,51 @@
 				t.Errorf("%q.Authorize(%v) returned error: %v, want to match: %q", d.client, ctx, err, test.authErr)
 			}
 			if err := verifyAuthorizedID(d.client, authID, test.authNames); err != nil {
-				t.Errorf("%q.Authorize(%v) returned identity: %v want identity with names: %q", d.client, ctx, authID, test.authNames)
+				t.Errorf("%q.Authorize(%v) returned identity: %v want identity with names: %q [%v]", d.client, ctx, authID, test.authNames, err)
 			}
 		}
 	}
 }
 
 func TestAuthorizeWithThirdPartyCaveats(t *testing.T) {
-	mkveyronchain := func(name string) security.PrivateID {
-		base := newChain(name)
-		return derive(bless(base.PublicID(), veyronChain, name, nil), base)
+	mkveyron := func(id security.PrivateID, name string) security.PrivateID {
+		return derive(bless(id.PublicID(), veyronChain, name, nil), id)
 	}
-	mkveyrontree := func(name string) security.PrivateID {
-		base := newTree(name)
-		return derive(bless(base.PublicID(), veyronTree, name, nil), base)
+	mkgoogle := func(id security.PrivateID, name string) security.PrivateID {
+		return derive(bless(id.PublicID(), googleChain, name, nil), id)
 	}
-	// Principals (type conversions just to protect against accidentally
-	// calling the wrong factory function)
+	mkcaveat := func(id security.PrivateID) []security.ServiceCaveat {
+		c, err := caveat.NewPublicKeyCaveat("proximity", id.PublicID(), fmt.Sprintf("%v location", id.PublicID()))
+		if err != nil {
+			t.Fatal(err)
+		}
+		return []security.ServiceCaveat{security.UniversalCaveat(c)}
+	}
 	var (
-		alice  = mkveyronchain("alice")
-		cBob   = mkveyronchain("bob").(*chainPrivateID)
-		tBob   = mkveyrontree("bob").(*treePrivateID)
-		cCarol = mkveyronchain("carol").(*chainPrivateID).PublicID()
-		tCarol = mkveyrontree("carol").(*treePrivateID).PublicID()
+		alice = newChain("alice")
+		bob   = newChain("bob")
+		carol = newChain("carol").PublicID()
+
+		// aliceProximityCaveat is a caveat whose discharge can only be minted by alice.
+		aliceProximityCaveat = mkcaveat(alice)
+		bobProximityCaveat   = mkcaveat(bob)
 	)
-	// aliceProximityCaveat is a caveat that can only be minted by alice
-	aliceProximityCaveat, err := caveat.NewPublicKeyCaveat("proximity", alice.PublicID(), "alice location")
-	if err != nil {
-		t.Fatal(err)
-	}
+
 	mintDischarge := func(id security.PrivateID, duration time.Duration, caveats []security.ServiceCaveat) security.ThirdPartyDischarge {
-		d, err := id.MintDischarge(aliceProximityCaveat, duration, caveats)
+		d, err := id.MintDischarge(aliceProximityCaveat[0].Caveat.(security.ThirdPartyCaveat), duration, caveats)
 		if err != nil {
 			t.Fatalf("%q.MintDischarge failed: %v", id, err)
 		}
 		return d
 	}
-	// Discharges
 	var (
+		// Discharges
 		dAlice   = mintDischarge(alice, time.Minute, nil)
 		dGoogle  = mintDischarge(alice, time.Minute, peerIdentityCaveat("google"))
 		dExpired = mintDischarge(alice, 0, nil)
-		dInvalid = mintDischarge(cBob, time.Minute, nil) // Invalid because carol cannot mint valid discharges for aliceProximityCaveat
-	)
-	// Contexts
-	var (
+		dInvalid = mintDischarge(bob, time.Minute, nil) // Invalid because bob cannot mint valid discharges for aliceProximityCaveat
+
+		// Contexts
 		ctxEmpty = NewContext(ContextArgs{Debug: "ctxEmpty"})
 		ctxAlice = NewContext(ContextArgs{
 			Discharges: security.CaveatDischargeMap{dAlice.CaveatID(): dAlice},
@@ -484,57 +437,69 @@
 			Discharges: security.CaveatDischargeMap{dInvalid.CaveatID(): dInvalid},
 			Debug:      "ctxInvalid",
 		})
+
+		// Contexts that should always end in authorization errors
+		errtests = map[security.Context]string{
+			ctxEmpty:         "missing discharge",
+			ctxGoogleAtOther: "forbids RPCing with peer",
+			ctxExpired:       "at this time",
+			ctxInvalid:       "invalid signature",
+		}
 	)
 
-	type want struct {
-		// Exactly one of these should be non-empty
-		authNames []string
-		err       string
-	}
-
-	chaintests := map[security.Context]want{
-		ctxEmpty:          want{err: "missing discharge"},
-		ctxAlice:          want{authNames: S{"veyron/bob/friend"}},
-		ctxGoogleAtOther:  want{err: "forbids RPCing with peer"},
-		ctxGoogleAtGoogle: want{authNames: S{"veyron/bob/friend"}},
-		ctxExpired:        want{err: "at this time"},
-		ctxInvalid:        want{err: "invalid signature"},
-	}
-	treetests := map[security.Context]want{
-		ctxEmpty:          want{authNames: S{"veyron/carol"}},
-		ctxAlice:          want{authNames: S{"veyron/carol", "veyron/bob/friend"}},
-		ctxGoogleAtOther:  want{authNames: S{"veyron/carol"}},
-		ctxGoogleAtGoogle: want{authNames: S{"veyron/carol", "veyron/bob/friend"}},
-		ctxExpired:        want{authNames: S{"veyron/carol"}},
-		ctxInvalid:        want{authNames: S{"veyron/carol"}},
-	}
-	caveats := []security.ServiceCaveat{security.UniversalCaveat(aliceProximityCaveat)}
 	testdata := []struct {
-		id    security.PublicID
-		tests map[security.Context]want
+		id        security.PublicID
+		authNames S // For ctxAlice and ctxGoogleAtGoogle
 	}{
-		{bless(cCarol, cBob, "friend", caveats), chaintests},
-		{bless(tCarol, tBob, "friend", caveats), treetests},
+		// carol blessed by bob with the third-party caveat should be authorized when the context contains a valid discharge
+		{
+			id:        bless(carol, mkveyron(bob, "bob"), "friend", aliceProximityCaveat),
+			authNames: S{"veyron/bob/friend"},
+		},
+		// veyron/vbob/vfriend with bobProximityCaveat and google/gbob/gfriend with aliceProximityCaveat
+		// Only google/gbob/gfriend should be authorized since the discharge for the former is missing
+		{
+			id: newSetPublicID(
+				bless(carol, mkveyron(bob, "vbob"), "vfriend", bobProximityCaveat),
+				bless(carol, mkgoogle(bob, "gbob"), "gfriend", aliceProximityCaveat)),
+			authNames: S{"google/gbob/gfriend"},
+		},
+		// veyron/vbob/friend#google/gbob/friend both have the same caveat and both are satisfied
+		{
+			id:        bless(carol, newSetPrivateID(mkveyron(bob, "vbob"), mkgoogle(bob, "gbob")), "friend", aliceProximityCaveat),
+			authNames: S{"veyron/vbob/friend", "google/gbob/friend"},
+		},
 	}
-	for _, d := range testdata {
-		if _, err := roundTrip(d.id); err != nil {
-			t.Errorf("%q is not round-trippable: %v", d.id, d.id, err)
+	for _, test := range testdata {
+		if _, err := roundTrip(test.id); err != nil {
+			t.Errorf("%q is not round-trippable: %v", test.id, test.id, err)
 		}
-		for ctx, want := range d.tests {
-			if (len(want.authNames) != 0) && (len(want.err) != 0) {
-				t.Fatalf("Bad testdata. Atmost one of (authNames, err) must be non-empty: %q, %v", d.id, ctx)
+		for _, ctx := range []security.Context{ctxAlice, ctxGoogleAtGoogle} {
+			authID, _ := test.id.Authorize(ctx)
+			if err := verifyAuthorizedID(test.id, authID, test.authNames); err != nil {
+				t.Errorf("%q.Authorize(%v): %v", test.id, ctx, err)
 			}
-			authID, err := d.id.Authorize(ctx)
-			if !matchesErrorPattern(err, want.err) {
-				t.Errorf("%q.Authorize(%v) returned error: %v, want to match: %q", d.id, ctx, err, want.err)
+		}
+		for ctx, want := range errtests {
+			authID, err := test.id.Authorize(ctx)
+			if authID != nil {
+				t.Errorf("%q.Authorize(%v) returned %v, should have returned nil", test.id, ctx, authID)
 			}
-			if err := verifyAuthorizedID(d.id, authID, want.authNames); err != nil {
-				t.Errorf("%q.Authorize(%v): %v", d.id, ctx, err)
+			if !matchesErrorPattern(err, want) {
+				t.Errorf("%q.Authorize(%v) returned error: %v, want to match: %q", test.id, ctx, err, want)
 			}
 		}
 	}
 }
 
+type SortedThirdPartyCaveats []security.ServiceCaveat
+
+func (s SortedThirdPartyCaveats) Len() int { return len(s) }
+func (s SortedThirdPartyCaveats) Less(i, j int) bool {
+	return s[i].Caveat.(security.ThirdPartyCaveat).ID() < s[j].Caveat.(security.ThirdPartyCaveat).ID()
+}
+func (s SortedThirdPartyCaveats) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
 func TestThirdPartyCaveatAccessors(t *testing.T) {
 	mkTPCaveat := func(restriction string, id security.PublicID) security.ThirdPartyCaveat {
 		tpCav, err := caveat.NewPublicKeyCaveat(restriction, id, "someLocation")
@@ -551,48 +516,57 @@
 		return d
 	}
 
-	// Principals (type conversions just to protect against accidentally
-	// calling the wrong factory function)
+	sortTPCaveats := func(c []security.ServiceCaveat) []security.ServiceCaveat {
+		sort.Stable(SortedThirdPartyCaveats(c))
+		return c
+	}
+
 	var (
-		alice = newChain("alice").(*chainPrivateID)
-		cBob  = newChain("bob").(*chainPrivateID)
-		tBob  = newTree("bob").(*treePrivateID)
-	)
-	// Caveats
-	var (
+		// Principals (type conversions just to protect against accidentally
+		// calling the wrong factory function)
+		alice       = newChain("alice").(*chainPrivateID)
+		cBob        = newChain("bob").(*chainPrivateID)
+		cBobBuilder = derive(bless(cBob.PublicID(), cBob, "builder", nil), cBob) // Bob also calls himself bob/builder
+		sBob        = newSetPrivateID(cBob, cBobBuilder).(setPrivateID)
+
+		// Caveats
 		tpCavService   = security.ServiceCaveat{Service: "someService", Caveat: mkTPCaveat("foo", alice.PublicID())}
 		tpCavUniversal = security.UniversalCaveat(mkTPCaveat("bar", alice.PublicID()))
 		cav            = methodRestrictionCaveat("someService", nil)[0]
 	)
 
-	caveatsData := []struct {
-		caveats           []security.ServiceCaveat
-		thirdPartyCaveats []security.ServiceCaveat
+	caveats := []struct {
+		firstparty []security.ServiceCaveat
+		thirdparty []security.ServiceCaveat
 	}{
-		{caveats: nil, thirdPartyCaveats: nil},
-		{caveats: []security.ServiceCaveat{cav}, thirdPartyCaveats: nil},
-		{caveats: []security.ServiceCaveat{tpCavService}, thirdPartyCaveats: []security.ServiceCaveat{tpCavService}},
-		{caveats: []security.ServiceCaveat{tpCavService, tpCavUniversal}, thirdPartyCaveats: []security.ServiceCaveat{tpCavService, tpCavUniversal}},
-		{caveats: []security.ServiceCaveat{tpCavService, cav, tpCavUniversal}, thirdPartyCaveats: []security.ServiceCaveat{tpCavService, tpCavUniversal}},
+		{firstparty: nil, thirdparty: nil},
+		{firstparty: []security.ServiceCaveat{cav}},
+		{thirdparty: []security.ServiceCaveat{tpCavService}},
+		{thirdparty: []security.ServiceCaveat{tpCavService, tpCavUniversal}},
+		{firstparty: []security.ServiceCaveat{cav}, thirdparty: []security.ServiceCaveat{tpCavService, tpCavUniversal}},
 	}
 	testdata := []struct {
 		privID security.PrivateID
 		pubID  security.PublicID
 	}{
-		{privID: veyronChain, pubID: cBob.PublicID()},
-		{privID: veyronTree, pubID: tBob.PublicID()},
+		{privID: veyronChain, pubID: cBob.PublicID()}, // Chain blessing a chain
+		{privID: veyronChain, pubID: sBob.PublicID()}, // Chain blessing a set
+		{privID: sBob, pubID: cBob.PublicID()},        // Set blessing a chain
+		//{privID: veyronTree, pubID: tBob.PublicID()},
 	}
 	for _, d := range testdata {
-		for _, c := range caveatsData {
+		for _, c := range caveats {
+			all := append(c.firstparty, c.thirdparty...)
 			// Test ThirdPartyCaveat accessors on security.PublicIDs.
-			id := bless(d.pubID, d.privID, "irrelevant", c.caveats)
-			if got, want := id.ThirdPartyCaveats(), c.thirdPartyCaveats; !reflect.DeepEqual(got, want) {
-				t.Errorf("Test credential %q with caveats %+v: got ThirdPartyCaveats() = %+v, want %+v", id, c.caveats, got, want)
+			id := bless(d.pubID, d.privID, "irrelevant", all)
+			want := sortTPCaveats(c.thirdparty)
+			if got := sortTPCaveats(id.ThirdPartyCaveats()); !reflect.DeepEqual(got, want) {
+				t.Errorf("%q(%T) got ThirdPartyCaveats() = %+v, want %+v", id, id, got, want)
 			}
 			// Test ThirdPartyCaveat accessors on security.ThirdPartyCaveatDischarges.
-			dis := mintDischarge(mkTPCaveat("baz", alice.PublicID()), d.privID, c.caveats)
-			if got, want := dis.ThirdPartyCaveats(), c.thirdPartyCaveats; !reflect.DeepEqual(got, want) {
-				t.Errorf("Test credential %q with caveats %+v: got ThirdPartyCaveats() = %+v, want %+v", dis, c.caveats, got, want)
+			dis := mintDischarge(mkTPCaveat("baz", alice.PublicID()), d.privID, all)
+			if got := sortTPCaveats(dis.ThirdPartyCaveats()); !reflect.DeepEqual(got, want) {
+				t.Errorf("%q got ThirdPartyCaveats() = %+v, want %+v", dis, got, want)
 			}
 		}
 	}
@@ -666,24 +640,28 @@
 		cAlice       = newChain("alice")
 		cVeyronAlice = bless(cAlice.PublicID(), veyronChain, "alice", nil)
 		cBob         = newChain("bob").PublicID()
-		tAlice       = newTree("alice")
-		tVeyronAlice = bless(tAlice.PublicID(), veyronTree, "alice", nil)
-		tBob         = newTree("bob").PublicID()
+		sVeyronAlice = newSetPrivateID(cAlice, derive(cVeyronAlice, cAlice))
+
+		tChain = reflect.TypeOf(cAlice)
+		tSet   = reflect.TypeOf(sVeyronAlice)
+		tErr   = reflect.TypeOf(nil)
 	)
 	testdata := []struct {
 		priv security.PrivateID
 		pub  security.PublicID
-		err  bool
+		typ  reflect.Type
 	}{
-		{priv: cAlice, pub: cVeyronAlice},
-		{priv: cAlice, pub: cBob, err: true},
-		{priv: tAlice, pub: tVeyronAlice},
-		{priv: tAlice, pub: tBob, err: true},
+		{priv: cAlice, pub: cVeyronAlice, typ: tChain},          // chain.Derive(chain) = chain
+		{priv: cAlice, pub: sVeyronAlice.PublicID(), typ: tSet}, // chain.Derive(set) = set
+		{priv: cAlice, pub: cBob, typ: tErr},
+		{priv: sVeyronAlice, pub: cAlice.PublicID(), typ: tChain},     // set.Derive(chain) = chain
+		{priv: sVeyronAlice, pub: sVeyronAlice.PublicID(), typ: tSet}, // set.Derive(set) = set
+		{priv: sVeyronAlice, pub: cBob, typ: tErr},
 	}
 	for _, d := range testdata {
 		derivedID, err := d.priv.Derive(d.pub)
-		if (err != nil) != d.err {
-			t.Errorf("%q.Derive(%q) returned error: %v, wanted: %t", d.priv, d.pub, err, d.err)
+		if reflect.TypeOf(derivedID) != d.typ {
+			t.Errorf("%T=%q.Derive(%T=%q) yielded %T, want %v", d.priv, d.priv, d.pub, d.pub, derivedID, d.typ)
 			continue
 		}
 		if err != nil {
@@ -702,3 +680,37 @@
 		}
 	}
 }
+
+func TestNewSetFailures(t *testing.T) {
+	var (
+		alice = newChain("alice")
+		bob   = newChain("bob")
+	)
+	if s, err := NewSetPrivateID(alice, bob); err == nil {
+		t.Errorf("Got %v, want error since PrivateKeys do not match", s)
+	}
+	if s, err := NewSetPublicID(alice.PublicID(), bob.PublicID()); err == nil {
+		t.Errorf("Got %v, want error since PublicKeys do not match", s)
+	}
+}
+
+func TestSetIdentityAmplification(t *testing.T) {
+	var (
+		alice = newChain("alice").PublicID()
+		bob   = newChain("bob").PublicID()
+
+		sAlice = newSetPublicID(bless(alice, veyronChain, "valice", nil), bless(alice, googleChain, "galice", nil))
+	)
+
+	// Manipulate sAlice before writing it out to the wire so that it has Bob's authorizations.
+	reflect.ValueOf(sAlice).Elem().Index(1).Set(reflect.ValueOf(bob))
+	// Encode/decode the identity.
+	var buf bytes.Buffer
+	if err := vom.NewEncoder(&buf).Encode(sAlice); err != nil {
+		t.Fatal(err)
+	}
+	var decoded security.PublicID
+	if err := vom.NewDecoder(&buf).Decode(&decoded); err == nil || decoded != nil {
+		t.Fatalf("Got (%v, %v), want wire decode of manipulated identity to fail", decoded, err)
+	}
+}
diff --git a/runtimes/google/security/identity_tree.go b/runtimes/google/security/identity_tree.go
deleted file mode 100644
index 6c9eabd..0000000
--- a/runtimes/google/security/identity_tree.go
+++ /dev/null
@@ -1,276 +0,0 @@
-package security
-
-// This file describes a blessing tree based implementation of security.PublicID.
-
-import (
-	"bytes"
-	"crypto/ecdsa"
-	"crypto/elliptic"
-	"crypto/rand"
-	"errors"
-	"fmt"
-	"math/big"
-	"reflect"
-	"strings"
-	"time"
-
-	icaveat "veyron/runtimes/google/security/caveat"
-	"veyron/runtimes/google/security/keys"
-	"veyron/runtimes/google/security/wire"
-	"veyron/security/caveat"
-	"veyron2/security"
-	"veyron2/vom"
-)
-
-// nameSeparator is used to join blessing chain names to form a blessing tree name.
-const nameSeparator = "#"
-
-// treePublicID implements security.PublicID.
-type treePublicID struct {
-	blessings []wire.Blessing
-	publicKey *ecdsa.PublicKey
-	paths     []treePath
-}
-
-func (id *treePublicID) Names() []string {
-	var names []string
-	for _, p := range id.paths {
-		if keys.LevelOfTrust(p.providerKey, p.providerName) == keys.Trusted {
-			names = append(names, p.name)
-		}
-	}
-	return names
-}
-
-// Match determines if the PublicID's chained name can be extended to match the
-// provided PrincipalPattern. An extension of a chained name is any name obtained
-// by joining additional strings to the name using wire.ChainSeparator. Ex: extensions
-// of the name "foo/bar" are the names "foo/bar", "foo/bar/baz", "foo/bar/baz/car", and
-// so on.
-func (id *treePublicID) Match(pattern security.PrincipalPattern) bool {
-	return matchPrincipalPattern(id.Names(), pattern)
-}
-
-func (id *treePublicID) PublicKey() *ecdsa.PublicKey { return id.publicKey }
-
-func (id *treePublicID) String() string {
-	var buf bytes.Buffer
-	for i, p := range id.paths {
-		if i > 0 {
-			buf.WriteString(nameSeparator)
-		}
-		buf.WriteString(p.String())
-	}
-	return buf.String()
-}
-
-func (id *treePublicID) VomEncode() (*wire.TreePublicID, error) {
-	var pKey wire.PublicKey
-	if err := pKey.Encode(id.publicKey); err != nil {
-		return nil, err
-	}
-	return &wire.TreePublicID{Blessings: id.blessings, PublicKey: pKey}, nil
-}
-
-func (id *treePublicID) VomDecode(w *wire.TreePublicID) error {
-	if err := w.VerifyIntegrity(); err != nil {
-		return err
-	}
-	return id.initFromWire(w)
-}
-
-func (id *treePublicID) initFromWire(w *wire.TreePublicID) error {
-	names, providers := w.Names()
-	paths := make([]treePath, len(names))
-	for i, p := range paths {
-		if len(names[i]) == 0 || providers[i] == nil {
-			return fmt.Errorf("invalid identity provider: (name=%q, key=%v)", names[i], providers[i])
-		}
-		p.name = strings.Join(names[i], wire.ChainSeparator)
-		p.providerName = names[i][0]
-		p.providerKey = providers[i]
-		paths[i] = p
-	}
-	key, err := w.PublicKey.Decode()
-	if err != nil {
-		return err
-	}
-	id.blessings = w.Blessings
-	id.publicKey = key
-	id.paths = paths
-	return nil
-}
-
-// Authorize returns a new treePublicID with only those blessing chains from
-// the existing PublicID whose caveats validate with respect to the provided
-// context and whose identity providers (leaf blessings) are trusted.  This
-// method assumes that the existing PublicID was obtained after successfully
-// decoding a serialized PublicID and hence has integrity.
-func (id *treePublicID) Authorize(context security.Context) (security.PublicID, error) {
-	w, err := id.VomEncode()
-	if err != nil {
-		return nil, err
-	}
-	wAuthorizedID := w.Authorize(context)
-	if wAuthorizedID == nil {
-		return nil, errors.New("tree identity with no blessings")
-	}
-	authorizedID := &treePublicID{}
-	if err := authorizedID.initFromWire(wAuthorizedID); err != nil {
-		return nil, err
-	}
-	return authorizedID, nil
-}
-
-// treePath encapsulates the name created by following blessings that link the
-// public key of a treePublicID to an identity provider.
-type treePath struct {
-	name         string
-	providerName string
-	providerKey  *ecdsa.PublicKey
-}
-
-func (t *treePath) String() string {
-	if keys.LevelOfTrust(t.providerKey, t.providerName) != keys.Trusted {
-		return wire.UntrustedIDProviderPrefix + t.name
-	}
-	return t.name
-}
-
-func (id *treePublicID) ThirdPartyCaveats() (thirdPartyCaveats []security.ServiceCaveat) {
-	if w, err := id.VomEncode(); err == nil {
-		thirdPartyCaveats = w.ThirdPartyCaveats()
-	}
-	return
-}
-
-// treePrivateID implements security.PrivateID.
-type treePrivateID struct {
-	publicID   *treePublicID
-	privateKey *ecdsa.PrivateKey
-}
-
-// PublicID returns the PublicID associated with the PrivateID.
-func (id *treePrivateID) PublicID() security.PublicID { return id.publicID }
-
-// PrivateKey returns the private key associated with the PrivateID.
-func (id *treePrivateID) PrivateKey() *ecdsa.PrivateKey { return id.privateKey }
-
-func (id *treePrivateID) String() string { return fmt.Sprintf("PrivateID:%v", id.publicID) }
-
-func (id *treePrivateID) VomEncode() (*wire.TreePrivateID, error) {
-	var err error
-	w := &wire.TreePrivateID{Secret: id.privateKey.D.Bytes()}
-	w.PublicID, err = id.publicID.VomEncode()
-	return w, err
-}
-
-func (id *treePrivateID) VomDecode(w *wire.TreePrivateID) error {
-	if err := id.publicID.VomDecode(w.PublicID); err != nil {
-		return err
-	}
-	id.privateKey = &ecdsa.PrivateKey{
-		PublicKey: *id.publicID.publicKey,
-		D:         new(big.Int).SetBytes(w.Secret),
-	}
-	return nil
-}
-
-// Bless returns a new PublicID by extendinig the blessee's blessings with a
-// new one signed by id's private key and named blessingName with caveats and
-// an additional expiry caveat for the provided duration.
-func (id *treePrivateID) Bless(blesseeID security.PublicID, blessingName string, duration time.Duration, caveats []security.ServiceCaveat) (security.PublicID, error) {
-	// The integrity of the PublicID blessee is assumed to have been verified
-	// (typically by a Vom decode)
-	if err := wire.ValidateBlessingName(blessingName); err != nil {
-		return nil, err
-	}
-	blessee, ok := blesseeID.(*treePublicID)
-	if !ok {
-		return nil, fmt.Errorf("PrivateID of type %T cannot bless PublicID of type %T", id, blesseeID)
-	}
-	if blessee.blessings == nil {
-		return nil, errors.New("blessee must at least have one blessing before it can be blessed further")
-	}
-
-	blessing := wire.Blessing{Name: blessingName}
-	var err error
-	if blessing.Blessor, err = id.publicID.VomEncode(); err != nil {
-		return nil, err
-	}
-	now := time.Now()
-	caveats = append(caveats, security.UniversalCaveat(&caveat.Expiry{IssueTime: now, ExpiryTime: now.Add(duration)}))
-	if blessing.Caveats, err = wire.EncodeCaveats(caveats); err != nil {
-		return nil, err
-	}
-	var pKey wire.PublicKey
-	if err := pKey.Encode(blessee.publicKey); err != nil {
-		return nil, err
-	}
-	if err := blessing.Sign(pKey, id.privateKey); err != nil {
-		return nil, err
-	}
-	w := &wire.TreePublicID{
-		Blessings: append(blessee.blessings, blessing),
-		PublicKey: pKey,
-	}
-	blessed := &treePublicID{}
-	if err := blessed.initFromWire(w); err != nil {
-		return nil, err
-	}
-	return blessed, nil
-}
-
-// Derive returns a new PrivateID containing priv's private key and the provided PublicID.
-// The provided PublicID must have the same public key as the public key of priv's PublicID.
-func (id *treePrivateID) Derive(pub security.PublicID) (security.PrivateID, error) {
-	if !reflect.DeepEqual(pub.PublicKey(), id.publicID.publicKey) {
-		return nil, errDeriveMismatch
-	}
-	treePub, ok := pub.(*treePublicID)
-	if !ok {
-		return nil, fmt.Errorf("PrivateID of type %T cannot be obtained from PublicID of type %T", id, pub)
-	}
-	return &treePrivateID{
-		publicID:   treePub,
-		privateKey: id.privateKey,
-	}, nil
-
-}
-
-func (id *treePrivateID) MintDischarge(cav security.ThirdPartyCaveat, duration time.Duration, dischargeCaveats []security.ServiceCaveat) (security.ThirdPartyDischarge, error) {
-	switch c := cav.(type) {
-	case *icaveat.PublicKeyCaveat:
-		return icaveat.NewPublicKeyDischarge(c, id.privateKey, duration, dischargeCaveats)
-	}
-	return nil, fmt.Errorf("discharge cannot be constructed for ThirdPartyCaveat of type %T from PrivateID of type %T", cav, id)
-}
-
-// newTreePrivateID returns a new PrivateID containing a freshly generated private
-// key, and a single self-signed blessing for the provided name and the public key
-// corresponding to the generated private key.
-func newTreePrivateID(name string) (security.PrivateID, error) {
-	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
-	if err != nil {
-		return nil, err
-	}
-	var pKey wire.PublicKey
-	if err := pKey.Encode(&key.PublicKey); err != nil {
-		return nil, err
-	}
-	blessing := wire.Blessing{Name: name}
-	if err := blessing.Sign(pKey, key); err != nil {
-		return nil, err
-	}
-	w := &wire.TreePublicID{Blessings: []wire.Blessing{blessing}, PublicKey: pKey}
-	publicID := &treePublicID{}
-	if err := publicID.initFromWire(w); err != nil {
-		return nil, err
-	}
-	return &treePrivateID{publicID: publicID, privateKey: key}, nil
-}
-
-func init() {
-	vom.Register(treePublicID{})
-	vom.Register(treePrivateID{})
-}
diff --git a/runtimes/google/security/performance_test.go b/runtimes/google/security/performance_test.go
index ded5af8..06cbe5e 100644
--- a/runtimes/google/security/performance_test.go
+++ b/runtimes/google/security/performance_test.go
@@ -19,21 +19,7 @@
 // Wire size with 0 blessings: 676 bytes ("untrusted/X")
 // Wire size with 1 blessings: 976 bytes ("untrusted/X/X")
 // Wire size with 2 blessings: 1275 bytes ("untrusted/X/X/X")
-//
-// -- tree implementation --
-//
-// BenchmarkNewTree                     1338252 ns/op
-// BenchmarkBlessTree                    774195 ns/op
-// BenchmarkEncode0BlessingTree           51532 ns/op
-// BenchmarkEncode1BlessingTree           63069 ns/op
-// BenchmarkDecode0BlessingTree         2591321 ns/op
-// BenchmarkDecode1BlessingTree         7575987 ns/op
-//
-// Wire size with 0 blessings: 687 bytes ("untrusted/X")
-// Wire size with 1 blessings: 1066 bytes ("untrusted/X#untrusted/1/X")
-// Wire size with 2 blessings: 1444 bytes ("untrusted/X#untrusted/1/X#untrusted/2/X")
 import (
-	"fmt"
 	"testing"
 	"time"
 
@@ -118,55 +104,3 @@
 		priv = derive(bless(pub, priv, "X", nil), priv)
 	}
 }
-
-// -- tree implementation benchmarks --
-
-func BenchmarkNewTree(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		if _, err := newTreePrivateID("X"); err != nil {
-			b.Fatalf("newTreePrivateID #%d: %v", i, err)
-		}
-
-	}
-}
-
-func BenchmarkBlessTree(b *testing.B) {
-	benchmarkBless(b, newTree("alice"), newTree("bob").PublicID())
-}
-
-func BenchmarkEncode0BlessingTree(b *testing.B) {
-	benchmarkEncode(b, newTree("alice").PublicID())
-}
-
-func BenchmarkEncode1BlessingTree(b *testing.B) {
-	benchmarkEncode(b, bless(newTree("alice").PublicID(), veyronTree, "alice", nil))
-}
-
-func BenchmarkDecode0BlessingTree(b *testing.B) {
-	idBytes, err := encode(newTree("alice").PublicID())
-	if err != nil {
-		b.Fatal(err)
-	}
-	benchmarkDecode(b, idBytes)
-}
-
-func BenchmarkDecode1BlessingTree(b *testing.B) {
-	idBytes, err := encode(bless(newTree("alice").PublicID(), veyronTree, "alice", nil))
-	if err != nil {
-		b.Fatal(err)
-	}
-	benchmarkDecode(b, idBytes)
-}
-
-func TestTreeWireSize(t *testing.T) {
-	const N = 3
-	id := newTree("X").PublicID()
-	for i := 0; i < N; i++ {
-		buf, err := encode(id)
-		if err != nil {
-			t.Fatalf("Failed to encode %q: %v", id, err)
-		}
-		t.Logf("Wire size of %T with %d blessings: %d bytes (%q)", id, i, len(buf), id)
-		id = bless(id, newTree(fmt.Sprintf("%d", i+1)), "X", nil)
-	}
-}
diff --git a/runtimes/google/security/util.go b/runtimes/google/security/util.go
index aab52f4..dcb6f1a 100644
--- a/runtimes/google/security/util.go
+++ b/runtimes/google/security/util.go
@@ -19,9 +19,9 @@
 	switch t := id.(type) {
 	case *chainPrivateID:
 		keys.Trust(t.publicID.rootKey, t.publicID.certificates[0].Name)
-	case *treePrivateID:
-		for _, p := range t.publicID.paths {
-			keys.Trust(p.providerKey, p.providerName)
+	case setPrivateID:
+		for _, priv := range t {
+			TrustIdentityProviders(priv)
 		}
 	default:
 		// Silently ignore
diff --git a/runtimes/google/security/util_test.go b/runtimes/google/security/util_test.go
index f3c4e35..f1f76fc 100644
--- a/runtimes/google/security/util_test.go
+++ b/runtimes/google/security/util_test.go
@@ -19,9 +19,7 @@
 	// Trusted identity providers
 	// (type assertion just to ensure test sanity)
 	veyronChain = newChain("veyron").(*chainPrivateID)
-	veyronTree  = newTree("veyron").(*treePrivateID)
 	googleChain = newChain("google").(*chainPrivateID)
-	googleTree  = newTree("google").(*treePrivateID)
 )
 
 func matchesErrorPattern(err error, pattern string) bool {
@@ -59,8 +57,16 @@
 	return id
 }
 
-func newTree(name string) security.PrivateID {
-	id, err := newTreePrivateID(name)
+func newSetPublicID(ids ...security.PublicID) security.PublicID {
+	id, err := NewSetPublicID(ids...)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+func newSetPrivateID(ids ...security.PrivateID) security.PrivateID {
+	id, err := NewSetPrivateID(ids...)
 	if err != nil {
 		panic(err)
 	}
@@ -116,55 +122,44 @@
 func init() {
 	// Mark "veyron" and "google" as trusted identity providers.
 	keys.Trust(veyronChain.PublicID().PublicKey(), "veyron")
-	keys.Trust(veyronTree.PublicID().PublicKey(), "veyron")
 	keys.Trust(googleChain.PublicID().PublicKey(), "google")
-	keys.Trust(googleTree.PublicID().PublicKey(), "google")
 }
 
 func TestTrustIdentityProviders(t *testing.T) {
 	var (
-		cSelf = newChain("chainself")
-		// cBlessed = "chainprovider/somebody"
-		cProvider = newChain("chainprovider")
+		cSelf     = newChain("chainself")
+		cProvider = newChain("provider")
 		cBlessed  = derive(bless(cSelf.PublicID(), cProvider, "somebody", nil), cSelf)
 
-		tSelf     = newTree("treeself")
-		tProvider = newTree("treeprovider")
-		tBlessed  = derive(bless(tSelf.PublicID(), tProvider, "somebody", nil), tSelf)
+		cProvider1 = newChain("provider")
+		cProvider2 = newChain("provider")
+		cSomebody1 = derive(bless(cSelf.PublicID(), cProvider1, "somebody1", nil), cSelf)
+		cSomebody2 = derive(bless(cSelf.PublicID(), cProvider2, "somebody2", nil), cSelf)
+		setID      = newSetPrivateID(cSomebody1, cSomebody2)
 
 		fake = security.FakePrivateID("fake")
 	)
 	// Initially nobody is trusted
 	m := map[security.PrivateID]bool{
-		cSelf:     false,
-		cProvider: false,
-		tSelf:     false,
-		tProvider: false,
+		cSelf:      false,
+		cProvider:  false,
+		cBlessed:   false,
+		cProvider1: false,
+		cProvider2: false,
+		cSomebody1: false,
+		cSomebody2: false,
 	}
 	test := func() {
 		for priv, want := range m {
 			id := priv.PublicID()
-			key := id.PublicKey()
-			var tl keys.TrustLevel
-			switch impl := id.(type) {
-			case *chainPublicID:
-				tl = keys.LevelOfTrust(key, impl.certificates[0].Name)
-			case *treePublicID:
-				tl = keys.LevelOfTrust(impl.paths[0].providerKey, impl.paths[0].providerName)
-			default:
-				t.Fatal("Unexpected security.PublicID implementation, identity provider TrustLevel checks only apply to the chain and tree implementations of security.PublicID")
-			}
-
-			switch tl {
+			switch tl := keys.LevelOfTrust(id.PublicKey(), "provider"); tl {
 			case keys.Trusted:
 				if !want {
 					t.Errorf("%q is trusted, should not be", id)
 				}
-			case keys.Mistrusted:
-				t.Errorf("%q is mistrusted. This test should not allow anyone to be mistrusted", id)
-			case keys.Unknown:
+			case keys.Unknown, keys.Mistrusted:
 				if want {
-					t.Errorf("%q is not trusted, it should be", id)
+					t.Errorf("%q is %v, it should be trusted", id, tl)
 				}
 			default:
 				t.Errorf("%q has an invalid trust level: %v", tl)
@@ -172,19 +167,15 @@
 		}
 	}
 	test()
-	// Trusting cSelf
-	TrustIdentityProviders(cSelf)
-	m[cSelf] = true
-	test()
 	// Trusting cBlessed should cause cProvider to be trusted
 	TrustIdentityProviders(cBlessed)
 	m[cProvider] = true
 	test()
-	// Trusting tBlessed should cause both tSelf and tProvider to be
-	// trusted (since tBlessed has both as identity providers)
-	TrustIdentityProviders(tBlessed)
-	m[tSelf] = true
-	m[tProvider] = true
+	// Trusting setID should cause both cProvider1 and cProvider2
+	// to be trusted.
+	TrustIdentityProviders(setID)
+	m[cProvider1] = true
+	m[cProvider2] = true
 	// Trusting a fake identity should be a no-op
 	TrustIdentityProviders(fake)
 	test()
diff --git a/runtimes/google/security/wire/methods.go b/runtimes/google/security/wire/methods.go
index a84ac24..0e7b9de 100644
--- a/runtimes/google/security/wire/methods.go
+++ b/runtimes/google/security/wire/methods.go
@@ -13,7 +13,6 @@
 	"math/big"
 	"strings"
 
-	"veyron/runtimes/google/security/keys"
 	"veyron2/security"
 	"veyron2/vom"
 )
@@ -125,7 +124,7 @@
 func (c *Caveat) Validate(ctx security.Context) error {
 	// TODO(ataly): Is checking that the localID matches the caveat's Service pattern
 	// the right choice here?
-	if c.Service != security.AllPrincipals && (ctx.LocalID() == nil || !ctx.LocalID().Match(security.PrincipalPattern(c.Service))) {
+	if c.Service != security.AllPrincipals && (ctx.LocalID() == nil || !ctx.LocalID().Match(c.Service)) {
 		return nil
 	}
 	cav, err := c.Decode()
@@ -176,7 +175,7 @@
 	return nil
 }
 
-func (c *Certificate) verifyIntegrity(issuerSignature Signature, key *ecdsa.PublicKey) bool {
+func (c *Certificate) verify(issuerSignature Signature, key *ecdsa.PublicKey) bool {
 	var r, s big.Int
 	return ecdsa.Verify(key, c.contentHash(issuerSignature), r.SetBytes(c.Signature.R), s.SetBytes(c.Signature.S))
 }
@@ -226,7 +225,7 @@
 		}
 		// TODO(ashankar, ataly): Do we worry about timing attacks by
 		// early exiting on invalid certificate?
-		if !c.verifyIntegrity(issuerSignature, verificationKey) {
+		if !c.verify(issuerSignature, verificationKey) {
 			return ErrNoIntegrity
 		}
 		if verificationKey, err = c.PublicKey.Decode(); err != nil {
@@ -237,167 +236,6 @@
 	return nil
 }
 
-// -- Helper methods on the wire format for the chain implementation of Identity --
-
-// contentHash returns a SHA256 hash of the contents of the blessing and the provided
-// public key.
-func (b *Blessing) contentHash(pubKey PublicKey) []byte {
-	h := sha256.New()
-	tmp := make([]byte, binary.MaxVarintLen64)
-	h.Write([]byte{byte(pubKey.Curve)})
-	WriteBytes(h, tmp, pubKey.XY)
-	WriteString(h, tmp, b.Name)
-	for _, cav := range b.Caveats {
-		WriteString(h, tmp, string(cav.Service))
-		WriteBytes(h, tmp, cav.Bytes)
-	}
-	return h.Sum(nil)
-}
-
-// Sign uses the provided private key to sign the contents of the Blessing along with
-// the provided public key. The private key typically belongs to the principal providing
-// the blessing and the public key to the principal being blessed.
-func (b *Blessing) Sign(pubKey PublicKey, key *ecdsa.PrivateKey) error {
-	r, s, err := ecdsa.Sign(rand.Reader, key, b.contentHash(pubKey))
-	if err != nil {
-		return err
-	}
-	b.Signature.R = r.Bytes()
-	b.Signature.S = s.Bytes()
-	return nil
-}
-
-func (b *Blessing) verifyIntegrity(pubKey PublicKey) bool {
-	var key *ecdsa.PublicKey
-	var err error
-	if b.Blessor == nil {
-		// This is a leaf blessing.
-		key, err = pubKey.Decode()
-	} else {
-		key, err = b.Blessor.PublicKey.Decode()
-	}
-	if err != nil {
-		return false
-	}
-	var r, s big.Int
-	return ecdsa.Verify(key, b.contentHash(pubKey), r.SetBytes(b.Signature.R), s.SetBytes(b.Signature.S))
-}
-
-// validateCaveats verifies if all caveats present on the blessing validate with
-// respect to the provided context.
-func (b *Blessing) validateCaveats(ctx security.Context) error {
-	for _, cav := range b.Caveats {
-		if err := cav.Validate(ctx); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// Names returns an array of blessing-chains and associated identity provider's
-// public key (i.e., the public key of the leaf blessing). More formally,
-//
-// names[i] is the list of names of all blessings on a path from a leaf
-// blessing (signed by providers[i]) to the public key of id.
-func (id *TreePublicID) Names() (names [][]string, providers []*ecdsa.PublicKey) {
-	for _, b := range id.Blessings {
-		if b.Blessor == nil {
-			// leaf blessing - id is an identity provider for this blessing.
-			names = append(names, []string{b.Name})
-			key, _ := id.PublicKey.Decode()
-			providers = append(providers, key)
-			continue
-		}
-		n2, p2 := b.Blessor.Names()
-		providers = append(providers, p2...)
-		for _, n := range n2 {
-			names = append(names, append(n, b.Name))
-		}
-	}
-	return
-}
-
-// ThirdPartyCaveats returns the set of third-party restrictions embedded a TreePublicID.
-// The resulting objects are wrapped in security.ServiceCaveat objects according to the
-// services they are bound to.
-func (id *TreePublicID) ThirdPartyCaveats() (thirdPartyCaveats []security.ServiceCaveat) {
-	for _, b := range id.Blessings {
-		thirdPartyCaveats = append(thirdPartyCaveats, DecodeThirdPartyCaveats(b.Caveats)...)
-		if b.Blessor != nil {
-			thirdPartyCaveats = append(thirdPartyCaveats, b.Blessor.ThirdPartyCaveats()...)
-		}
-	}
-	return
-}
-
-// VerifyIntegrity verifies that the TreePublicID has a valid blessing tree, i.e,
-// (1) each blessing on the tree has a signature that can be verified using the
-// public key specified in its child node, (2) the leaf blessing's signature can
-// be verified using the public key that is being blessed by it, and (3) all
-// blessing names are valid.
-func (id *TreePublicID) VerifyIntegrity() error {
-	if len(id.Blessings) == 0 {
-		return ErrNoIntegrity
-	}
-	for _, b := range id.Blessings {
-		if err := ValidateBlessingName(b.Name); err != nil {
-			return err
-		}
-		if !b.verifyIntegrity(id.PublicKey) {
-			return ErrNoIntegrity
-		}
-		// TODO(ashankar, ataly): Do we worry about timing attacks by
-		// early exiting on invalid blessing?
-		if b.Blessor == nil {
-			continue
-		}
-		if err := b.Blessor.VerifyIntegrity(); err != nil {
-			return ErrNoIntegrity
-		}
-	}
-	return nil
-}
-
-// Authorize returns a new TreePublicID with just those blessing chains from the existing
-// PublicID whose caveats validate with respect to the provided context and whose leaf
-// public key is trusted. This method assumes that the existing TreePublicID has
-// integrity (see VerifyIntegrity).
-func (id *TreePublicID) Authorize(ctx security.Context) *TreePublicID {
-	authorizedID := &TreePublicID{PublicKey: id.PublicKey}
-	for _, b := range id.Blessings {
-		if b.validateCaveats(ctx) != nil {
-			continue
-		}
-		bID := b.Blessor
-		if bID == nil {
-			// This is a leaf blessing.
-			key, err := id.PublicKey.Decode()
-			if err != nil {
-				continue
-			}
-			switch keys.LevelOfTrust(key, b.Name) {
-			case keys.Unknown, keys.Trusted:
-				// No-op
-			default:
-				// Mistrusted blessings are silently dropped.
-				continue
-			}
-		} else if bID = b.Blessor.Authorize(ctx); bID == nil {
-			continue
-		}
-		authorizedID.Blessings = append(authorizedID.Blessings, Blessing{
-			Blessor:   bID,
-			Name:      b.Name,
-			Caveats:   b.Caveats,
-			Signature: b.Signature,
-		})
-	}
-	if authorizedID.Blessings == nil {
-		return nil
-	}
-	return authorizedID
-}
-
 // ValidateBlessingName verifies if the provided name is fit to be the name of a blessing.
 func ValidateBlessingName(name string) error {
 	// TODO(ataly, ashankar): Define the list of reserved characters (such as  "*", "#",
diff --git a/runtimes/google/security/wire/wire.go b/runtimes/google/security/wire/wire.go
index d09cb8c..b672efe 100644
--- a/runtimes/google/security/wire/wire.go
+++ b/runtimes/google/security/wire/wire.go
@@ -10,9 +10,7 @@
 // that make up the public key.
 package wire
 
-import (
-	"veyron2/security"
-)
+import "veyron2/security"
 
 const (
 	keyCurveP256 keyCurve = 0
@@ -81,49 +79,7 @@
 // ChainPrivateID represents the chain implementation of PrivateIDs from veyron/runtimes/google/security.
 type ChainPrivateID struct {
 	// PublicID associated with the PrivateID.
-	PublicID *ChainPublicID
-	// Secret represents the secret integer that together with an ECDSA public key makes up the
-	// corresponding private key.
-	Secret []byte
-}
-
-// Blessing is a signed assertion binding a name to a public key under a certain set
-// of caveats. The aforesaid public key is also called the "public key being blessed".
-// The issuer of a blessing is the principal that possesses the private key
-// under which the Blessing was signed. The PublicID of the issuer is also linked to
-// from the blessing.
-type Blessing struct {
-	// Blessor is the PublicID of the issuer of the blessing. It is nil if the blessing
-	// is self-signed, i.e, the public key being blessed and the private key signing
-	// the blessing correspond.
-	Blessor *TreePublicID
-	// Name specified in the blessing, e.g., Alice, Bob. Name must not have the
-	// characters "/" or "#".
-	Name string
-	// Caveats under which the blessing is valid.
-	Caveats []Caveat
-	// Signature of the contents of the blessing along with the public key being
-	// blessed.
-	Signature Signature
-}
-
-// TreePublicID represents the tree implementation of PublicIDs from veyron/runtimes/google/security.
-// It consists of a public key and a list of blessings binding different names to the public key.
-// For each blessing, the blesser's PublicID (which is linked to from the blessing) may in turn
-// have blessings of its own thus resulting in a tree of blessings. The blessings at the leaves
-// of the tree are "self signed". This blessing tree effectively binds a tree of names to the
-// PublicID depending on which blessings are valid.
-type TreePublicID struct {
-	// PublicKey is the ECDSA public key associated with the PublicID.
-	PublicKey PublicKey
-	// Blessings is the list of blessings for the aforesaid public key.
-	Blessings []Blessing
-}
-
-// TreePrivateID represents the tree implementation of PrivateIDs from veyron/runtimes/google/security.
-type TreePrivateID struct {
-	// PublicID associated with the PrivateID.
-	PublicID *TreePublicID
+	PublicID ChainPublicID
 	// Secret represents the secret integer that together with an ECDSA public key makes up the
 	// corresponding private key.
 	Secret []byte