diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5e9c752..f83e590 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,15 @@
 # APC P15 Tool Changelog
 
+## [v1.1.0-b1] - 2024-07-09
+
+BETA: First effort to add support for EC key support for NMC3.
+
+This version also enables RSA 4,092 bit length. Code was updated
+so the NMC2 key+cert file is not generated when NMC2 is not
+supported. Log messages were also updated to signal user when
+a compatibility issue is present.
+
+
 ## [v1.0.0] - 2024-07-01
 
 First official stable release.
diff --git a/README.md b/README.md
index 5e47692..976d5fc 100644
--- a/README.md
+++ b/README.md
@@ -58,23 +58,36 @@ and licensed under the GPL-3.0 license.
 Both NMC2 and NMC3 devices should be fully supported. However, I have one
 NMC2 device in a home lab and have no way to guarantee success in all cases.
 
-Only RSA 1,024, 2,048, and 3,072 bit keys are accepted. 1,024 bit RSA is no
-longer considered completely secure; avoid keys of this size if possible. Most 
-(all?) public ACME services won't accept keys of this size anyway.
+### Key Types and Sizes
 
-NMC2 does not officially support the 3,072 bit key size, however, it works fine
-on my NMC2. If you use this size and it doesn't work on your NMC2, try a 2,048
-bit key instead. Later versions of the NMC3 firmware support RSA 4,096 and 
-ECDSA keys, but this tool does not. ECDSA was not included in APC's proprietary
-tool, and as such I have no way to generate files to reverse engineer.
+NMC2:
+- RSA 1,024, 2,048, 3,072* bit lengths.
+
+NMC3:
+- RSA 1,024, 2,048, 3,072, and 4,092 bit lengths.
+- ECDSA curves P-256, P-384, and P-521. 
+
+* 3,072 bit length is not officially supported by my NMC2, but appears to work
+  fine.
+
+1,024 bit RSA is no longer considered completely secure; avoid keys of 
+this size if possible. Most (all?) public ACME services won't accept keys 
+of this size anyway.
+
+### General Troubleshooting
 
 My setup (and therefore the testing setup) is:
 - APC Smart-UPS 1500VA RM 2U SUA1500RM2U (Firmware Revision 667.18.D)
 - AP9631 NMC2 Hardware Revision 05 running AOS v7.1.2 and Boot Monitor 
   v1.0.9.
 
-If you have problems, please post the log in an issue and I can try to fix it
-but it may be difficult without your particular hardware to test with.
+If you have trouble, your first step should be to update your NMC's firmware.
+Many issues with this tool will be resolved simply by updating to the newest
+firmware.
+
+If you have a problem after that, please post the log in an issue and I can 
+try to fix it but it may be difficult without your particular hardware to 
+test with.
 
 In particular, if you are experiencing `ssh: handshake failed:` first try
 using the `--insecurecipher` flag. If this works, you should upgrade your
diff --git a/pkg/apcssh/ssl.go b/pkg/apcssh/ssl.go
index 2eb3bce..18bff70 100644
--- a/pkg/apcssh/ssl.go
+++ b/pkg/apcssh/ssl.go
@@ -1,10 +1,13 @@
 package apcssh
 
 import (
+	"errors"
 	"fmt"
 	"strings"
 )
 
+var errSSLMissingData = errors.New("apcssh: ssl cert install: cant install nil data (unsupported key/nmc version/nmc firmware combo?)")
+
 // InstallSSLCert installs the specified p15 key and p15 cert files on the
 // UPS. It has logic to deduce if the NMC is a newer version (e.g., NMC3 with
 // newer firmware) and acts accordingly.
