veyron/security/agent: Added encryption to agent and option not
to encrypt.

* Password will only be requested when the PEM Block is not encrypted.
* Next step is to change the agent from a signer to a principal. Coming
  soon...

Change-Id: I811bb6af636d83243052465039192c7bfa307cc1
diff --git a/security/principal_test.go b/security/principal_test.go
index a8ad464..d2d18ce 100644
--- a/security/principal_test.go
+++ b/security/principal_test.go
@@ -1,38 +1,105 @@
 package security
 
 import (
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
 	"io/ioutil"
 	"os"
+	"path"
 	"testing"
 )
 
-func TestNewPersistentPrincipal(t *testing.T) {
+func TestLoadPersistentPrincipal(t *testing.T) {
+	// If the directory does not exist want os.IsNotExists.
+	_, err := LoadPersistentPrincipal("/tmp/fake/path/", nil)
+	if !os.IsNotExist(err) {
+		t.Errorf("invalid path should return does not exist error, instead got %v", err)
+	}
+	// If the key file exists and is unencrypted we should succeed.
+	dir := generatePEMFile(nil)
+	if _, err = LoadPersistentPrincipal(dir, nil); err != nil {
+		t.Errorf("unencrypted LoadPersistentPrincipal should have succeeded: %v", err)
+	}
+	os.RemoveAll(dir)
+
+	// If the private key file exists and is encrypted we should succeed with correct passphrase.
+	passphrase := []byte("passphrase")
+	incorrect_passphrase := []byte("incorrect_passphrase")
+	dir = generatePEMFile(passphrase)
+	if _, err = LoadPersistentPrincipal(dir, passphrase); err != nil {
+		t.Errorf("encrypted LoadPersistentPrincipal should have succeeded: %v", err)
+	}
+	// and fail with an incorrect passphrase.
+	if _, err = LoadPersistentPrincipal(dir, incorrect_passphrase); err == nil {
+		t.Errorf("encrypted LoadPersistentPrincipal with incorrect passphrase should fail")
+	}
+	// and return MissingPassphraseError if the passphrase is nil.
+	if _, err = LoadPersistentPrincipal(dir, nil); err != MissingPassphraseErr {
+		t.Errorf("encrypted LoadPersistentPrincipal with nil passphrase should return MissingPassphraseErr: %v", err)
+	}
+	os.RemoveAll(dir)
+}
+
+func TestCreatePersistentPrincipal(t *testing.T) {
+	tests := []struct {
+		Message, Passphrase []byte
+	}{
+		{[]byte("unencrypted"), nil},
+		{[]byte("encrypted"), []byte("passphrase")},
+	}
+	for _, test := range tests {
+		testCreatePersistentPrincipal(t, test.Message, test.Passphrase)
+	}
+}
+
+func testCreatePersistentPrincipal(t *testing.T, message, passphrase []byte) {
 	// Persistence of the BlessingRoots and BlessingStore objects is
 	// tested in other files. Here just test the persistence of the key.
-	dir, err := ioutil.TempDir("", "TestNewPersistentPrincipal")
+	dir, err := ioutil.TempDir("", "TestCreatePersistentPrincipal")
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer os.RemoveAll(dir)
 
-	p, existed, err := NewPersistentPrincipal(dir)
+	p, err := CreatePersistentPrincipal(dir, passphrase)
 	if err != nil {
 		t.Fatal(err)
 	}
-	if existed {
-		t.Fatalf("%q already has data", existed)
-	}
-	message := []byte("this is a test message")
 	sig, err := p.Sign(message)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	p2, _, err := NewPersistentPrincipal(dir)
+	p2, err := CreatePersistentPrincipal(dir, passphrase)
+	if err == nil {
+		t.Errorf("p2 CreatePersistentPrincipal should have failed")
+	}
+	p2, err = LoadPersistentPrincipal(dir, passphrase)
 	if err != nil {
 		t.Fatal(err)
 	}
-	if !sig.Verify(p2.PublicKey(), message) {
-		t.Errorf("p.PublicKey=%v, p2.PublicKey=%v", p.PublicKey(), p2.PublicKey())
+	if !sig.Verify(p.PublicKey(), message) {
+		t.Errorf("%s failed: p.PublicKey=%v, p2.PublicKey=%v", message, p.PublicKey(), p2.PublicKey())
 	}
 }
+
+func generatePEMFile(passphrase []byte) (dir string) {
+	dir, err := ioutil.TempDir("", "TestLoadPersistentPrincipal")
+	if err != nil {
+		panic(err)
+	}
+	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		panic(err)
+	}
+	f, err := os.Create(path.Join(dir, privateKeyFile))
+	if err != nil {
+		panic(err)
+	}
+	defer f.Close()
+	if err = savePEMKey(f, key, passphrase); err != nil {
+		panic(err)
+	}
+	return dir
+}