veyron/runtimes/google/security: replace private key with a generic Signer.

The goal here is to abstract the signing operation so that it can be performed
by agents that don't necessarily want to expose their private keys (e.g.,
ssh-agent, android KeyStore).

Change-Id: Ic118aa006f3bf121f92998392c3a6a21babad599
diff --git a/lib/testutil/security/util.go b/lib/testutil/security/util.go
index f2a4214..ddd65e5 100644
--- a/lib/testutil/security/util.go
+++ b/lib/testutil/security/util.go
@@ -18,7 +18,7 @@
 // under the provided name. This function is meant to be used for testing purposes only,
 // it panics if there is an error.
 func NewBlessedIdentity(blesser security.PrivateID, name string) security.PrivateID {
-	id, err := isecurity.NewPrivateID("test")
+	id, err := isecurity.NewPrivateID("test", nil)
 	if err != nil {
 		panic(err)
 	}
diff --git a/runtimes/google/ipc/stream/manager/manager_test.go b/runtimes/google/ipc/stream/manager/manager_test.go
index 2e02ffb..84a78ee 100644
--- a/runtimes/google/ipc/stream/manager/manager_test.go
+++ b/runtimes/google/ipc/stream/manager/manager_test.go
@@ -24,7 +24,7 @@
 )
 
 func newID(name string) security.PrivateID {
-	id, err := isecurity.NewPrivateID(name)
+	id, err := isecurity.NewPrivateID(name, nil)
 	if err != nil {
 		panic(err)
 	}
diff --git a/runtimes/google/ipc/stream/proxy/proxy_test.go b/runtimes/google/ipc/stream/proxy/proxy_test.go
index 7b3e1dd..c5ccf58 100644
--- a/runtimes/google/ipc/stream/proxy/proxy_test.go
+++ b/runtimes/google/ipc/stream/proxy/proxy_test.go
@@ -20,7 +20,7 @@
 )
 
 func newID(name string) security.PrivateID {
-	id, err := isecurity.NewPrivateID(name)
+	id, err := isecurity.NewPrivateID(name, nil)
 	if err != nil {
 		panic(err)
 	}
diff --git a/runtimes/google/ipc/stream/vc/init.go b/runtimes/google/ipc/stream/vc/init.go
index a801353..261df0d 100644
--- a/runtimes/google/ipc/stream/vc/init.go
+++ b/runtimes/google/ipc/stream/vc/init.go
@@ -11,7 +11,7 @@
 
 func init() {
 	var err error
-	if anonymousID, err = isecurity.NewPrivateID("anonymous"); err != nil {
+	if anonymousID, err = isecurity.NewPrivateID("anonymous", nil); err != nil {
 		vlog.Fatalf("could create anonymousID for IPCs: %s", err)
 	}
 }
diff --git a/runtimes/google/ipc/stream/vc/listener_test.go b/runtimes/google/ipc/stream/vc/listener_test.go
index a621b97..80c52b4 100644
--- a/runtimes/google/ipc/stream/vc/listener_test.go
+++ b/runtimes/google/ipc/stream/vc/listener_test.go
@@ -16,7 +16,7 @@
 type noopFlow struct{}
 
 func newID(name string) security.PrivateID {
-	id, err := isecurity.NewPrivateID(name)
+	id, err := isecurity.NewPrivateID(name, nil)
 	if err != nil {
 		panic(err)
 	}
diff --git a/runtimes/google/ipc/stream/vc/vc_test.go b/runtimes/google/ipc/stream/vc/vc_test.go
index 3acd6fb..2cd770e 100644
--- a/runtimes/google/ipc/stream/vc/vc_test.go
+++ b/runtimes/google/ipc/stream/vc/vc_test.go
@@ -43,7 +43,7 @@
 )
 
 func newID(name string) security.PrivateID {
-	id, err := isecurity.NewPrivateID(name)
+	id, err := isecurity.NewPrivateID(name, nil)
 	if err != nil {
 		panic(err)
 	}
diff --git a/runtimes/google/ipc/stream/vif/vif_test.go b/runtimes/google/ipc/stream/vif/vif_test.go
index a743542..769a90d 100644
--- a/runtimes/google/ipc/stream/vif/vif_test.go
+++ b/runtimes/google/ipc/stream/vif/vif_test.go
@@ -26,7 +26,7 @@
 )
 
 func newLocalID(name string) vc.LocalID {
-	id, err := isecurity.NewPrivateID(name)
+	id, err := isecurity.NewPrivateID(name, nil)
 	if err != nil {
 		panic(err)
 	}
diff --git a/runtimes/google/ipc/testutil_test.go b/runtimes/google/ipc/testutil_test.go
index f990ca7..2768b0c 100644
--- a/runtimes/google/ipc/testutil_test.go
+++ b/runtimes/google/ipc/testutil_test.go
@@ -42,7 +42,7 @@
 }
 
 func newID(name string) security.PrivateID {
-	id, err := isecurity.NewPrivateID(name)
+	id, err := isecurity.NewPrivateID(name, nil)
 	if err != nil {
 		panic(err)
 	}
diff --git a/runtimes/google/rt/ipc_test.go b/runtimes/google/rt/ipc_test.go
index 1822541..85c49fd 100644
--- a/runtimes/google/rt/ipc_test.go
+++ b/runtimes/google/rt/ipc_test.go
@@ -26,7 +26,7 @@
 type S []string
 
 func newID(name string) security.PrivateID {
-	id, err := isecurity.NewPrivateID(name)
+	id, err := isecurity.NewPrivateID(name, nil)
 	if err != nil {
 		panic(err)
 	}
diff --git a/runtimes/google/rt/security.go b/runtimes/google/rt/security.go
index 466cb8a..5326b2c 100644
--- a/runtimes/google/rt/security.go
+++ b/runtimes/google/rt/security.go
@@ -12,7 +12,7 @@
 )
 
 func (rt *vrt) NewIdentity(name string) (security.PrivateID, error) {
-	return isecurity.NewPrivateID(name)
+	return isecurity.NewPrivateID(name, nil)
 }
 
 func (rt *vrt) Identity() security.PrivateID {
diff --git a/runtimes/google/security/identity.go b/runtimes/google/security/identity.go
index 857408c..a4765ee 100644
--- a/runtimes/google/security/identity.go
+++ b/runtimes/google/security/identity.go
@@ -2,9 +2,13 @@
 
 import "veyron2/security"
 
-// NewPrivateID returns a new PrivateID containing a freshly generated
-// private key, and a single self-signed certificate specifying the provided
-// name and the public key corresponding to the generated private key.
-func NewPrivateID(name string) (security.PrivateID, error) {
-	return newChainPrivateID(name)
+// NewPrivateID returns a new PrivateID that uses the provided Signer to generate
+// signatures.  The returned PrivateID additionaly contains a single self-signed
+// certificate with the given name.
+//
+// If a nil signer is provided, this method will generate a new public/private key pair
+// and use a system-default signer, which stores the private key in the clear in the memory
+// of the running process.
+func NewPrivateID(name string, signer security.Signer) (security.PrivateID, error) {
+	return newChainPrivateID(name, signer)
 }
diff --git a/runtimes/google/security/identity_chain.go b/runtimes/google/security/identity_chain.go
index 2c3c4d8..87f55ac 100644
--- a/runtimes/google/security/identity_chain.go
+++ b/runtimes/google/security/identity_chain.go
@@ -116,24 +116,20 @@
 
 // chainPrivateID implements security.PrivateID
 type chainPrivateID struct {
+	security.Signer
 	publicID   *chainPublicID
-	privateKey *ecdsa.PrivateKey
+	privateKey *ecdsa.PrivateKey // can be nil
 }
 
 func (id *chainPrivateID) PublicID() security.PublicID { return id.publicID }
 
-func (id *chainPrivateID) Sign(message []byte) (sig security.Signature, err error) {
-	r, s, err := ecdsa.Sign(rand.Reader, id.privateKey, message)
-	if err != nil {
-		return
-	}
-	sig.R, sig.S = r.Bytes(), s.Bytes()
-	return
-}
-
 func (id *chainPrivateID) String() string { return fmt.Sprintf("PrivateID:%v", id.publicID) }
 
 func (id *chainPrivateID) VomEncode() (*wire.ChainPrivateID, error) {
+	if id.privateKey == nil {
+		// TODO(ataly): Figure out a clean way to serialize Signers.
+		return nil, fmt.Errorf("cannot vom-encode a chainPrivateID that doesn't have access to a private key")
+	}
 	pub, err := id.publicID.VomEncode()
 	if err != nil {
 		return nil, err
@@ -150,6 +146,7 @@
 		PublicKey: *id.publicID.publicKey,
 		D:         new(big.Int).SetBytes(w.Secret),
 	}
+	id.Signer = NewClearSigner(id.privateKey)
 	return nil
 }
 
@@ -172,11 +169,11 @@
 	if cert.Caveats, err = wire.EncodeCaveats(caveats); err != nil {
 		return nil, err
 	}
-	vomID, err := id.VomEncode()
+	vomPubID, err := id.publicID.VomEncode()
 	if err != nil {
 		return nil, err
 	}
-	if err := cert.Sign(vomID); err != nil {
+	if err := cert.Sign(id, vomPubID); err != nil {
 		return nil, err
 	}
 	w := &wire.ChainPublicID{
@@ -197,6 +194,7 @@
 	switch p := pub.(type) {
 	case *chainPublicID:
 		return &chainPrivateID{
+			Signer:     id.Signer,
 			publicID:   p,
 			privateKey: id.privateKey,
 		}, nil
@@ -218,35 +216,47 @@
 	return caveat.NewPublicKeyDischarge(id, cav, ctx, duration, dischargeCaveats)
 }
 
-// newChainPrivateID returns a new PrivateID containing a freshly generated
-// private key, and a single self-signed certificate specifying the provided
-// name and the public key corresponding to the generated private key.
-func newChainPrivateID(name string) (security.PrivateID, error) {
+// newChainPrivateID returns a new PrivateID that uses the provided Signer to generate
+// signatures.  The returned PrivateID additionaly contains a single self-signed
+// certificate with the given name.
+//
+// If a nil signer is provided, this method will generate a new public/private key pair
+// and use a system-default signer, which stores the private key in the clear in the memory
+// of the running process.
+func newChainPrivateID(name string, signer security.Signer) (security.PrivateID, error) {
 	if err := wire.ValidateBlessingName(name); err != nil {
 		return nil, err
 	}
-	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
-	if err != nil {
-		return nil, err
+	var privKey *ecdsa.PrivateKey
+	if signer == nil {
+		var err error
+		privKey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+		if err != nil {
+			return nil, err
+		}
+		signer = NewClearSigner(privKey)
 	}
+
 	id := &chainPrivateID{
+		Signer: signer,
 		publicID: &chainPublicID{
 			certificates: []wire.Certificate{{Name: name}},
 			name:         name,
-			publicKey:    &key.PublicKey,
-			rootKey:      &key.PublicKey,
+			publicKey:    signer.PublicKey(),
+			rootKey:      signer.PublicKey(),
 		},
-		privateKey: key,
+		privateKey: privKey,
 	}
+	// Self-sign the (single) certificate.
 	cert := &id.publicID.certificates[0]
-	if err := cert.PublicKey.Encode(&key.PublicKey); err != nil {
+	if err := cert.PublicKey.Encode(signer.PublicKey()); err != nil {
 		return nil, err
 	}
-	vomID, err := id.VomEncode()
+	vomPubID, err := id.publicID.VomEncode()
 	if err != nil {
 		return nil, err
 	}
-	if err := cert.Sign(vomID); err != nil {
+	if err := cert.Sign(id, vomPubID); err != nil {
 		return nil, err
 	}
 	return id, nil
diff --git a/runtimes/google/security/identity_set.go b/runtimes/google/security/identity_set.go
index 0b2bd89..1c00e00 100644
--- a/runtimes/google/security/identity_set.go
+++ b/runtimes/google/security/identity_set.go
@@ -167,6 +167,8 @@
 
 func (s setPrivateID) Sign(message []byte) (security.Signature, error) { return s[0].Sign(message) }
 
+func (s setPrivateID) PublicKey() *ecdsa.PublicKey { return s[0].PublicKey() }
+
 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 {
diff --git a/runtimes/google/security/identity_test.go b/runtimes/google/security/identity_test.go
index 18b43bf..890325c 100644
--- a/runtimes/google/security/identity_test.go
+++ b/runtimes/google/security/identity_test.go
@@ -32,7 +32,7 @@
 		{"google/alice/bob", "invalid blessing name"},
 	}
 	for _, d := range testdata {
-		if _, err := NewPrivateID(d.name); !matchesErrorPattern(err, d.err) {
+		if _, err := NewPrivateID(d.name, nil); !matchesErrorPattern(err, d.err) {
 			t.Errorf("NewPrivateID(%q): got: %s, want to match: %s", d.name, err, d.err)
 		}
 	}
diff --git a/runtimes/google/security/performance_test.go b/runtimes/google/security/performance_test.go
index 06cbe5e..4f9fd76 100644
--- a/runtimes/google/security/performance_test.go
+++ b/runtimes/google/security/performance_test.go
@@ -58,7 +58,7 @@
 
 func BenchmarkNewChain(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		if _, err := newChainPrivateID("X"); err != nil {
+		if _, err := newChainPrivateID("X", nil); err != nil {
 			b.Fatalf("Failed newChainPrivateID #%d: %v", i, err)
 		}
 
diff --git a/runtimes/google/security/signer.go b/runtimes/google/security/signer.go
new file mode 100644
index 0000000..9d96754
--- /dev/null
+++ b/runtimes/google/security/signer.go
@@ -0,0 +1,31 @@
+package security
+
+import (
+	"crypto/ecdsa"
+	"crypto/rand"
+
+	"veyron2/security"
+)
+
+// NewClearSigner creates a Signer that uses the provided private key to sign messages.
+// This private key is kept in the clear in the memory of the running process.
+func NewClearSigner(key *ecdsa.PrivateKey) security.Signer {
+	return &clearSigner{key}
+}
+
+type clearSigner struct {
+	key *ecdsa.PrivateKey
+}
+
+func (c *clearSigner) Sign(message []byte) (sig security.Signature, err error) {
+	r, s, err := ecdsa.Sign(rand.Reader, c.key, message)
+	if err != nil {
+		return
+	}
+	sig.R, sig.S = r.Bytes(), s.Bytes()
+	return
+}
+
+func (c *clearSigner) PublicKey() *ecdsa.PublicKey {
+	return &c.key.PublicKey
+}
diff --git a/runtimes/google/security/signer_test.go b/runtimes/google/security/signer_test.go
new file mode 100644
index 0000000..cd81097
--- /dev/null
+++ b/runtimes/google/security/signer_test.go
@@ -0,0 +1,36 @@
+package security
+
+import (
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/sha256"
+	"math/big"
+	"testing"
+)
+
+func TestSigner(t *testing.T) {
+	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		t.Fatalf("Couldn't generate ECDSA private key: %v", err)
+	}
+	signer := NewClearSigner(key)
+	testdata := [][]byte{
+		nil,
+		[]byte{},
+		[]byte(""),
+		[]byte("withorwithoutyou"),
+		[]byte("wherethestreetshavenoname"),
+	}
+	for _, d := range testdata {
+		hash := sha256.Sum256(d)
+		sig, err := signer.Sign(hash[:])
+		if err != nil {
+			t.Errorf("Sign(%q) returned err: %q, expected success.", d, err)
+			continue
+		}
+		if !ecdsa.Verify(signer.PublicKey(), hash[:], new(big.Int).SetBytes(sig.R), new(big.Int).SetBytes(sig.S)) {
+			t.Errorf("Sign(%q) signature couldn't be verified.", d)
+		}
+	}
+}
diff --git a/runtimes/google/security/util_test.go b/runtimes/google/security/util_test.go
index f1f76fc..4c495c9 100644
--- a/runtimes/google/security/util_test.go
+++ b/runtimes/google/security/util_test.go
@@ -50,7 +50,7 @@
 }
 
 func newChain(name string) security.PrivateID {
-	id, err := newChainPrivateID(name)
+	id, err := newChainPrivateID(name, nil)
 	if err != nil {
 		panic(err)
 	}