@@ -29,6 +32,11 @@ func (cli *Client) InstallSSLCert(keyP15 []byte, certPem []byte, keyCertP15 []by
 // installSSLCertModern installs the SSL key and certificate using the UPS built-in
 // command `ssl`. This command is not present on older devices (e.g., NMC2) or firmwares.
 func (cli *Client) installSSLCertModern(keyP15 []byte, certPem []byte) error {
+	// fail if required data isn't present
+	if keyP15 == nil || len(keyP15) <= 0 || certPem == nil || len(certPem) <= 0 {
+		return errSSLMissingData
+	}
+
 	// upload the key P15 file
 	err := cli.UploadSCP("/ssl/nmc.key", keyP15, 0600)
 	if err != nil {
@@ -63,6 +71,11 @@ func (cli *Client) installSSLCertModern(keyP15 []byte, certPem []byte) error {
 // them to a .p15 file on the UPS. This is used for older devices (e.g., NMC2) and
 // firmwares that do not support the `ssl` command.
 func (cli *Client) installSSLCertLegacy(keyCertP15 []byte) error {
+	// fail if required data isn't present
+	if keyCertP15 == nil || len(keyCertP15) <= 0 {
+		return errSSLMissingData
+	}
+
 	// upload/install keyCert P15 file
 	err := cli.UploadSCP("/ssl/defaultcert.p15", keyCertP15, 0600)
 	if err != nil {
diff --git a/pkg/app/app.go b/pkg/app/app.go
index d2d9767..d262678 100644
--- a/pkg/app/app.go
+++ b/pkg/app/app.go
@@ -12,7 +12,7 @@ import (
 )
 
 const (
-	appVersion = "1.0.0"
+	appVersion = "1.1.0-b1"
 )
 
 // struct for receivers to use common app pieces
diff --git a/pkg/app/cmd_create.go b/pkg/app/cmd_create.go
index 77f13ee..8791a81 100644
--- a/pkg/app/cmd_create.go
+++ b/pkg/app/cmd_create.go
@@ -51,11 +51,14 @@ func (app *app) cmdCreate(_ context.Context, args []string) error {
 	}
 	app.stdLogger.Printf("create: apc p15 key file %s written to disk", keyFileName)
 
-	err = os.WriteFile(keyCertFileName, apcKeyCertFile, 0600)
-	if err != nil {
-		return fmt.Errorf("create: failed to write apc p15 key+cert file (%s)", err)
+	// skip key+cert if it wasn't generated
+	if len(apcKeyCertFile) > 0 {
+		err = os.WriteFile(keyCertFileName, apcKeyCertFile, 0600)
+		if err != nil {
+			return fmt.Errorf("create: failed to write apc p15 key+cert file (%s)", err)
+		}
+		app.stdLogger.Printf("create: apc p15 key+cert file %s written to disk", keyCertFileName)
 	}
-	app.stdLogger.Printf("create: apc p15 key+cert file %s written to disk", keyCertFileName)
 
 	// if debug, write additional debug files (b64 format to make copy/paste into asn1 decoder
 	// easy to do e.g., https://lapo.it/asn1js)
@@ -67,19 +70,22 @@ func (app *app) cmdCreate(_ context.Context, args []string) error {
 		}
 		app.debugLogger.Printf("create: apc p15 key file %s written to disk", keyFileNameDebug)
 
-		keyCertFileNameDebug := keyCertFileName + ".noheader.b64"
-		err = os.WriteFile(keyCertFileNameDebug, []byte(base64.StdEncoding.EncodeToString(apcKeyCertFile[apcHeaderLen:])), 0600)
-		if err != nil {
-			return fmt.Errorf("create: failed to write apc p15 key+cert file (%s)", err)
-		}
-		app.debugLogger.Printf("create: apc p15 key+cert file %s written to disk", keyCertFileNameDebug)
+		// skip key+cert if it wasn't generated
+		if len(apcKeyCertFile) > 0 {
+			keyCertFileNameDebug := keyCertFileName + ".noheader.b64"
+			err = os.WriteFile(keyCertFileNameDebug, []byte(base64.StdEncoding.EncodeToString(apcKeyCertFile[apcHeaderLen:])), 0600)
+			if err != nil {
+				return fmt.Errorf("create: failed to write apc p15 key+cert file (%s)", err)
+			}
+			app.debugLogger.Printf("create: apc p15 key+cert file %s written to disk", keyCertFileNameDebug)
 
-		keyCertFileNameHeaderDebug := keyCertFileName + ".header.b64"
-		err = os.WriteFile(keyCertFileNameHeaderDebug, []byte(base64.StdEncoding.EncodeToString(apcKeyCertFile[:apcHeaderLen])), 0600)
-		if err != nil {
-			return fmt.Errorf("create: failed to write apc p15 key+cert file (%s)", err)
+			keyCertFileNameHeaderDebug := keyCertFileName + ".header.b64"
+			err = os.WriteFile(keyCertFileNameHeaderDebug, []byte(base64.StdEncoding.EncodeToString(apcKeyCertFile[:apcHeaderLen])), 0600)
+			if err != nil {
+				return fmt.Errorf("create: failed to write apc p15 key+cert file (%s)", err)
+			}
+			app.debugLogger.Printf("create: apc p15 key+cert file header %s written to disk", keyCertFileNameHeaderDebug)
 		}
-		app.debugLogger.Printf("create: apc p15 key+cert file header %s written to disk", keyCertFileNameHeaderDebug)
 
 	}
 
diff --git a/pkg/app/config.go b/pkg/app/config.go
index e8ff1fc..6ef840b 100644
--- a/pkg/app/config.go
+++ b/pkg/app/config.go
@@ -68,9 +68,9 @@ func (app *app) getConfig(args []string) error {
 	// create -- subcommand
 	createFlags := ff.NewFlagSet("create").SetParent(rootFlags)
 
-	cfg.create.keyPemFilePath = createFlags.StringLong("keyfile", "", "path and filename of the rsa-1024 or rsa-2048 key in pem format")
+	cfg.create.keyPemFilePath = createFlags.StringLong("keyfile", "", "path and filename of the key in pem format")
 	cfg.create.certPemFilePath = createFlags.StringLong("certfile", "", "path and filename of the certificate in pem format")
-	cfg.create.keyPem = createFlags.StringLong("keypem", "", "string of the rsa-1024 or rsa-2048 key in pem format")
+	cfg.create.keyPem = createFlags.StringLong("keypem", "", "string of the key in pem format")
 	cfg.create.certPem = createFlags.StringLong("certpem", "", "string of the certificate in pem format")
 	cfg.create.outFilePath = createFlags.StringLong("outfile", createDefaultOutFilePath, "path and filename to write the key+cert p15 file to")
 	cfg.create.outKeyFilePath = createFlags.StringLong("outkeyfile", createDefaultOutKeyFilePath, "path and filename to write the key p15 file to")
@@ -88,9 +88,9 @@ func (app *app) getConfig(args []string) error {
 	// install -- subcommand
 	installFlags := ff.NewFlagSet("install").SetParent(rootFlags)
 
-	cfg.install.keyPemFilePath = installFlags.StringLong("keyfile", "", "path and filename of the rsa-1024 or rsa-2048 key in pem format")
+	cfg.install.keyPemFilePath = installFlags.StringLong("keyfile", "", "path and filename of the key in pem format")
 	cfg.install.certPemFilePath = installFlags.StringLong("certfile", "", "path and filename of the certificate in pem format")
-	cfg.install.keyPem = installFlags.StringLong("keypem", "", "string of the rsa-1024 or rsa-2048 key in pem format")
+	cfg.install.keyPem = installFlags.StringLong("keypem", "", "string of the key in pem format")
 	cfg.install.certPem = installFlags.StringLong("certpem", "", "string of the certificate in pem format")
 	cfg.install.hostAndPort = installFlags.StringLong("apchost", "", "hostname:port of the apc ups to install the certificate on")
 	cfg.install.fingerprint = installFlags.StringLong("fingerprint", "", "the SHA256 fingerprint value of the ups' ssh server")
diff --git a/pkg/app/pem_to_p15.go b/pkg/app/pem_to_p15.go
index e376bc6..d48d4a8 100644
--- a/pkg/app/pem_to_p15.go
+++ b/pkg/app/pem_to_p15.go
@@ -3,13 +3,22 @@ package app
 import (
 	"apc-p15-tool/pkg/pkcs15"
 	"fmt"
+	"slices"
 )
 
-// pemToAPCP15 reads the specified pem files and returns the apc p15 files (both a
-// p15 file with just the private key, and also a p15 file with both the private key
-// and certificate). The key+cert file includes the required APC header, prepended.
+// list of keys supported by the NMC2
+var nmc2SupportedKeyTypes = []pkcs15.KeyType{
+	pkcs15.KeyTypeRSA1024,
+	pkcs15.KeyTypeRSA2048,
+	pkcs15.KeyTypeRSA3072, // officially not supported but works
+}
+
+// pemToAPCP15 reads the specified pem files and returns the apc p15 file(s). If the
+// key type of the key is not supported by NMC2, the combined key+cert file is not
+// generated and nil is returned instead for that file. If the key IS supported by
+// NMC2, the key+cert file is generated and the proper header is prepended.
 func (app *app) pemToAPCP15(keyPem, certPem []byte, parentCmdName string) (keyFile []byte, apcKeyCertFile []byte, err error) {
-	app.stdLogger.Printf("%s: making apc p15 file from pem", parentCmdName)
+	app.stdLogger.Printf("%s: making apc p15 file(s) content from pem", parentCmdName)
 
 	// make p15 struct
 	p15, err := pkcs15.ParsePEMToPKCS15(keyPem, certPem)
@@ -17,24 +26,40 @@ func (app *app) pemToAPCP15(keyPem, certPem []byte, parentCmdName string) (keyFi
 		return nil, nil, fmt.Errorf("%s: failed to parse pem files (%w)", parentCmdName, err)
 	}
 
-	app.stdLogger.Printf("%s: successfully loaded pem files", parentCmdName)
+	app.stdLogger.Printf("%s: successfully parsed pem files", parentCmdName)
 
-	// make file bytes
-	keyCertFile, keyFile, err := p15.ToP15Files()
+	// make key file (always)
+	keyFile, err = p15.ToP15Key()
 	if err != nil {
-		return nil, nil, fmt.Errorf("%s: failed to make p15 file (%w)", parentCmdName, err)
+		return nil, nil, fmt.Errorf("%s: failed to make p15 key file (%w)", parentCmdName, err)
 	}
 
-	// make header for file bytes
-	apcHeader, err := makeFileHeader(keyCertFile)
-	if err != nil {
-		return nil, nil, fmt.Errorf("%s: failed to make p15 file header (%w)", parentCmdName, err)
+	app.stdLogger.Printf("%s: successfully generated p15 key file content", parentCmdName)
+
+	// check key type for compat with NMC2
+	if slices.Contains(nmc2SupportedKeyTypes, p15.KeyType()) {
+		app.stdLogger.Printf("%s: key type is supported by NMC2, generating p15 key+cert file content...", parentCmdName)
+
+		// make file bytes
+		keyCertFile, err := p15.ToP15KeyCert()
+		if err != nil {
+			return nil, nil, fmt.Errorf("%s: failed to make p15 key+cert file content (%w)", parentCmdName, err)
+		}
+
+		// make header for file bytes
+		apcHeader, err := makeFileHeader(keyCertFile)
+		if err != nil {
+			return nil, nil, fmt.Errorf("%s: failed to make p15 key+cert file header (%w)", parentCmdName, err)
+		}
+
+		// combine header with file
+		apcKeyCertFile = append(apcHeader, keyCertFile...)
+	} else {
+		// NMC2 unsupported
+		app.stdLogger.Printf("%s: key type is not supported by NMC2, skipping p15 key+cert file content", parentCmdName)
 	}
 
-	// combine header with file
-	apcKeyCertFile = append(apcHeader, keyCertFile...)
-
-	app.stdLogger.Printf("%s: apc p15 file data succesfully generated", parentCmdName)
+	app.stdLogger.Printf("%s: apc p15 file(s) data succesfully generated", parentCmdName)
 
 	return keyFile, apcKeyCertFile, nil
 }
diff --git a/pkg/pkcs15/encrypted_envelope.go b/pkg/pkcs15/encrypted_envelope.go
index cead3c8..71433d1 100644
--- a/pkg/pkcs15/encrypted_envelope.go
+++ b/pkg/pkcs15/encrypted_envelope.go
@@ -21,14 +21,19 @@ const (
 	apcKEKIterations = 5000
 )
 
-// encryptedKeyEnvelope encrypts p15's rsa private key using the algorithms and
-// params expected in the APC file. Salt values are always random.
-func (p15 *pkcs15KeyCert) encryptedKeyEnvelope() ([]byte, error) {
+// encryptedKeyEnvelope encrypts p15's private key using the algorithms and
+// params expected in the APC file.
+func (p15 *pkcs15KeyCert) computeEncryptedKeyEnvelope() error {
+	// if computation already performed, this is a no-op (keep existing envelope)
+	if p15.envelopedPrivateKey != nil && len(p15.envelopedPrivateKey) != 0 {
+		return nil
+	}
+
 	// calculate values for the object
 	kekSalt := make([]byte, 8)
 	_, err := rand.Read(kekSalt)
 	if err != nil {
-		return nil, err
+		return err
 	}
 
 	// kek hash alg
@@ -42,7 +47,7 @@ func (p15 *pkcs15KeyCert) encryptedKeyEnvelope() ([]byte, error) {
 	// make DES cipher from KEK for CEK
 	cekDesCipher, err := des.NewTripleDESCipher(kek)
 	if err != nil {
-		return nil, err
+		return err
 	}
 
 	// cek (16 bytes for authEnc128) -- see: rfc3211
@@ -50,7 +55,7 @@ func (p15 *pkcs15KeyCert) encryptedKeyEnvelope() ([]byte, error) {
 	cek := make([]byte, cekLen)
 	_, err = rand.Read(cek)
 	if err != nil {
-		return nil, err
+		return err
 	}
 
 	// LEN + Check Val [3]
@@ -71,7 +76,7 @@ func (p15 *pkcs15KeyCert) encryptedKeyEnvelope() ([]byte, error) {
 	cekPadding := make([]byte, cekPadLen)
 	_, err = rand.Read(cekPadding)
 	if err != nil {
-		return nil, err
+		return err
 	}
 
 	wrappedCEK = append(wrappedCEK, cekPadding...)
@@ -80,7 +85,7 @@ func (p15 *pkcs15KeyCert) encryptedKeyEnvelope() ([]byte, error) {
 	cekEncryptSalt := make([]byte, 8)
 	_, err = rand.Read(cekEncryptSalt)
 	if err != nil {
-		return nil, err
+		return err
 	}
 
 	cekEncrypter := cipher.NewCBCEncrypter(cekDesCipher, cekEncryptSalt)
@@ -94,13 +99,13 @@ func (p15 *pkcs15KeyCert) encryptedKeyEnvelope() ([]byte, error) {
 	contentEncSalt := make([]byte, 8)
 	_, err = rand.Read(contentEncSalt)
 	if err != nil {
-		return nil, err
+		return err
 	}
 
 	contentEncryptKey := pbkdf2.Key(cek, []byte("encryption"), 1, 24, sha1.New)
 	contentDesCipher, err := des.NewTripleDESCipher(contentEncryptKey)
 	if err != nil {
-		return nil, err
+		return err
 	}
 
 	// envelope content (that will be encrypted)
@@ -151,7 +156,7 @@ func (p15 *pkcs15KeyCert) encryptedKeyEnvelope() ([]byte, error) {
 	// make MAC
 	_, err = macHasher.Write(hashMe)
 	if err != nil {
-		return nil, err
+		return err
 	}
 	mac := macHasher.Sum(nil)
 
@@ -218,5 +223,7 @@ func (p15 *pkcs15KeyCert) encryptedKeyEnvelope() ([]byte, error) {
 		finalEnv = append(finalEnv, envelope[i]...)
 	}
 
-	return finalEnv, nil
+	// set p15 struct envelope
+	p15.envelopedPrivateKey = finalEnv
+	return nil
 }
diff --git a/pkg/pkcs15/keyid.go b/pkg/pkcs15/keyid.go
index 68a3051..08a3ce4 100644
--- a/pkg/pkcs15/keyid.go
+++ b/pkg/pkcs15/keyid.go
@@ -2,6 +2,7 @@ package pkcs15
 
 import (
 	"apc-p15-tool/pkg/tools/asn1obj"
+	"crypto/ecdsa"
 	"crypto/rsa"
 	"crypto/sha1"
 	"encoding/binary"
@@ -119,9 +120,13 @@ func (p15 *pkcs15KeyCert) keyIdInt8() []byte {
 		nBytes := privKey.N.Bytes()
 		keyIdVal = nBytes[len(nBytes)-8:]
 
+	case *ecdsa.PrivateKey:
+		// don't use this key id, leave empty
+		return nil
+
 	default:
-		// panic if non-RSA key
-		panic("key id 8 for non-rsa key is unexpected and unsupported")
+		// panic if unexpected key type
+		panic("key id 8 for key is unexpected and unsupported")
 	}
 
 	// object to return
@@ -181,33 +186,13 @@ func (p15 *pkcs15KeyCert) keyIdInt9() []byte {
 		e := big.NewInt(int64(privKey.PublicKey.E))
 		publicKeyPacket = append(publicKeyPacket, bigIntToMpi(e)...)
 
-	// case *ecdsa.PrivateKey:
-	// 	// A one-octet number denoting the public-key algorithm of this key.
-	// 	// 19 - ECDSA public key algorithm (see rfc 6637 s. 5)
-	// 	publicKeyPacket = append(publicKeyPacket, uint8(19))
-
-	// 	// Algorithm-Specific Fields for ECDSA public keys (see rfc 6637 s. 11 table)
-	// 	// This is a length byte followed by the curve ID (length is the number of bytes the curve ID uses)
-	// 	switch privKey.Curve.Params().Name {
-	// 	case "P-256":
-	// 		// 1.2.840.10045.3.1.7    8   2A 86 48 CE 3D 03 01 07   NIST curve P-256
-	// 		publicKeyPacket = append(publicKeyPacket, byte(8))
-	// 		hex, _ := hex.DecodeString("2A8648CE3D030107")
-	// 		publicKeyPacket = append(publicKeyPacket, hex...)
-
-	// 	case "P-384":
-	// 		// 1.3.132.0.34           5   2B 81 04 00 22            NIST curve P-384
-	// 		publicKeyPacket = append(publicKeyPacket, byte(5))
-	// 		hex, _ := hex.DecodeString("2B81040022")
-	// 		publicKeyPacket = append(publicKeyPacket, hex...)
-
-	// 	default:
-	// 		panic(fmt.Sprintf("key id 9 for ecdsa key curve %s is unexpected and unsupported", privKey.Curve.Params().Name))
-	// 	}
+	case *ecdsa.PrivateKey:
+		// don't use this key id, leave empty
+		return nil
 
 	default:
-		// panic if non-RSA key
-		panic("key id 9 for non-rsa key is unexpected and unsupported")
+		// panic if unexpected key type
+		panic("key id 9 for key is unexpected and unsupported")
 	}
 
 	// Assemble the V4 byte array that will be hashed
diff --git a/pkg/pkcs15/pem_decode.go b/pkg/pkcs15/pem_decode.go
index 66a34b7..2d51837 100644
--- a/pkg/pkcs15/pem_decode.go
+++ b/pkg/pkcs15/pem_decode.go
@@ -2,6 +2,7 @@ package pkcs15
 
 import (
 	"crypto"
+	"crypto/ecdsa"
 	"crypto/rsa"
 	"crypto/tls"
 	"crypto/x509"
@@ -9,21 +10,27 @@ import (
 	"errors"
 	"fmt"
 	"reflect"
+	"slices"
 )
 
 var (
 	errPemKeyBadBlock       = errors.New("pkcs15: pem key: failed to decode pem block")
 	errPemKeyFailedToParse  = errors.New("pkcs15: pem key: failed to parse key")
-	errPemKeyWrongBlockType = errors.New("pkcs15: pem key: unsupported pem block type (only pkcs1 and pkcs8 supported)")
-	errPemKeyWrongType      = errors.New("pkcs15: pem key: unsupported key type (only rsa 1,024, 2,048, and 3,072 supported)")
+	errPemKeyWrongBlockType = errors.New("pkcs15: pem key: unsupported pem block type")
+	errKeyWrongType         = errors.New("pkcs15: pem key: unsupported key type")
 
 	errPemCertBadBlock      = errors.New("pkcs15: pem cert: failed to decode pem block")
 	errPemCertFailedToParse = errors.New("pkcs15: pem cert: failed to parse cert")
 )
 
+var (
+	supportedRSASizes    = []int{1024, 2048, 3072, 4096}
+	supportedECDSACurves = []string{"P-256", "P-384", "P-521"}
+)
+
 // pemKeyDecode attempts to decode a pem encoded byte slice and then attempts
-// to parse an RSA private key from the decoded pem block. an error is returned
-// if any of these steps fail OR if the key is not RSA and of bitlen 1,024 or 2,048
+// to parse a private key from the decoded pem block. an error is returned
+// if any of these steps fail OR if the key is not supported.
 func pemKeyDecode(keyPem []byte) (crypto.PrivateKey, error) {
 	// decode
 	pemBlock, _ := pem.Decode([]byte(keyPem))
@@ -47,28 +54,27 @@ func pemKeyDecode(keyPem []byte) (crypto.PrivateKey, error) {
 			return nil, fmt.Errorf("pkcs15: pem key: failed sanity check (%s)", err)
 		}
 
-		// verify proper bitlen
-		if rsaKey.N.BitLen() != 1024 && rsaKey.N.BitLen() != 2048 && rsaKey.N.BitLen() != 3072 {
-			return nil, errPemKeyWrongType
+		// verify supported rsa bitlen
+		if !slices.Contains(supportedRSASizes, rsaKey.N.BitLen()) {
+			return nil, errKeyWrongType
 		}
 
 		// good to go
 		privateKey = rsaKey
 
-	// case "EC PRIVATE KEY": // SEC1, ASN.1
-	// 	var ecdKey *ecdsa.PrivateKey
-	// 	ecdKey, err := x509.ParseECPrivateKey(pemBlock.Bytes)
-	// 	if err != nil {
-	// 		return nil, errPemKeyFailedToParse
-	// 	}
+	case "EC PRIVATE KEY": // SEC1, ASN.1
+		ecdKey, err := x509.ParseECPrivateKey(pemBlock.Bytes)
+		if err != nil {
+			return nil, errPemKeyFailedToParse
+		}
 
-	// 	// verify acceptable curve name
-	// 	if ecdKey.Curve.Params().Name != "P-256" && ecdKey.Curve.Params().Name != "P-384" {
-	// 		return nil, errPemKeyWrongType
-	// 	}
+		// verify supported curve name
+		if !slices.Contains(supportedECDSACurves, ecdKey.Curve.Params().Name) {
+			return nil, errKeyWrongType
+		}
 
-	// 	// good to go
-	// 	privateKey = ecdKey
+		// good to go
+		privateKey = ecdKey
 
 	case "PRIVATE KEY": // PKCS8
 		pkcs8Key, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes)
@@ -84,25 +90,25 @@ func pemKeyDecode(keyPem []byte) (crypto.PrivateKey, error) {
 				return nil, fmt.Errorf("pkcs15: pem key: failed sanity check (%s)", err)
 			}
 
-			// verify proper bitlen
-			if pkcs8Key.N.BitLen() != 1024 && pkcs8Key.N.BitLen() != 2048 && pkcs8Key.N.BitLen() != 3072 {
-				return nil, errPemKeyWrongType
+			// verify supported rsa bitlen
+			if !slices.Contains(supportedRSASizes, pkcs8Key.N.BitLen()) {
+				return nil, errKeyWrongType
 			}
 
 			// good to go
 			privateKey = pkcs8Key
 
-		// case *ecdsa.PrivateKey:
-		// 	// verify acceptable curve name
-		// 	if pkcs8Key.Curve.Params().Name != "P-256" && pkcs8Key.Curve.Params().Name != "P-384" {
-		// 		return nil, errPemKeyWrongType
-		// 	}
+		case *ecdsa.PrivateKey:
+			// verify supported curve name
+			if !slices.Contains(supportedECDSACurves, pkcs8Key.Curve.Params().Name) {
+				return nil, errKeyWrongType
+			}
 
-		// 	// good to go
-		// 	privateKey = pkcs8Key
+			// good to go
+			privateKey = pkcs8Key
 
 		default:
-			return nil, errPemKeyWrongType
+			return nil, errKeyWrongType
 		}
 
 	default:
diff --git a/pkg/pkcs15/pem_parse.go b/pkg/pkcs15/pem_parse.go
index 2cd1fea..19e44f1 100644
--- a/pkg/pkcs15/pem_parse.go
+++ b/pkg/pkcs15/pem_parse.go
@@ -2,6 +2,8 @@ package pkcs15
 
 import (
 	"crypto"
+	"crypto/ecdsa"
+	"crypto/rsa"
 	"crypto/x509"
 )
 
@@ -10,6 +12,59 @@ import (
 type pkcs15KeyCert struct {
 	key  crypto.PrivateKey
 	cert *x509.Certificate
+	// store the encrypted enveloped Private Key for re-use
+	envelopedPrivateKey []byte
+}
+
+// KeyType is used by consumers to check for compatibility
+type KeyType int
+
+const (
+	KeyTypeRSA1024 KeyType = iota
+	KeyTypeRSA2048
+	KeyTypeRSA3072
+	KeyTypeRSA4096
+
+	KeyTypeECP256
+	KeyTypeECP384
+	KeyTypeECP521
+
+	KeyTypeUnknown
+)
+
+// KeyType returns the private key type
+func (p15 *pkcs15KeyCert) KeyType() KeyType {
+	switch pKey := p15.key.(type) {
+	case *rsa.PrivateKey:
+		switch pKey.N.BitLen() {
+		case 1024:
+			return KeyTypeRSA1024
+		case 2048:
+			return KeyTypeRSA2048
+		case 3072:
+			return KeyTypeRSA3072
+		case 4096:
+			return KeyTypeRSA4096
+
+		default:
+		}
+
+	case *ecdsa.PrivateKey:
+		switch pKey.Curve.Params().Name {
+		case "P-256":
+			return KeyTypeECP256
+		case "P-384":
+			return KeyTypeECP384
+		case "P-521":
+			return KeyTypeECP521
+
+		default:
+		}
+
+	default:
+	}
+
+	return KeyTypeUnknown
 }
 
 // ParsePEMToPKCS15 parses the provide pem files to a pkcs15 struct; it also does some
@@ -27,10 +82,17 @@ func ParsePEMToPKCS15(keyPem, certPem []byte) (*pkcs15KeyCert, error) {
 		return nil, err
 	}
 
+	// create p15 struct
 	p15 := &pkcs15KeyCert{
 		key:  key,
 		cert: cert,
 	}
 
+	// pre-calculate encrypted envelope
+	err = p15.computeEncryptedKeyEnvelope()
+	if err != nil {
+		return nil, err
+	}
+
 	return p15, nil
 }
diff --git a/pkg/pkcs15/pem_to_p15.go b/pkg/pkcs15/pem_to_p15.go
index c213ddb..0c2214d 100644
--- a/pkg/pkcs15/pem_to_p15.go
+++ b/pkg/pkcs15/pem_to_p15.go
@@ -2,8 +2,10 @@ package pkcs15
 
 import (
 	"apc-p15-tool/pkg/tools/asn1obj"
+	"crypto/ecdsa"
 	"crypto/rsa"
 	"encoding/asn1"
+	"fmt"
 	"math/big"
 )
 
@@ -13,39 +15,87 @@ const (
 
 // toP15KeyCert creates a P15 file with both the private key and certificate, mirroring the
 // final p15 file an APC UPS expects (though without the header)
-func (p15 *pkcs15KeyCert) toP15KeyCert(keyEnvelope []byte) (keyCert []byte, err error) {
-	// private key object
-	privateKey := asn1obj.Sequence([][]byte{
-		// commonObjectAttributes - Label
-		asn1obj.Sequence([][]byte{
-			asn1obj.UTF8String(apcKeyLabel),
-		}),
-		// CommonKeyAttributes
-		asn1obj.Sequence([][]byte{
-			// CommonKeyAttributes - iD - uses keyId that is SHA1( SubjectPublicKeyInfo SEQUENCE )
-			asn1obj.OctetString(p15.keyId()),
-			// CommonKeyAttributes - usage (trailing 0s will drop)
-			asn1obj.BitString([]byte{byte(0b11100010)}),
-			// CommonKeyAttributes - accessFlags (trailing 0s will drop)
-			asn1obj.BitString([]byte{byte(0b10110000)}),
-			// CommonKeyAttributes - startDate
-			asn1obj.GeneralizedTime(p15.cert.NotBefore),
-			// CommonKeyAttributes - [0] endDate
-			asn1obj.GeneralizedTimeExplicitValue(0, p15.cert.NotAfter),
-		}),
-		// ObjectValue - indirect-protected
-		asn1obj.ExplicitCompound(1, [][]byte{
+func (p15 *pkcs15KeyCert) ToP15KeyCert() (keyCert []byte, err error) {
+	// encrypted envelope is required
+	err = p15.computeEncryptedKeyEnvelope()
+	if err != nil {
+		return nil, err
+	}
+
+	// create private key object
+	var privKeyObj []byte
+
+	switch p15.key.(type) {
+	case *rsa.PrivateKey:
+		// private key object
+		privKeyObj =
 			asn1obj.Sequence([][]byte{
-				// AuthEnvelopedData Type ([4])
-				asn1obj.ExplicitCompound(4, [][]byte{
-					keyEnvelope,
+				// commonObjectAttributes - Label
+				asn1obj.Sequence([][]byte{
+					asn1obj.UTF8String(apcKeyLabel),
 				}),
-			}),
-		}),
-	})
+				// CommonKeyAttributes
+				asn1obj.Sequence([][]byte{
+					// CommonKeyAttributes - iD - uses keyId that is SHA1( SubjectPublicKeyInfo SEQUENCE )
+					asn1obj.OctetString(p15.keyId()),
+					// CommonKeyAttributes - usage (trailing 0s will drop)
+					asn1obj.BitString([]byte{byte(0b11100010)}),
+					// CommonKeyAttributes - accessFlags (trailing 0s will drop)
+					asn1obj.BitString([]byte{byte(0b10110000)}),
+					// CommonKeyAttributes - startDate
+					asn1obj.GeneralizedTime(p15.cert.NotBefore),
+					// CommonKeyAttributes - [0] endDate
+					asn1obj.GeneralizedTimeExplicitValue(0, p15.cert.NotAfter),
+				}),
+				// ObjectValue - indirect-protected
+				asn1obj.ExplicitCompound(1, [][]byte{
+					asn1obj.Sequence([][]byte{
+						// AuthEnvelopedData Type ([4])
+						asn1obj.ExplicitCompound(4, [][]byte{
+							p15.envelopedPrivateKey,
+						}),
+					}),
+				}),
+			})
+
+	case *ecdsa.PrivateKey:
+		privKeyObj =
+			asn1obj.ExplicitCompound(0, [][]byte{
+				// commonObjectAttributes - Label
+				asn1obj.Sequence([][]byte{
+					asn1obj.UTF8String(apcKeyLabel),
+				}),
+				// CommonKeyAttributes
+				asn1obj.Sequence([][]byte{
+					// CommonKeyAttributes - iD - uses keyId that is SHA1( SubjectPublicKeyInfo SEQUENCE )
+					asn1obj.OctetString(p15.keyId()),
+					// CommonKeyAttributes - usage (trailing 0s will drop)
+					asn1obj.BitString([]byte{byte(0b00100010)}),
+					// CommonKeyAttributes - accessFlags (trailing 0s will drop)
+					asn1obj.BitString([]byte{byte(0b10110000)}),
+					// CommonKeyAttributes - startDate
+					asn1obj.GeneralizedTime(p15.cert.NotBefore),
+					// CommonKeyAttributes - [0] endDate
+					asn1obj.GeneralizedTimeExplicitValue(0, p15.cert.NotAfter),
+				}),
+				// ObjectValue - indirect-protected
+				asn1obj.ExplicitCompound(1, [][]byte{
+					asn1obj.Sequence([][]byte{
+						// AuthEnvelopedData Type ([4])
+						asn1obj.ExplicitCompound(4, [][]byte{
+							p15.envelopedPrivateKey,
+						}),
+					}),
+				}),
+			})
+
+	default:
+		// bad key type
+		return nil, errKeyWrongType
+	}
 
 	// cert object
-	cert := asn1obj.Sequence([][]byte{
+	certObj := asn1obj.Sequence([][]byte{
 		// commonObjectAttributes - Label
 		asn1obj.Sequence([][]byte{
 			asn1obj.UTF8String(apcKeyLabel),
@@ -59,6 +109,7 @@ func (p15 *pkcs15KeyCert) toP15KeyCert(keyEnvelope []byte) (keyCert []byte, err
 				p15.keyIdInt3(),
 				p15.keyIdInt6(),
 				p15.keyIdInt7(),
+				// 8 & 9 will return nil for EC keys (effectively omitting them)
 				p15.keyIdInt8(),
 				p15.keyIdInt9(),
 			}),
@@ -77,7 +128,7 @@ func (p15 *pkcs15KeyCert) toP15KeyCert(keyEnvelope []byte) (keyCert []byte, err
 		}),
 	})
 
-	// build the file
+	// build the object
 
 	// ContentInfo
 	keyCert = asn1obj.Sequence([][]byte{
@@ -92,12 +143,12 @@ func (p15 *pkcs15KeyCert) toP15KeyCert(keyEnvelope []byte) (keyCert []byte, err
 				asn1obj.Sequence([][]byte{
 					asn1obj.ExplicitCompound(0, [][]byte{
 						asn1obj.ExplicitCompound(0, [][]byte{
-							privateKey,
+							privKeyObj,
 						}),
 					}),
 					asn1obj.ExplicitCompound(4, [][]byte{
 						asn1obj.ExplicitCompound(0, [][]byte{
-							cert,
+							certObj,
 						}),
 					}),
 				}),
@@ -111,141 +162,212 @@ func (p15 *pkcs15KeyCert) toP15KeyCert(keyEnvelope []byte) (keyCert []byte, err
 // toP15Key creates a P15 file with just the private key, mirroring the p15 format
 // the APC tool uses when generating a new private key (Note: no header is used on
 // this file)
-func (p15 *pkcs15KeyCert) toP15Key(keyEnvelope []byte) (key []byte, err error) {
-	// create public key object
-	var pubKeyObj []byte
+func (p15 *pkcs15KeyCert) ToP15Key() (key []byte, err error) {
+	// encrypted envelope is required
+	err = p15.computeEncryptedKeyEnvelope()
+	if err != nil {
+		return nil, err
+	}
+
+	// create private and public key objects
+	var pubKeyObj, privKeyObj []byte
 
 	switch privKey := p15.key.(type) {
 	case *rsa.PrivateKey:
-		pubKeyObj = asn1obj.ExplicitCompound(1, [][]byte{
+		// private key object (slightly different than the key+cert format)
+		privKeyObj =
 			asn1obj.Sequence([][]byte{
+				// commonObjectAttributes - Label
+				asn1obj.Sequence([][]byte{
+					asn1obj.UTF8String(apcKeyLabel),
+				}),
+				// CommonKeyAttributes
+				asn1obj.Sequence([][]byte{
+					// CommonKeyAttributes - iD - uses keyId that is SHA1( SubjectPublicKeyInfo SEQUENCE )
+					asn1obj.OctetString(p15.keyId()),
+					// CommonKeyAttributes - usage (trailing 0s will drop)
+					asn1obj.BitString([]byte{byte(0b11100010)}),
+					// CommonKeyAttributes - accessFlags (trailing 0s will drop)
+					asn1obj.BitString([]byte{byte(0b10110000)}),
+				}),
+
+				// Key IDs
 				asn1obj.ExplicitCompound(0, [][]byte{
-					asn1obj.ExplicitCompound(1, [][]byte{
-						asn1obj.Sequence([][]byte{
-							asn1obj.ObjectIdentifier(asn1obj.OIDrsaEncryptionPKCS1),
-							asn1.NullBytes,
+					asn1obj.Sequence([][]byte{
+						asn1obj.ExplicitCompound(0, [][]byte{
+							p15.keyIdInt2(),
+							p15.keyIdInt8(),
+							p15.keyIdInt9(),
 						}),
-						// RSAPublicKey SubjectPublicKeyInfo
-						asn1obj.BitString(
-							asn1obj.Sequence([][]byte{
-								asn1obj.Integer(privKey.PublicKey.N),
-								asn1obj.Integer(big.NewInt(int64(privKey.PublicKey.E))),
-							}),
-						),
 					}),
 				}),
-				// not 100% certain but appears to be rsa key byte len
-				asn1obj.Integer(big.NewInt(int64(privKey.PublicKey.N.BitLen() / 8))),
-			}),
-		})
+
+				// ObjectValue - indirect-protected
+				asn1obj.ExplicitCompound(1, [][]byte{
+					asn1obj.Sequence([][]byte{
+						// AuthEnvelopedData Type ([4])
+						asn1obj.ExplicitCompound(4, [][]byte{
+							p15.envelopedPrivateKey,
+						}),
+					}),
+				}),
+			})
+
+		// pub key stub
+		pubKeyObj =
+			asn1obj.Sequence([][]byte{
+				// commonObjectAttributes - Label
+				asn1obj.Sequence([][]byte{
+					asn1obj.UTF8String(apcKeyLabel),
+				}),
+				// CommonKeyAttributes
+				asn1obj.Sequence([][]byte{
+					asn1obj.OctetString(p15.keyId()),
+					asn1obj.BitString([]byte{byte(0b10000010)}),
+					asn1obj.BitString([]byte{byte(0b01000000)}),
+				}),
+
+				asn1obj.ExplicitCompound(1, [][]byte{
+					asn1obj.Sequence([][]byte{
+						asn1obj.ExplicitCompound(0, [][]byte{
+							asn1obj.ExplicitCompound(1, [][]byte{
+								asn1obj.Sequence([][]byte{
+									asn1obj.ObjectIdentifier(asn1obj.OIDrsaEncryptionPKCS1),
+									asn1.NullBytes,
+								}),
+								// RSAPublicKey SubjectPublicKeyInfo
+								asn1obj.BitString(
+									asn1obj.Sequence([][]byte{
+										asn1obj.Integer(privKey.PublicKey.N),
+										asn1obj.Integer(big.NewInt(int64(privKey.PublicKey.E))),
+									}),
+								),
+							}),
+						}),
+						// not 100% certain but appears to be rsa key byte len
+						asn1obj.Integer(big.NewInt(int64(privKey.PublicKey.N.BitLen() / 8))),
+					}),
+				}),
+			})
+
+	case *ecdsa.PrivateKey:
+		// private key object (slightly different than the key+cert format)
+		privKeyObj =
+			asn1obj.ExplicitCompound(0, [][]byte{
+				// commonObjectAttributes - Label
+				asn1obj.Sequence([][]byte{
+					asn1obj.UTF8String(apcKeyLabel),
+				}),
+				// CommonKeyAttributes
+				asn1obj.Sequence([][]byte{
+					// CommonKeyAttributes - iD - uses keyId that is SHA1( SubjectPublicKeyInfo SEQUENCE )
+					asn1obj.OctetString(p15.keyId()),
+					// CommonKeyAttributes - usage (trailing 0s will drop)
+					asn1obj.BitString([]byte{byte(0b00100010)}),
+					// CommonKeyAttributes - accessFlags (trailing 0s will drop)
+					asn1obj.BitString([]byte{byte(0b10110000)}),
+				}),
+
+				// Key IDs
+				asn1obj.ExplicitCompound(0, [][]byte{
+					asn1obj.Sequence([][]byte{
+						asn1obj.ExplicitCompound(0, [][]byte{
+							p15.keyIdInt2(),
+						}),
+					}),
+				}),
+
+				// ObjectValue - indirect-protected
+				asn1obj.ExplicitCompound(1, [][]byte{
+					asn1obj.Sequence([][]byte{
+						// AuthEnvelopedData Type ([4])
+						asn1obj.ExplicitCompound(4, [][]byte{
+							p15.envelopedPrivateKey,
+						}),
+					}),
+				}),
+			})
+
+		// convert ec pub key to a form that provides a public key bytes function
+		ecdhKey, err := privKey.PublicKey.ECDH()
+		if err != nil {
+			return nil, fmt.Errorf("failed to parse ec public key (%s)", err)
+		}
+
+		// select correct OID for curve
+		var curveOID asn1.ObjectIdentifier
+		switch privKey.Curve.Params().Name {
+		case "P-256":
+			curveOID = asn1obj.OIDprime256v1
+		case "P-384":
+			curveOID = asn1obj.OIDsecp384r1
+		case "P-521":
+			curveOID = asn1obj.OIDsecp521r1
+		default:
+			// bad curve name
+			return nil, errKeyWrongType
+		}
+
+		// pub key stub
+		pubKeyObj =
+			asn1obj.ExplicitCompound(0, [][]byte{
+				// commonObjectAttributes - Label
+				asn1obj.Sequence([][]byte{
+					asn1obj.UTF8String(apcKeyLabel),
+				}),
+				// CommonKeyAttributes
+				asn1obj.Sequence([][]byte{
+					asn1obj.OctetString(p15.keyId()),
+					asn1obj.BitString([]byte{byte(0b00000010)}),
+					asn1obj.BitString([]byte{byte(0b01000000)}),
+				}),
+
+				asn1obj.ExplicitCompound(1, [][]byte{
+					asn1obj.Sequence([][]byte{
+						asn1obj.ExplicitCompound(0, [][]byte{
+							asn1obj.Sequence([][]byte{
+								asn1obj.Sequence([][]byte{
+									asn1obj.ObjectIdentifier(asn1obj.OIDecPublicKey),
+									asn1obj.ObjectIdentifier(curveOID),
+								}),
+								asn1obj.BitString(ecdhKey.Bytes()),
+							}),
+						}),
+					}),
+				}),
+			})
 
 	default:
-		// panic if non-RSA key
-		panic("p15 key file for non-rsa key is unexpected and unsupported")
+		// bad key type
+		return nil, errKeyWrongType
 	}
 
-	// private key object (slightly different than the key+cert format)
-	privateKey := asn1obj.Sequence([][]byte{
-		// commonObjectAttributes - Label
+	// assemble complete object
+	key =
 		asn1obj.Sequence([][]byte{
-			asn1obj.UTF8String(apcKeyLabel),
-		}),
-		// CommonKeyAttributes
-		asn1obj.Sequence([][]byte{
-			// CommonKeyAttributes - iD - uses keyId that is SHA1( SubjectPublicKeyInfo SEQUENCE )
-			asn1obj.OctetString(p15.keyId()),
-			// CommonKeyAttributes - usage (trailing 0s will drop)
-			asn1obj.BitString([]byte{byte(0b11100010)}),
-			// CommonKeyAttributes - accessFlags (trailing 0s will drop)
-			asn1obj.BitString([]byte{byte(0b10110000)}),
-		}),
-
-		//
-		asn1obj.ExplicitCompound(0, [][]byte{
-			asn1obj.Sequence([][]byte{
-				asn1obj.ExplicitCompound(0, [][]byte{
-					p15.keyIdInt2(),
-					p15.keyIdInt8(),
-					p15.keyIdInt9(),
-				}),
-			}),
-		}),
-
-		// ObjectValue - indirect-protected
-		asn1obj.ExplicitCompound(1, [][]byte{
-			asn1obj.Sequence([][]byte{
-				// AuthEnvelopedData Type ([4])
-				asn1obj.ExplicitCompound(4, [][]byte{
-					keyEnvelope,
-				}),
-			}),
-		}),
-	})
-
-	// ContentInfo
-	key = asn1obj.Sequence([][]byte{
-
-		// contentType: OID: 1.2.840.113549.1.15.3.1 pkcs15content (PKCS #15 content type)
-		asn1obj.ObjectIdentifier(asn1obj.OIDPkscs15Content),
-
-		// content
-		asn1obj.ExplicitCompound(0, [][]byte{
-			asn1obj.Sequence([][]byte{
-				asn1obj.Integer(big.NewInt(0)),
+			// contentType: OID: 1.2.840.113549.1.15.3.1 pkcs15content (PKCS #15 content type)
+			asn1obj.ObjectIdentifier(asn1obj.OIDPkscs15Content),
+			// content
+			asn1obj.ExplicitCompound(0, [][]byte{
 				asn1obj.Sequence([][]byte{
-					// [0] Private Key
-					asn1obj.ExplicitCompound(0, [][]byte{
+					asn1obj.Integer(big.NewInt(0)),
+					asn1obj.Sequence([][]byte{
+						// [0] Private Keys
 						asn1obj.ExplicitCompound(0, [][]byte{
-							privateKey,
+							asn1obj.ExplicitCompound(0, [][]byte{
+								privKeyObj,
+							}),
 						}),
-					}),
-					// [1] Public Key
-					asn1obj.ExplicitCompound(1, [][]byte{
-						asn1obj.ExplicitCompound(0, [][]byte{
-							asn1obj.Sequence([][]byte{
-								// commonObjectAttributes - Label
-								asn1obj.Sequence([][]byte{
-									asn1obj.UTF8String(apcKeyLabel),
-								}),
-								// CommonKeyAttributes
-								asn1obj.Sequence([][]byte{
-									asn1obj.OctetString(p15.keyId()),
-									asn1obj.BitString([]byte{byte(0b10000010)}),
-									asn1obj.BitString([]byte{byte(0b01000000)}),
-								}),
-
+						// [1] Public Keys
+						asn1obj.ExplicitCompound(1, [][]byte{
+							asn1obj.ExplicitCompound(0, [][]byte{
 								pubKeyObj,
 							}),
 						}),
 					}),
 				}),
 			}),
-		}),
-	})
+		})
 
 	return key, nil
 }
-
-// ToP15File turns the key and cert into a properly formatted and encoded
-// p15 file
-func (p15 *pkcs15KeyCert) ToP15Files() (keyCertFile []byte, keyFile []byte, err error) {
-	// rsa encrypted key in encrypted envelope (will be shared by both output files)
-	envelope, err := p15.encryptedKeyEnvelope()
-	if err != nil {
-		return nil, nil, err
-	}
-
-	// key + cert file
-	keyCertFile, err = p15.toP15KeyCert(envelope)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	// key only file
-	keyFile, err = p15.toP15Key(envelope)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	return keyCertFile, keyFile, nil
-}
diff --git a/pkg/pkcs15/private_key.go b/pkg/pkcs15/private_key.go
index 0321551..59b538e 100644
--- a/pkg/pkcs15/private_key.go
+++ b/pkg/pkcs15/private_key.go
@@ -2,6 +2,7 @@ package pkcs15
 
 import (
 	"apc-p15-tool/pkg/tools/asn1obj"
+	"crypto/ecdsa"
 	"crypto/rsa"
 )
 
@@ -27,15 +28,13 @@ func (p15 *pkcs15KeyCert) privateKeyObject() []byte {
 			asn1obj.IntegerExplicitValue(7, privKey.Precomputed.Qinv),
 		})
 
-	// case *ecdsa.PrivateKey:
-	// 	// Only private piece is the integer D
-	// 	privKeyObj = asn1obj.Sequence([][]byte{
-	// 		asn1obj.Integer(privKey.D),
-	// 	})
+	case *ecdsa.PrivateKey:
+		// Only private piece is the integer D
+		privKeyObj = asn1obj.Integer(privKey.D)
 
 	default:
-		// panic if non-RSA key
-		panic("private key object for non-rsa key is unexpected and unsupported")
+		// panic if unsupported key
+		panic("private key type is unexpected and unsupported")
 	}
 
 	return privKeyObj
diff --git a/pkg/tools/asn1obj/oid.go b/pkg/tools/asn1obj/oid.go
index 3975ded..70009c2 100644
--- a/pkg/tools/asn1obj/oid.go
+++ b/pkg/tools/asn1obj/oid.go
@@ -11,6 +11,10 @@ var (
 	OIDdesEDE3CBC         = asn1.ObjectIdentifier{1, 2, 840, 113549, 3, 7}            // des-EDE3-CBC (RSADSI encryptionAlgorithm)
 	OIDpkcs7Data          = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1}         // data (PKCS #7)
 	OIDauthEnc128         = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 3, 15} // authEnc128 (S/MIME Algorithms)
+	OIDecPublicKey        = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}             // ecPublicKey (ANSI X9.62 public key type)
+	OIDprime256v1         = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}          //  prime256v1 (ANSI X9.62 named elliptic curve)
+	OIDsecp384r1          = asn1.ObjectIdentifier{1, 3, 132, 0, 34}                   //  secp384r1 (SECG (Certicom) named elliptic curve)
+	OIDsecp521r1          = asn1.ObjectIdentifier{1, 3, 132, 0, 35}                   //  secp521r1 (SECG (Certicom) named elliptic curve)
 )
 
 // ObjectIdentifier returns an ASN.1 OBJECT IDENTIFIER with the oidValue bytes