Correctly decode PEM files in Go.

I had a misunderstanding of what a PEM encoding of a public or private
key was. This bug was not detected until I started working on the
interaction between the C++ code and the Go code. Previously
I had a unit test in which I was incorrectly creating a PEM encoding
and then incorrectly parsing the PEM encoding that I created.

Now I have a unit test in which I use a literal PEM string that was
created by the C++ code and so I can test that the new implementation
of PEM decoding in GO is correct. I don't implement PEM encoding in GO as
we have no need for it.

Change-Id: I21d60d55049d49b639381840285b6011a120ded3
diff --git a/shuffler/src/util/elliptic_util.go b/shuffler/src/util/elliptic_util.go
index 1f95c3e..e4cfbff 100644
--- a/shuffler/src/util/elliptic_util.go
+++ b/shuffler/src/util/elliptic_util.go
@@ -15,7 +15,10 @@
 package util
 
 import (
+	"crypto/ecdsa"
 	"crypto/elliptic"
+	"crypto/x509"
+	"encoding/pem"
 	"fmt"
 	"math/big"
 )
@@ -160,3 +163,54 @@
 	copy(fieldElementPadded[ecFieldElementSize-len(fieldElement):], fieldElement)
 	return fieldElementPadded, nil
 }
+
+// ParseECPrivateKeyPem parses a PEM encoded private EC key. The PEM should contain
+// an unencrypted PKCS#8 (see RFC 5208) private key of type ECDSA (see RFC 5480).
+func ParseECPrivateKeyPem(privateKeyPem string) (privateKey []byte, err error) {
+	block, _ := pem.Decode([]byte(privateKeyPem))
+	if block == nil {
+		err = fmt.Errorf("Private key PEM could not be parsed.")
+		return
+	}
+	result, err2 := x509.ParsePKCS8PrivateKey(block.Bytes)
+	if err2 != nil {
+		err = err2
+		return
+	}
+	ecPrivateKey, ok := result.(*ecdsa.PrivateKey)
+	if !ok {
+		err = fmt.Errorf("The private key PEM file did not contain an EC private key but rather a %T.", result)
+		return
+	}
+	privateKey, err = padFieldElement(ecPrivateKey.D.Bytes())
+	if err != nil {
+		err = fmt.Errorf("Cannot parse hybrid cipher private key PEM: %d.", err)
+		return
+	}
+	return
+}
+
+// ParseECPublicKeyPem parses a PEM encoded public EC key. The PEM should contain a
+// PKCS#8 public key of type ECDSA.
+func ParseECPublicKeyPem(publicKeyPEM string) (publicKey []byte, err error) {
+	block, _ := pem.Decode([]byte(publicKeyPEM))
+	if block == nil {
+		err = fmt.Errorf("Public key PEM could not be parsed.")
+		return
+	}
+	result, err2 := x509.ParsePKIXPublicKey(block.Bytes)
+	if err2 != nil {
+		err = err2
+		return
+	}
+	ecPublicKey, ok := result.(*ecdsa.PublicKey)
+	if !ok {
+		err = fmt.Errorf("The public key PEM file did not contain an EC public key but rather a %T.", result)
+		return
+	}
+	if ecPublicKey.Curve != ellipticCurve {
+		err = fmt.Errorf("The public key PEM contained an EC public key for the wrong curve: %v", ecPublicKey.Curve)
+		return
+	}
+	return elliptic.Marshal(ecPublicKey.Curve, ecPublicKey.X, ecPublicKey.Y), nil
+}
diff --git a/shuffler/src/util/encrypted_message_util.go b/shuffler/src/util/encrypted_message_util.go
index d9dfeab..66cb0ca 100644
--- a/shuffler/src/util/encrypted_message_util.go
+++ b/shuffler/src/util/encrypted_message_util.go
@@ -15,8 +15,6 @@
 package util
 
 import (
-	"encoding/pem"
-
 	"github.com/golang/glog"
 	"github.com/golang/protobuf/proto"
 	"google.golang.org/grpc"
@@ -62,12 +60,11 @@
 	scheme cobalt.EncryptedMessage_EncryptionScheme) *EncryptedMessageMaker {
 	var cipher *HybridCipher
 	if scheme == cobalt.EncryptedMessage_HYBRID_ECDH_V1 {
-		block, _ := pem.Decode([]byte(publicKeyPem))
-		if block == nil {
-			glog.Errorln("Failed to decode publicKeyPem.")
+		publicKey, err := ParseECPublicKeyPem(publicKeyPem)
+		if err != nil {
+			glog.Errorf("Failed to decode public key PEM: %v.", err)
 			return nil
 		}
-		publicKey := block.Bytes
 		cipher = NewHybridCipher(nil, publicKey)
 		if cipher == nil {
 			glog.Errorln("Failed to construct a HybridCipher.")
@@ -136,11 +133,18 @@
 // key.
 func NewMessageDecrypter(privateKeyPem string) *MessageDecrypter {
 	var hybridCipher *HybridCipher
-	block, _ := pem.Decode([]byte(privateKeyPem))
-	if block == nil {
-		glog.V(1).Infoln("Failed to decode privateKeyPem.")
+	if privateKeyPem == "" {
+		// We use glog.V() here becuase we don't want to print an error message if the
+		// Shuffler is being used in a test without encryption.
+		glog.V(3).Infoln("No privateKeyPem provided. Shuffler will not be able to decrypt EncryptedMessages.")
 	} else {
-		hybridCipher = NewHybridCipher(block.Bytes, nil)
+		privateKey, err := ParseECPrivateKeyPem(privateKeyPem)
+		if err != nil {
+			glog.Errorf("Failed to decode private key PEM: %v, Shuffler will not be able to decrypt EncryptedMessages.", err)
+		} else {
+			hybridCipher = NewHybridCipher(privateKey, nil)
+			glog.Infoln("Successfully parsed the private key PEM file.")
+		}
 	}
 	return &MessageDecrypter{
 		hybridCipher: hybridCipher,
@@ -179,6 +183,7 @@
 	if err = proto.Unmarshal(recoveredText, outMessage); err != nil {
 		return grpc.Errorf(codes.InvalidArgument, "Unable to unmarshal decrypted text: %v", err)
 	}
+	glog.V(4).Infoln("Decryption of Envelope succeeded.")
 	return nil
 
 }
diff --git a/shuffler/src/util/encrypted_message_util_test.go b/shuffler/src/util/encrypted_message_util_test.go
index d76b960..1af2796 100644
--- a/shuffler/src/util/encrypted_message_util_test.go
+++ b/shuffler/src/util/encrypted_message_util_test.go
@@ -15,13 +15,27 @@
 package util
 
 import (
-	"encoding/pem"
 	"reflect"
 	"testing"
 
 	"cobalt"
 )
 
+var privateKeyPem, publicKeyPem string
+
+func init() {
+	privateKeyPem = `-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg1kZxvT81qrRWg2Y8
+g/M7YNtiHaC14/fbevhy/hgXcByhRANCAASkbLO+7iLLaPayYIr3YVmY0jkbwalG
+sOB9Tf3R8TR7Ow43cHlGjX3HALV1z4Lxs1v2K13yeegBJF8lU88cdAqY
+-----END PRIVATE KEY-----`
+
+	publicKeyPem = `-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpGyzvu4iy2j2smCK92FZmNI5G8Gp
+RrDgfU390fE0ezsON3B5Ro19xwC1dc+C8bNb9itd8nnoASRfJVPPHHQKmA==
+-----END PUBLIC KEY-----`
+}
+
 // Makes and returns an Envelope with some non-default values so that we can recognized
 // when we correctly encrypt and decrypt it.
 func MakeTestEnvelope() cobalt.Envelope {
@@ -43,6 +57,9 @@
 func TestNoEncryption(t *testing.T) {
 	// Make an EncryptedMessageMaker
 	encryptedMessageMaker := NewEncryptedMessageMaker("", cobalt.EncryptedMessage_NONE)
+	if encryptedMessageMaker == nil {
+		t.Fatal("Failed to create EncryptedMessageMaker")
+	}
 
 	// Make an Envelope with some non-default values so we can recognize it.
 	envelope1 := MakeTestEnvelope()
@@ -72,24 +89,11 @@
 // Tests that a MessageDecrypter that is constructed with a valid private key
 // can decrypt messages that use the HYBRID_ECDH_V1 scheme.
 func TestHybridEncryption(t *testing.T) {
-	// Generate a key pair.
-	privateKey, publicKey, _, _, err := generateECKey()
-	if err != nil {
-		t.Errorf("%v", err)
-	}
-
-	// Make privateKeyPem
-	block := pem.Block{
-		Bytes: privateKey,
-	}
-	privateKeyPem := string(pem.EncodeToMemory(&block))
-
-	// Make publicKeyPem
-	block.Bytes = publicKey
-	publicKeyPem := string(pem.EncodeToMemory(&block))
-
 	// Make an EncryptedMessageMaker
 	encryptedMessageMaker := NewEncryptedMessageMaker(publicKeyPem, cobalt.EncryptedMessage_HYBRID_ECDH_V1)
+	if encryptedMessageMaker == nil {
+		t.Fatal("Failed to create EncryptedMessageMaker")
+	}
 
 	// Make an Envelope with some non-default values so we can recognize it.
 	envelope1 := MakeTestEnvelope()
@@ -119,20 +123,11 @@
 // Tests that a MessageDecrypter that is constructed with an invalid private key
 // can fail gracefully.
 func TestFailedHybridEncryption(t *testing.T) {
-	// Generate a key pair.
-	_, publicKey, _, _, err := generateECKey()
-	if err != nil {
-		t.Errorf("%v", err)
-	}
-
-	// Make publicKeyPem
-	block := pem.Block{
-		Bytes: publicKey,
-	}
-	publicKeyPem := string(pem.EncodeToMemory(&block))
-
 	// Make an EncryptedMessageMaker
 	encryptedMessageMaker := NewEncryptedMessageMaker(publicKeyPem, cobalt.EncryptedMessage_HYBRID_ECDH_V1)
+	if encryptedMessageMaker == nil {
+		t.Fatal("Failed to create EncryptedMessageMaker")
+	}
 
 	// Make an Envelope with some non-default values so we can recognize it.
 	envelope1 := MakeTestEnvelope()
@@ -157,24 +152,11 @@
 // Tests that a MessageDecrypter that is constructed with a valid private key
 // and is given a corrupted ciphertext can fail gracefully.
 func TestCorruptedHybridEncryption(t *testing.T) {
-	// Generate a key pair.
-	privateKey, publicKey, _, _, err := generateECKey()
-	if err != nil {
-		t.Errorf("%v", err)
-	}
-
-	// Make privateKeyPem
-	block := pem.Block{
-		Bytes: privateKey,
-	}
-	privateKeyPem := string(pem.EncodeToMemory(&block))
-
-	// Make publicKeyPem
-	block.Bytes = publicKey
-	publicKeyPem := string(pem.EncodeToMemory(&block))
-
 	// Make an EncryptedMessageMaker
 	encryptedMessageMaker := NewEncryptedMessageMaker(publicKeyPem, cobalt.EncryptedMessage_HYBRID_ECDH_V1)
+	if encryptedMessageMaker == nil {
+		t.Fatal("Failed to create EncryptedMessageMaker")
+	}
 
 	// Make an Envelope with some non-default values so we can recognize it.
 	envelope1 := MakeTestEnvelope()