veyron.io/veyron/veyron/security: create principal from signer.

Add methods that create in-memory and persistent principals from an
existing signer.

We need this functionality as in Android we store the private key inside
a hardware token and pass a signer into Go.

Change-Id: I5575ec92533ded5dae22219ba39e9a8195b8ee4f
diff --git a/security/principal.go b/security/principal.go
index c92430d..a351f00 100644
--- a/security/principal.go
+++ b/security/principal.go
@@ -23,6 +23,27 @@
 	return security.CreatePrincipal(security.NewInMemoryECDSASigner(priv), newInMemoryBlessingStore(pub), newInMemoryBlessingRoots())
 }
 
+// NewPrincipalFromSigner creates a principal using the provided signer, storing its
+// BlessingRoots and BlessingStore in memory.
+func NewPrincipalFromSigner(signer security.Signer) (security.Principal, error) {
+	return security.CreatePrincipal(signer, newInMemoryBlessingStore(signer.PublicKey()), newInMemoryBlessingRoots())
+}
+
+// NewPersistentPrincipalForSigner creates a new principal using the provided Signer and a
+// partial state (i.e., BlessingRoots, BlessingStore) that is read from the provided directory 'dir'.
+// Changes to the partial state are persisted and commited to the same directory; the provided
+// signer isn't persisted: the caller is expected to persist it separately or use the
+// {Load,Create}PersistentPrincipal() methods instead.
+//
+// If the directory does not contain any partial state, new partial state instances are created
+// and subsequently commited to 'dir'.  If the directory does not exist, it is created.
+func NewPersistentPrincipalFromSigner(signer security.Signer, dir string) (security.Principal, error) {
+	if err := mkDir(dir); err != nil {
+		return nil, err
+	}
+	return newPersistentPrincipalFromSigner(signer, dir)
+}
+
 // LoadPersistentPrincipal reads state for a principal (private key, BlessingRoots, BlessingStore)
 // from the provided directory 'dir' and commits all state changes to the same directory.
 // If private key file does not exist then an error 'err' is returned such that os.IsNotExist(err) is true.
@@ -33,27 +54,49 @@
 	if err != nil {
 		return nil, err
 	}
-	return newPersistentPrincipalFromKey(key, dir)
+	return newPersistentPrincipalFromSigner(security.NewInMemoryECDSASigner(key), dir)
 }
 
 // CreatePersistentPrincipal creates a new principal (private key, BlessingRoots, BlessingStore) and commits all state changes to the provided directory.
 // The generated private key is serialized and saved encrypted if the 'passphrase' is non-nil, and unencrypted otherwise.
 // If the directory has any preexisting key, CreatePersistentPrincipal will return an error.
 // The specified directory may not exist, in which case it gets created by this function.
-func CreatePersistentPrincipal(dir string, passphrase []byte) (principal security.Principal, err error) {
-	if finfo, err := os.Stat(dir); err == nil {
-		if !finfo.IsDir() {
-			return nil, fmt.Errorf("%q is not a directory", dir)
-		}
-	} else if err := os.MkdirAll(dir, 0700); err != nil {
-		return nil, fmt.Errorf("failed to create %q: %v", dir, err)
+func CreatePersistentPrincipal(dir string, passphrase []byte) (security.Principal, error) {
+	if err := mkDir(dir); err != nil {
+		return nil, err
 	}
 	key, err := initKey(dir, nil)
 	if err != nil {
 		return nil, fmt.Errorf("could not initialize private key from credentials directory %v: %v", dir, err)
 	}
-	p, err := newPersistentPrincipalFromKey(key, dir)
-	return p, err
+	return newPersistentPrincipalFromSigner(security.NewInMemoryECDSASigner(key), dir)
+}
+
+func newPersistentPrincipalFromSigner(signer security.Signer, dir string) (security.Principal, error) {
+	serializationSigner, err := security.CreatePrincipal(signer, nil, nil)
+	if err != nil {
+		return nil, fmt.Errorf("failed to create serialization.Signer: %v", err)
+	}
+	roots, err := newPersistingBlessingRoots(dir, serializationSigner)
+	if err != nil {
+		return nil, fmt.Errorf("failed to load BlessingRoots from %q: %v", dir, err)
+	}
+	store, err := newPersistingBlessingStore(dir, serializationSigner)
+	if err != nil {
+		return nil, fmt.Errorf("failed to load BlessingStore from %q: %v", dir, err)
+	}
+	return security.CreatePrincipal(signer, store, roots)
+}
+
+func mkDir(dir string) error {
+	if finfo, err := os.Stat(dir); err == nil {
+		if !finfo.IsDir() {
+			return fmt.Errorf("%q is not a directory", dir)
+		}
+	} else if err := os.MkdirAll(dir, 0700); err != nil {
+		return fmt.Errorf("failed to create %q: %v", dir, err)
+	}
+	return nil
 }
 
 func loadKeyFromDir(dir string, passphrase []byte) (*ecdsa.PrivateKey, error) {
@@ -70,22 +113,6 @@
 	return key.(*ecdsa.PrivateKey), nil
 }
 
-func newPersistentPrincipalFromKey(key *ecdsa.PrivateKey, dir string) (security.Principal, error) {
-	signer, err := security.CreatePrincipal(security.NewInMemoryECDSASigner(key), nil, nil)
-	if err != nil {
-		return nil, fmt.Errorf("failed to create serialization.Signer: %v", err)
-	}
-	roots, err := newPersistingBlessingRoots(dir, signer)
-	if err != nil {
-		return nil, fmt.Errorf("failed to load BlessingRoots from %q: %v", dir, err)
-	}
-	store, err := newPersistingBlessingStore(dir, signer)
-	if err != nil {
-		return nil, fmt.Errorf("failed to load BlessingStore from %q: %v", dir, err)
-	}
-	return security.CreatePrincipal(security.NewInMemoryECDSASigner(key), store, roots)
-}
-
 // newKey generates an ECDSA (public, private) key pair.
 func newKey() (security.PublicKey, *ecdsa.PrivateKey, error) {
 	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)