"veyron/security": Load/Save private keys in PEM format
This CL adds methods to load and save ECDSA private keys in
PEM format (with ASN.1, DER data)
Change-Id: I12de7439655273b2000cfaf6cd082ca74256eae6
diff --git a/security/util.go b/security/util.go
index 0a8f9bb..8af97f2 100644
--- a/security/util.go
+++ b/security/util.go
@@ -2,15 +2,22 @@
import (
"bytes"
+ "crypto/ecdsa"
+ "crypto/x509"
"encoding/base64"
"encoding/json"
+ "encoding/pem"
+ "errors"
"fmt"
"io"
+ "io/ioutil"
"veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/vom"
)
+const ecPrivateKeyPEMType = "EC PRIVATE KEY"
+
var nullACL security.ACL
// OpenACL creates an ACL that grants access to all principals.
@@ -20,6 +27,47 @@
return acl
}
+// LoadPEMKey loads a key from 'r', assuming that it was
+// saved using SavePEMKey.
+func LoadPEMKey(r io.Reader) (interface{}, error) {
+ pemKeyBytes, err := ioutil.ReadAll(r)
+ if err != nil {
+ return nil, err
+ }
+
+ pemKey, _ := pem.Decode(pemKeyBytes)
+ if pemKey == nil {
+ return nil, errors.New("no PEM key block read")
+ }
+
+ switch pemKey.Type {
+ case ecPrivateKeyPEMType:
+ return x509.ParseECPrivateKey(pemKey.Bytes)
+ }
+ return nil, fmt.Errorf("PEM key block has an unrecognized type: %v", pemKey.Type)
+}
+
+// SavePEMKey marshals 'key' and saves the bytes to 'w' in PEM format.
+//
+// For example, if key is an ECDSA private key, it will be marshaled
+// in ASN.1, DER format and then written in a PEM block.
+func SavePEMKey(w io.Writer, key interface{}) error {
+ pemKey := &pem.Block{
+ Type: ecPrivateKeyPEMType,
+ }
+
+ switch k := key.(type) {
+ case *ecdsa.PrivateKey:
+ var err error
+ if pemKey.Bytes, err = x509.MarshalECPrivateKey(k); err != nil {
+ return err
+ }
+ default:
+ return fmt.Errorf("key of type %T cannot be saved", k)
+ }
+ return pem.Encode(w, pemKey)
+}
+
// LoadIdentity reads a PrivateID from r, assuming that it was written using
// SaveIdentity.
//