diff --git a/.github/workflows/build_releases.yml b/.github/workflows/build_releases.yml
index 5b41dbe..d1a0d90 100644
--- a/.github/workflows/build_releases.yml
+++ b/.github/workflows/build_releases.yml
@@ -8,11 +8,11 @@ on:
 
 env:
   GITHUB_REF: ${{ github.ref }}
-  GO_VERSION: '1.24.2'
+  GO_VERSION: '1.22.1'
 
 jobs:
   build-common:
-    runs-on: ubuntu-24.04
+    runs-on: ubuntu-latest
 
     steps:
       - name: Checkout Main Repo
@@ -40,10 +40,8 @@ jobs:
           name: CHANGELOG.md
           path: ./CHANGELOG.md
 
-###
-
   build-linux-arm64:
-    runs-on: ubuntu-24.04-arm
+    runs-on: ubuntu-latest
     steps:
       - name: Checkout Repo
         uses: actions/checkout@v4
@@ -52,6 +50,12 @@ jobs:
           ref: ${{ env.GITHUB_REF }}
           fetch-depth: 0
 
+      - name: Update apt
+        run: sudo apt update
+
+      - name: Install cross-compiler for linux/arm64
+        run: sudo apt-get -y install gcc-aarch64-linux-gnu
+
       - name: Set up Go
         uses: actions/setup-go@v5
         with:
@@ -62,6 +66,7 @@ jobs:
         env:
           GOOS: linux
           GOARCH: arm64
+          CC: aarch64-linux-gnu-gcc
           CGO_ENABLED: 0
 
       - name: Save Compiled Binary
@@ -85,7 +90,7 @@ jobs:
           path: ./apc-p15-install
 
   build-linux-amd64:
-    runs-on: ubuntu-24.04
+    runs-on: ubuntu-latest
     steps:
       - name: Checkout Backend Repo
         uses: actions/checkout@v4
@@ -166,93 +171,9 @@ jobs:
           name: apc-p15-install-windows-amd64
           path: ./apc-p15-install.exe
 
-  build-darwin-arm64:
-    runs-on: macos-15
-    steps:
-      - name: Checkout Backend Repo
-        uses: actions/checkout@v4
-        with:
-          repository: gregtwallace/apc-p15-tool
-          ref: ${{ env.GITHUB_REF }}
-          fetch-depth: 0
-
-      - name: Set up Go
-        uses: actions/setup-go@v5
-        with:
-          go-version: '${{ env.GO_VERSION }}'
-
-      - name: Build Tool
-        run: go build -o ./apc-p15-tool -v ./cmd/tool
-        env:
-          GOOS: darwin
-          GOARCH: arm64
-          CGO_ENABLED: 0
-
-      - name: Save Compiled Binary
-        uses: actions/upload-artifact@v4
-        with:
-          name: apc-p15-tool-darwin-arm64
-          path: ./apc-p15-tool
-
-      - name: Build Install Only
-        run: go build -o ./apc-p15-install -v ./cmd/install_only
-        env:
-          GOOS: darwin
-          GOARCH: arm64
-          CGO_ENABLED: 0
-
-      - name: Save Compiled Binary
-        uses: actions/upload-artifact@v4
-        with:
-          name: apc-p15-install-darwin-arm64
-          path: ./apc-p15-install
-
-  build-darwin-amd64:
-    runs-on: macos-13
-    steps:
-      - name: Checkout Backend Repo
-        uses: actions/checkout@v4
-        with:
-          repository: gregtwallace/apc-p15-tool
-          ref: ${{ env.GITHUB_REF }}
-          fetch-depth: 0
-
-      - name: Set up Go
-        uses: actions/setup-go@v5
-        with:
-          go-version: '${{ env.GO_VERSION }}'
-
-      - name: Build Tool
-        run: go build -o ./apc-p15-tool -v ./cmd/tool
-        env:
-          GOOS: darwin
-          GOARCH: amd64
-          CGO_ENABLED: 0
-
-      - name: Save Compiled Binary
-        uses: actions/upload-artifact@v4
-        with:
-          name: apc-p15-tool-darwin-amd64
-          path: ./apc-p15-tool
-
-      - name: Build Install Only
-        run: go build -o ./apc-p15-install -v ./cmd/install_only
-        env:
-          GOOS: darwin
-          GOARCH: amd64
-          CGO_ENABLED: 0
-
-      - name: Save Compiled Binary
-        uses: actions/upload-artifact@v4
-        with:
-          name: apc-p15-install-darwin-amd64
-          path: ./apc-p15-install
-
-###
-
   release-file-linux-arm64:
     needs: [build-common, build-linux-arm64]
-    runs-on: ubuntu-24.04
+    runs-on: ubuntu-latest
 
     steps:
       - name: Make release directory
@@ -296,7 +217,7 @@ jobs:
 
   release-file-linux-amd64:
     needs: [build-common, build-linux-amd64]
-    runs-on: ubuntu-24.04
+    runs-on: ubuntu-latest
 
     steps:
       - name: Make release directory
@@ -340,7 +261,7 @@ jobs:
 
   release-file-windows-amd64:
     needs: [build-common, build-windows-amd64]
-    runs-on: ubuntu-24.04
+    runs-on: ubuntu-latest
 
     steps:
       - name: Make release directory
@@ -381,91 +302,3 @@ jobs:
         with:
           name: apc-p15-tool_windows_amd64
           path: ./release
-
-  release-file-darwin-arm64:
-    needs: [build-common, build-darwin-arm64]
-    runs-on: ubuntu-24.04
-
-    steps:
-      - name: Make release directory
-        run: mkdir ./release
-
-      - name: Download Tool Binary
-        uses: actions/download-artifact@v4
-        with:
-          name: apc-p15-tool-darwin-arm64
-          path: ./release
-
-      - name: Download Install Binary
-        uses: actions/download-artifact@v4
-        with:
-          name: apc-p15-install-darwin-arm64
-          path: ./release
-
-      - name: Download README
-        uses: actions/download-artifact@v4
-        with:
-          name: README.md
-          path: ./release
-
-      - name: Download LICENSE
-        uses: actions/download-artifact@v4
-        with:
-          name: LICENSE.md
-          path: ./release
-
-      - name: Download CHANGELOG
-        uses: actions/download-artifact@v4
-        with:
-          name: CHANGELOG.md
-          path: ./release
-
-      - name: Save Release
-        uses: actions/upload-artifact@v4
-        with:
-          name: apc-p15-tool_darwin_arm64
-          path: ./release
-
-  release-file-darwin-amd64:
-    needs: [build-common, build-darwin-amd64]
-    runs-on: ubuntu-24.04
-
-    steps:
-      - name: Make release directory
-        run: mkdir ./release
-
-      - name: Download Tool Binary
-        uses: actions/download-artifact@v4
-        with:
-          name: apc-p15-tool-darwin-amd64
-          path: ./release
-
-      - name: Download Install Binary
-        uses: actions/download-artifact@v4
-        with:
-          name: apc-p15-install-darwin-amd64
-          path: ./release
-
-      - name: Download README
-        uses: actions/download-artifact@v4
-        with:
-          name: README.md
-          path: ./release
-
-      - name: Download LICENSE
-        uses: actions/download-artifact@v4
-        with:
-          name: LICENSE.md
-          path: ./release
-
-      - name: Download CHANGELOG
-        uses: actions/download-artifact@v4
-        with:
-          name: CHANGELOG.md
-          path: ./release
-
-      - name: Save Release
-        uses: actions/upload-artifact@v4
-        with:
-          name: apc-p15-tool_darwin_amd64
-          path: ./release
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cc534a6..39c9104 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,60 +1,5 @@
 # APC P15 Tool Changelog
 
-## [v1.2.2] - 2025-04-22
-
-All dependencies updated.
-
-Add darwin arm64 and amd64 builds.
-
-
-## [v1.2.1] - 2025-03-17
-
-Fix time check for UPS when it is set to GMT timezone.
-
-All dependencies updated.
-
-
-## [v1.2.0] - 2025-01-27
-
-Add a new feature to `install` that checks the time of the UPS to confirm
-it is accurate. A log message is added that advises either way. Even if
-the check fails, the install still proceeds with attempting to install
-the new certificate.
-
-Dependencies were also all updated.
-
-
-## [v1.1.0] - 2024-09-17
-
-> [!IMPORTANT]
-> The flag `apchost` on the `install` command has been renamed to
-> `hostname`. This flag should contain the hostname only. If a non-
-> default SSH port is needed, specify it in the `sshport` flag.
-
-This version brings support for for RSA 4,092 bit and EC keys. These 
-keys are only compatible with NMC3 running newer firmwares. To know 
-if your firmware is new enough, SSH into your UPS and type `ssh` and enter.
-If the UPS responds `Command Not Found` the firmware is too old or
-otherwise incompatible.
-
-This version also adds a post `install` check that connects to the web
-ui and verifies the certificate served is the expected one. You can
-specify a non standard ssl port with the `sslport` flag or skip the check
-entirely with the `skipverify` flag.
-
-
-## [v1.0.0] - 2024-07-01
-
-First official stable release.
-
-Fixes Go version in Github action.
-
-
-## [v0.5.3] - 2024-06-24
-
-Add 3,072 bit RSA key support.
-
-
 ## [v0.5.2] - 2024-06-19
 
 Minor tweak to the previous version. Add timeout for shell
diff --git a/README.md b/README.md
index 8a9218f..b41e8f3 100644
--- a/README.md
+++ b/README.md
@@ -58,42 +58,22 @@ 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.
 
-### Key Types and Sizes
+Only RSA 1,024 and 2,048 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.
 
-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.
-
-\* The additional key types supported by NMC3 require newer firmware on the
-  device. I am unsure what the version cutoff is, but you can check support
-  by connecting to the UPS via SSH and typing `ssl`. If `Command Not Found`
-  is returned, the firmware is too old and only the key types listed under
-  NMC2 will work.
-
-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
+Even though later versions of the NMC3 firmware supports RSA 4,096 and 
+ECDSA keys, this tool does not. These options were not available in APC's
+proprietary tool, and as such I have no way to generate files to reverse 
+engineer.
 
 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 
+- AP9631 NMC2 Hardware Revision 05 running AOS v7.0.4 and Boot Monitor 
   v1.0.9.
 
-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.
+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.
 
 In particular, if you are experiencing `ssh: handshake failed:` first try
 using the `--insecurecipher` flag. If this works, you should upgrade your
@@ -146,7 +126,7 @@ disk. It instead installs the files directly on the NMC. Logic
 automatically deduces if the device is an NMC2 or NMC3 and performs
 the appropriate installation steps.
 
-e.g. `./apc-p15-tool install --keyfile ./apckey.pem --certfile ./apccert.pem --hostname myapc.example.com --username apc --password someSecret --fingerprint 123abc`
+e.g. `./apc-p15-tool install --keyfile ./apckey.pem --certfile ./apccert.pem --apchost myapc.example.com:22 --username apc --password someSecret --fingerprint 123abc`
 
 ## Note About Install Automation
 
@@ -171,11 +151,6 @@ separate script.
 
 ![Cert Warden with APC P15 Tool](https://raw.githubusercontent.com/gregtwallace/apc-p15-tool/main/img/apc-p15-tool.png)
 
-## Links
-
-@Owl-Tec's write up using this tool with ACDS: 
-https://owltec.ca/Windows+Server/Deploying+An+Internal+HTTPS+Certificate+for+a+UPS+APC+with+ADCS+(Active+Directory+Certificate+Services)+with+APC+P15+Tool
-
 ## Thanks
 
 Special thanks to the following people and resources which helped me 
diff --git a/build.ps1 b/build.ps1
index 0c8774b..7147a33 100644
--- a/build.ps1
+++ b/build.ps1
@@ -34,25 +34,3 @@ $env:GOARCH = "arm64"
 $env:GOOS = "linux"
 $env:CGO_ENABLED = 0
 go build -o $outDir/apc-p15-install-arm64 ./cmd/install_only
-
-# Darwin (MacOS) amd64
-$env:GOARCH = "amd64"
-$env:GOOS = "darwin"
-$env:CGO_ENABLED = 0
-go build -o $outDir/apc-p15-tool-darwin-amd64 ./cmd/tool
-
-$env:GOARCH = "amd64"
-$env:GOOS = "darwin"
-$env:CGO_ENABLED = 0
-go build -o $outDir/apc-p15-install-darwin-amd64 ./cmd/install_only
-
-# Darwin (MacOS) arm64
-$env:GOARCH = "arm64"
-$env:GOOS = "darwin"
-$env:CGO_ENABLED = 0
-go build -o $outDir/apc-p15-tool-darwin-arm64 ./cmd/tool
-
-$env:GOARCH = "arm64"
-$env:GOOS = "darwin"
-$env:CGO_ENABLED = 0
-go build -o $outDir/apc-p15-install-darwin-arm64 ./cmd/install_only
diff --git a/go.mod b/go.mod
index 76eb3ca..ad1bc05 100644
--- a/go.mod
+++ b/go.mod
@@ -1,14 +1,14 @@
 module apc-p15-tool
 
-go 1.24.2
+go 1.22.4
 
 require (
 	github.com/peterbourgon/ff/v4 v4.0.0-alpha.4
-	github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1
-	golang.org/x/crypto v0.37.0
+	github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
+	golang.org/x/crypto v0.18.0
 )
 
-require golang.org/x/sys v0.32.0 // indirect
+require golang.org/x/sys v0.16.0 // indirect
 
 replace apc-p15-tool/cmd/install_only => /cmd/install_only
 
diff --git a/go.sum b/go.sum
index 0b94b0b..96676f0 100644
--- a/go.sum
+++ b/go.sum
@@ -2,13 +2,13 @@ github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N
 github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
 github.com/peterbourgon/ff/v4 v4.0.0-alpha.4 h1:aiqS8aBlF9PsAKeMddMSfbwp3smONCn3UO8QfUg0Z7Y=
 github.com/peterbourgon/ff/v4 v4.0.0-alpha.4/go.mod h1:H/13DK46DKXy7EaIxPhk2Y0EC8aubKm35nBjBe8AAGc=
-github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1 h1:NVK+OqnavpyFmUiKfUMHrpvbCi2VFoWTrcpI7aDaJ2I=
-github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
-golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
-golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
-golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
-golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
-golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
-golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
+github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs=
+github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
+golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
+golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
+golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
+golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
diff --git a/img/apc-p15-tool.png b/img/apc-p15-tool.png
index c537585..807fb84 100644
Binary files a/img/apc-p15-tool.png and b/img/apc-p15-tool.png differ
diff --git a/pkg/apcssh/cmd_gettime.go b/pkg/apcssh/cmd_gettime.go
deleted file mode 100644
index 139b0ba..0000000
--- a/pkg/apcssh/cmd_gettime.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package apcssh
-
-import (
-	"fmt"
-	"regexp"
-	"strings"
-	"time"
-)
-
-// GetTime sends the APC `system` command and then attempts to parse the
-// response to determine the UPS current date/time.
-func (cli *Client) GetTime() (time.Time, error) {
-	result, err := cli.cmd("date")
-	if err != nil {
-		return time.Time{}, fmt.Errorf("apcssh: failed to get time (%s)", err)
-	} else if !strings.EqualFold(result.code, "e000") {
-		return time.Time{}, fmt.Errorf("apcssh: failed to get time (%s: %s)", result.code, result.codeText)
-	}
-
-	// capture each portion of the date information
-	regex := regexp.MustCompile(`Date:\s*(\S*)\s*[\r\n]Time:\s*(\S*)\s*[\r\n]Format:\s*(\S*)\s*[\r\n]Time Zone:\s*(\S*)\s*[\r\n]?`)
-	datePieces := regex.FindStringSubmatch(result.resultText)
-	if len(datePieces) != 5 {
-		return time.Time{}, fmt.Errorf("apcssh: failed to get time (length of datetime value pieces was %d (expected: 5))", len(datePieces))
-	}
-	dateVal := datePieces[1]
-	timeVal := datePieces[2]
-	formatUPSVal := datePieces[3]
-	timeZoneVal := datePieces[4]
-
-	// GMT time requires + prefix
-	// APC UPS fails to use the required +, so add it
-	if timeZoneVal == "00:00" {
-		timeZoneVal = "+" + timeZoneVal
-	}
-
-	// known APC UPS format strings
-	dateFormatVal := ""
-	switch formatUPSVal {
-	case "mm/dd/yyyy":
-		dateFormatVal = "01/02/2006"
-	case "dd.mm.yyyy":
-		dateFormatVal = "02.01.2006"
-	case "mmm-dd-yy":
-		dateFormatVal = "Jan-02-06"
-	case "dd-mmm-yy":
-		dateFormatVal = "02-Jan-06"
-	case "yyyy-mm-dd":
-		dateFormatVal = "2006-01-02"
-
-	default:
-		return time.Time{}, fmt.Errorf("apcssh: failed to get time (ups returned unknown format string (%s)", formatUPSVal)
-	}
-
-	// convert to time.Time
-	t, err := time.Parse(dateFormatVal+" 15:04:05 -07:00", dateVal+" "+timeVal+" "+timeZoneVal)
-	if err != nil {
-		return time.Time{}, fmt.Errorf("apcssh: failed to get time (time parse failed: %s)", err)
-	}
-
-	return t, nil
-}
diff --git a/pkg/apcssh/ssl.go b/pkg/apcssh/ssl.go
index 18bff70..2eb3bce 100644
--- a/pkg/apcssh/ssl.go
+++ b/pkg/apcssh/ssl.go
@@ -1,13 +1,10 @@
 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.
@@ -32,11 +29,6 @@ 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 {
@@ -71,11 +63,6 @@ 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 052a00e..d1f4d6d 100644
--- a/pkg/app/app.go
+++ b/pkg/app/app.go
@@ -12,7 +12,7 @@ import (
 )
 
 const (
-	appVersion = "1.2.2"
+	appVersion = "0.5.2"
 )
 
 // struct for receivers to use common app pieces
diff --git a/pkg/app/cmd_create.go b/pkg/app/cmd_create.go
index 8791a81..77f13ee 100644
--- a/pkg/app/cmd_create.go
+++ b/pkg/app/cmd_create.go
@@ -51,14 +51,11 @@ func (app *app) cmdCreate(_ context.Context, args []string) error {
 	}
 	app.stdLogger.Printf("create: apc p15 key file %s written to disk", keyFileName)
 
-	// 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)
+	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)
 
 	// if debug, write additional debug files (b64 format to make copy/paste into asn1 decoder
 	// easy to do e.g., https://lapo.it/asn1js)
@@ -70,22 +67,19 @@ func (app *app) cmdCreate(_ context.Context, args []string) error {
 		}
 		app.debugLogger.Printf("create: apc p15 key file %s written to disk", keyFileNameDebug)
 
-		// 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)
-			}
-			app.debugLogger.Printf("create: apc p15 key+cert file header %s written to disk", keyCertFileNameHeaderDebug)
+		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)
+		}
+		app.debugLogger.Printf("create: apc p15 key+cert file header %s written to disk", keyCertFileNameHeaderDebug)
 
 	}
 
diff --git a/pkg/app/cmd_install.go b/pkg/app/cmd_install.go
index eacda53..d3270a4 100644
--- a/pkg/app/cmd_install.go
+++ b/pkg/app/cmd_install.go
@@ -2,18 +2,11 @@ package app
 
 import (
 	"apc-p15-tool/pkg/apcssh"
-	"bytes"
 	"context"
-	"crypto/tls"
-	"encoding/pem"
 	"errors"
 	"fmt"
-	"strconv"
-	"time"
 )
 
-const timeLoggingFormat = time.RFC1123Z
-
 // cmdInstall is the app's command to create apc p15 file content from key and cert
 // pem files and upload the p15 to the specified APC UPS
 func (app *app) cmdInstall(cmdCtx context.Context, args []string) error {
@@ -43,9 +36,7 @@ func (app *app) cmdInstall(cmdCtx context.Context, args []string) error {
 	}
 
 	// host to install on must be specified
-	if app.config.install.hostname == nil || *app.config.install.hostname == "" ||
-		app.config.install.sshport == nil || *app.config.install.sshport == 0 {
-
+	if app.config.install.hostAndPort == nil || *app.config.install.hostAndPort == "" {
 		return errors.New("install: failed, apc host not specified")
 	}
 
@@ -64,7 +55,7 @@ func (app *app) cmdInstall(cmdCtx context.Context, args []string) error {
 
 	// make APC SSH client
 	cfg := &apcssh.Config{
-		Hostname:          *app.config.install.hostname + ":" + strconv.Itoa(*app.config.install.sshport),
+		Hostname:          *app.config.install.hostAndPort,
 		Username:          *app.config.install.username,
 		Password:          *app.config.install.password,
 		ServerFingerprint: *app.config.install.fingerprint,
@@ -77,16 +68,6 @@ func (app *app) cmdInstall(cmdCtx context.Context, args []string) error {
 	}
 	app.stdLogger.Println("install: connected to ups ssh, installing ssl key and cert...")
 
-	// check time - don't fail it time is no good, just do logging here
-	upsT, err := client.GetTime()
-	if err != nil {
-		app.errLogger.Printf("warn: install: failed to fetch UPS time (%s), you should manually verify the time is correct on the UPS", err)
-	} else if upsT.After(time.Now().Add(1*time.Hour)) || upsT.Before(time.Now().Add(-1*time.Hour)) {
-		app.errLogger.Printf("warn: install: UPS clock skew detected (this system's time is %s vs. UPS time %s", time.Now().Format(timeLoggingFormat), upsT.Format(timeLoggingFormat))
-	} else {
-		app.stdLogger.Printf("install: UPS clock appears correct (%s)", upsT.Format(timeLoggingFormat))
-	}
-
 	// install SSL Cert
 	err = client.InstallSSLCert(keyP15, certPem, keyCertP15)
 	if err != nil {
@@ -94,7 +75,7 @@ func (app *app) cmdInstall(cmdCtx context.Context, args []string) error {
 	}
 
 	// installed
-	app.stdLogger.Printf("install: apc p15 file installed on %s", *app.config.install.hostname)
+	app.stdLogger.Printf("install: apc p15 file installed on %s", *app.config.install.hostAndPort)
 
 	// restart UPS webUI
 	if app.config.install.restartWebUI != nil && *app.config.install.restartWebUI {
@@ -108,48 +89,5 @@ func (app *app) cmdInstall(cmdCtx context.Context, args []string) error {
 		app.stdLogger.Println("install: sent webui restart command")
 	}
 
-	// check the new certificate is installed
-	if app.config.install.skipVerify != nil && !*app.config.install.skipVerify &&
-		app.config.install.webUISSLPort != nil && *app.config.install.webUISSLPort != 0 {
-
-		app.stdLogger.Println("install: attempting to verify certificate install...")
-
-		// sleep for UPS to finish anything it might be doing
-		time.Sleep(5 * time.Second)
-
-		// if UPS web UI was restarted, sleep longer
-		if app.config.install.restartWebUI != nil && *app.config.install.restartWebUI {
-			app.stdLogger.Println("install: waiting for ups webui restart...")
-			time.Sleep(25 * time.Second)
-		}
-
-		// connect to the web UI to get the current certificate
-		conf := &tls.Config{
-			InsecureSkipVerify: true,
-		}
-		conn, err := tls.Dial("tcp", *app.config.install.hostname+":"+strconv.Itoa(*app.config.install.webUISSLPort), conf)
-		if err != nil {
-			return fmt.Errorf("install: failed to dial webui for verification (%s)", err)
-		}
-		defer conn.Close()
-
-		// get top cert
-		leafCert := conn.ConnectionState().PeerCertificates[0]
-		if leafCert == nil {
-			return fmt.Errorf("install: failed to get web ui leaf cert for verification (%s)", err)
-		}
-
-		// convert pem to DER for comparison
-		pemBlock, _ := pem.Decode(certPem)
-
-		// verify cert is the correct one
-		certVerified := bytes.Equal(leafCert.Raw, pemBlock.Bytes)
-		if !certVerified {
-			return errors.New("install: web ui leaf cert does not match new cert")
-		}
-
-		app.stdLogger.Println("install: ups web ui cert verified")
-	}
-
 	return nil
 }
diff --git a/pkg/app/config.go b/pkg/app/config.go
index 7edf216..e8ff1fc 100644
--- a/pkg/app/config.go
+++ b/pkg/app/config.go
@@ -33,14 +33,11 @@ type config struct {
 	}
 	install struct {
 		keyCertPemCfg
-		hostname       *string
-		sshport        *int
+		hostAndPort    *string
 		fingerprint    *string
 		username       *string
 		password       *string
 		restartWebUI   *bool
-		webUISSLPort   *int
-		skipVerify     *bool
 		insecureCipher *bool
 	}
 }
@@ -71,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 key in pem format")
+	cfg.create.keyPemFilePath = createFlags.StringLong("keyfile", "", "path and filename of the rsa-1024 or rsa-2048 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 key in pem format")
+	cfg.create.keyPem = createFlags.StringLong("keypem", "", "string of the rsa-1024 or rsa-2048 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")
@@ -91,23 +88,20 @@ 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 key in pem format")
+	cfg.install.keyPemFilePath = installFlags.StringLong("keyfile", "", "path and filename of the rsa-1024 or rsa-2048 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 key in pem format")
+	cfg.install.keyPem = installFlags.StringLong("keypem", "", "string of the rsa-1024 or rsa-2048 key in pem format")
 	cfg.install.certPem = installFlags.StringLong("certpem", "", "string of the certificate in pem format")
-	cfg.install.hostname = installFlags.StringLong("hostname", "", "hostname of the apc ups to install the certificate on")
-	cfg.install.sshport = installFlags.IntLong("sshport", 22, "apc ups ssh port number")
+	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")
 	cfg.install.username = installFlags.StringLong("username", "", "username to login to the apc ups")
 	cfg.install.password = installFlags.StringLong("password", "", "password to login to the apc ups")
 	cfg.install.restartWebUI = installFlags.BoolLong("restartwebui", "some devices may need a webui restart to begin using the new cert, enabling this option sends the restart command after the p15 is installed")
-	cfg.install.webUISSLPort = installFlags.IntLong("sslport", 443, "apc ups ssl webui port number")
-	cfg.install.skipVerify = installFlags.BoolLong("skipverify", "the tool will try to connect to the UPS web UI to verify install success; this flag disables that check")
 	cfg.install.insecureCipher = installFlags.BoolLong("insecurecipher", "allows the use of insecure ssh ciphers (NOT recommended)")
 
 	installCmd := &ff.Command{
 		Name:      "install",
-		Usage:     "apc-p15-tool install --keyfile key.pem --certfile cert.pem --hostname example.com --fingerprint 123abc --username apc --password test",
+		Usage:     "apc-p15-tool install --keyfile key.pem --certfile cert.pem --apchost example.com:22 --fingerprint 123abc --username apc --password test",
 		ShortHelp: "install the specified key and cert pem files on an apc ups (they will be converted to a comaptible p15 file)",
 		Flags:     installFlags,
 		Exec:      app.cmdInstall,
diff --git a/pkg/app/pem_to_p15.go b/pkg/app/pem_to_p15.go
index d48d4a8..e376bc6 100644
--- a/pkg/app/pem_to_p15.go
+++ b/pkg/app/pem_to_p15.go
@@ -3,22 +3,13 @@ package app
 import (
 	"apc-p15-tool/pkg/pkcs15"
 	"fmt"
-	"slices"
 )
 
-// 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.
+// 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.
 func (app *app) pemToAPCP15(keyPem, certPem []byte, parentCmdName string) (keyFile []byte, apcKeyCertFile []byte, err error) {
-	app.stdLogger.Printf("%s: making apc p15 file(s) content from pem", parentCmdName)
+	app.stdLogger.Printf("%s: making apc p15 file from pem", parentCmdName)
 
 	// make p15 struct
 	p15, err := pkcs15.ParsePEMToPKCS15(keyPem, certPem)
@@ -26,40 +17,24 @@ 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 parsed pem files", parentCmdName)
+	app.stdLogger.Printf("%s: successfully loaded pem files", parentCmdName)
 
-	// make key file (always)
-	keyFile, err = p15.ToP15Key()
+	// make file bytes
+	keyCertFile, keyFile, err := p15.ToP15Files()
 	if err != nil {
-		return nil, nil, fmt.Errorf("%s: failed to make p15 key file (%w)", parentCmdName, err)
+		return nil, nil, fmt.Errorf("%s: failed to make p15 file (%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)
+	// 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: apc p15 file(s) data succesfully generated", parentCmdName)
+	// combine header with file
+	apcKeyCertFile = append(apcHeader, keyCertFile...)
+
+	app.stdLogger.Printf("%s: apc p15 file data succesfully generated", parentCmdName)
 
 	return keyFile, apcKeyCertFile, nil
 }
diff --git a/pkg/pkcs15/encrypted_envelope.go b/pkg/pkcs15/encrypted_envelope.go
index 71433d1..cead3c8 100644
--- a/pkg/pkcs15/encrypted_envelope.go
+++ b/pkg/pkcs15/encrypted_envelope.go
@@ -21,19 +21,14 @@ const (
 	apcKEKIterations = 5000
 )
 
-// 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
-	}
-
+// 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) {
 	// calculate values for the object
 	kekSalt := make([]byte, 8)
 	_, err := rand.Read(kekSalt)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	// kek hash alg
@@ -47,7 +42,7 @@ func (p15 *pkcs15KeyCert) computeEncryptedKeyEnvelope() error {
 	// make DES cipher from KEK for CEK
 	cekDesCipher, err := des.NewTripleDESCipher(kek)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	// cek (16 bytes for authEnc128) -- see: rfc3211
@@ -55,7 +50,7 @@ func (p15 *pkcs15KeyCert) computeEncryptedKeyEnvelope() error {
 	cek := make([]byte, cekLen)
 	_, err = rand.Read(cek)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	// LEN + Check Val [3]
@@ -76,7 +71,7 @@ func (p15 *pkcs15KeyCert) computeEncryptedKeyEnvelope() error {
 	cekPadding := make([]byte, cekPadLen)
 	_, err = rand.Read(cekPadding)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	wrappedCEK = append(wrappedCEK, cekPadding...)
@@ -85,7 +80,7 @@ func (p15 *pkcs15KeyCert) computeEncryptedKeyEnvelope() error {
 	cekEncryptSalt := make([]byte, 8)
 	_, err = rand.Read(cekEncryptSalt)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	cekEncrypter := cipher.NewCBCEncrypter(cekDesCipher, cekEncryptSalt)
@@ -99,13 +94,13 @@ func (p15 *pkcs15KeyCert) computeEncryptedKeyEnvelope() error {
 	contentEncSalt := make([]byte, 8)
 	_, err = rand.Read(contentEncSalt)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	contentEncryptKey := pbkdf2.Key(cek, []byte("encryption"), 1, 24, sha1.New)
 	contentDesCipher, err := des.NewTripleDESCipher(contentEncryptKey)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	// envelope content (that will be encrypted)
@@ -156,7 +151,7 @@ func (p15 *pkcs15KeyCert) computeEncryptedKeyEnvelope() error {
 	// make MAC
 	_, err = macHasher.Write(hashMe)
 	if err != nil {
-		return err
+		return nil, err
 	}
 	mac := macHasher.Sum(nil)
 
@@ -223,7 +218,5 @@ func (p15 *pkcs15KeyCert) computeEncryptedKeyEnvelope() error {
 		finalEnv = append(finalEnv, envelope[i]...)
 	}
 
-	// set p15 struct envelope
-	p15.envelopedPrivateKey = finalEnv
-	return nil
+	return finalEnv, nil
 }
diff --git a/pkg/pkcs15/keyid.go b/pkg/pkcs15/keyid.go
index 08a3ce4..76f4297 100644
--- a/pkg/pkcs15/keyid.go
+++ b/pkg/pkcs15/keyid.go
@@ -2,8 +2,6 @@ package pkcs15
 
 import (
 	"apc-p15-tool/pkg/tools/asn1obj"
-	"crypto/ecdsa"
-	"crypto/rsa"
 	"crypto/sha1"
 	"encoding/binary"
 	"math/big"
@@ -13,6 +11,22 @@ import (
 func (p15 *pkcs15KeyCert) keyId() []byte {
 	// object to hash is just the RawSubjectPublicKeyInfo
 
+	// Create Object to hash
+	// hashObj := asn1obj.Sequence([][]byte{
+	// 	asn1obj.Sequence([][]byte{
+	// 		// Key is RSA
+	// 		asn1obj.ObjectIdentifier(asn1obj.OIDrsaEncryptionPKCS1),
+	// 		asn1.NullBytes,
+	// 	}),
+	// 	// BIT STRING of rsa key public key
+	// 	asn1obj.BitString(
+	// 		asn1obj.Sequence([][]byte{
+	// 			asn1obj.Integer(p15.key.N),
+	// 			asn1obj.Integer((big.NewInt(int64(p15.key.E)))),
+	// 		}),
+	// 	),
+	// })
+
 	// SHA-1 Hash
 	hasher := sha1.New()
 	_, err := hasher.Write(p15.cert.RawSubjectPublicKeyInfo)
@@ -110,32 +124,18 @@ func (p15 *pkcs15KeyCert) keyIdInt7() []byte {
 }
 
 // keyIdInt8 returns the sequence for keyId with INT val of 8; This value is equivelant
-// to "pgp", which is PGP v3 key Id.
+// to "pgp", which is PGP v3 key Id. This value is just the last 8 bytes of the public
+// key N value
 func (p15 *pkcs15KeyCert) keyIdInt8() []byte {
-	var keyIdVal []byte
-
-	switch privKey := p15.key.(type) {
-	case *rsa.PrivateKey:
-		// RSA: The ID value is just the last 8 bytes of the public key N value
-		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 unexpected key type
-		panic("key id 8 for key is unexpected and unsupported")
-	}
+	nBytes := p15.key.N.Bytes()
 
 	// object to return
-	idObj := asn1obj.Sequence([][]byte{
+	obj := asn1obj.Sequence([][]byte{
 		asn1obj.Integer(big.NewInt(8)),
-		asn1obj.OctetString(keyIdVal),
+		asn1obj.OctetString(nBytes[len(nBytes)-8:]),
 	})
 
-	return idObj
+	return obj
 }
 
 // bigIntToMpi returns the MPI (as defined in RFC 4880 s 3.2) from a given
@@ -156,44 +156,33 @@ func (p15 *pkcs15KeyCert) keyIdInt9() []byte {
 	// Public-Key packet starting with the version field.  The Key ID is the
 	// low-order 64 bits of the fingerprint.
 
-	// first make the public key packet
+	// the entire Public-Key packet
 	publicKeyPacket := []byte{}
 
 	// starting with the version field (A one-octet version number (4)).
 	publicKeyPacket = append(publicKeyPacket, byte(4))
 
 	// A four-octet number denoting the time that the key was created.
+	time := make([]byte, 4)
+
 	// NOTE: use cert validity start as proxy for key creation since key pem
 	// doesn't actually contain a created at time -- in reality notBefore tends
 	// to be ~ 1 hour ish BEFORE the cert was even created. Key would also
 	// obviously have to be created prior to the cert creation.
-	time := make([]byte, 4)
 	binary.BigEndian.PutUint32(time, uint32(p15.cert.NotBefore.Unix()))
 	publicKeyPacket = append(publicKeyPacket, time...)
 
-	// the next part is key type specific
-	switch privKey := p15.key.(type) {
-	case *rsa.PrivateKey:
-		// A one-octet number denoting the public-key algorithm of this key.
-		// 1 - RSA (Encrypt or Sign) [HAC]
-		publicKeyPacket = append(publicKeyPacket, byte(1))
+	// A one-octet number denoting the public-key algorithm of this key.
+	// 1 - RSA (Encrypt or Sign) [HAC]
+	publicKeyPacket = append(publicKeyPacket, byte(1))
 
-		// Algorithm-Specific Fields for RSA public keys:
-		// multiprecision integer (MPI) of RSA public modulus n
-		publicKeyPacket = append(publicKeyPacket, bigIntToMpi(privKey.N)...)
+	// Algorithm-Specific Fields for RSA public keys:
+	// multiprecision integer (MPI) of RSA public modulus n
+	publicKeyPacket = append(publicKeyPacket, bigIntToMpi(p15.key.N)...)
 
-		// MPI of RSA public encryption exponent e
-		e := big.NewInt(int64(privKey.PublicKey.E))
-		publicKeyPacket = append(publicKeyPacket, bigIntToMpi(e)...)
-
-	case *ecdsa.PrivateKey:
-		// don't use this key id, leave empty
-		return nil
-
-	default:
-		// panic if unexpected key type
-		panic("key id 9 for key is unexpected and unsupported")
-	}
+	// MPI of RSA public encryption exponent e
+	e := big.NewInt(int64(p15.key.PublicKey.E))
+	publicKeyPacket = append(publicKeyPacket, bigIntToMpi(e)...)
 
 	// Assemble the V4 byte array that will be hashed
 	// 0x99 (1 octet)
@@ -216,10 +205,10 @@ func (p15 *pkcs15KeyCert) keyIdInt9() []byte {
 	keyId := sha1Hash[len(sha1Hash)-8:]
 
 	// object to return
-	idObj := asn1obj.Sequence([][]byte{
+	obj := asn1obj.Sequence([][]byte{
 		asn1obj.Integer(big.NewInt(9)),
 		asn1obj.OctetString(keyId),
 	})
 
-	return idObj
+	return obj
 }
diff --git a/pkg/pkcs15/pem_decode.go b/pkg/pkcs15/pem_decode.go
index 2d51837..d4b8764 100644
--- a/pkg/pkcs15/pem_decode.go
+++ b/pkg/pkcs15/pem_decode.go
@@ -1,37 +1,28 @@
 package pkcs15
 
 import (
-	"crypto"
-	"crypto/ecdsa"
 	"crypto/rsa"
 	"crypto/tls"
 	"crypto/x509"
 	"encoding/pem"
 	"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")
-	errKeyWrongType         = errors.New("pkcs15: pem key: unsupported key type")
+	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 or 2,048 supported)")
 
 	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 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) {
+// 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
+func pemKeyDecode(keyPem []byte) (*rsa.PrivateKey, error) {
 	// decode
 	pemBlock, _ := pem.Decode([]byte(keyPem))
 	if pemBlock == nil {
@@ -39,11 +30,13 @@ func pemKeyDecode(keyPem []byte) (crypto.PrivateKey, error) {
 	}
 
 	// parsing depends on block type
-	var privateKey crypto.PrivateKey
+	var rsaKey *rsa.PrivateKey
 
 	switch pemBlock.Type {
 	case "RSA PRIVATE KEY": // PKCS1
-		rsaKey, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes)
+		var err error
+
+		rsaKey, err = x509.ParsePKCS1PrivateKey(pemBlock.Bytes)
 		if err != nil {
 			return nil, errPemKeyFailedToParse
 		}
@@ -54,27 +47,12 @@ func pemKeyDecode(keyPem []byte) (crypto.PrivateKey, error) {
 			return nil, fmt.Errorf("pkcs15: pem key: failed sanity check (%s)", err)
 		}
 
-		// verify supported rsa bitlen
-		if !slices.Contains(supportedRSASizes, rsaKey.N.BitLen()) {
-			return nil, errKeyWrongType
+		// verify proper bitlen
+		if rsaKey.N.BitLen() != 1024 && rsaKey.N.BitLen() != 2048 {
+			return nil, errPemKeyWrongType
 		}
 
 		// good to go
-		privateKey = rsaKey
-
-	case "EC PRIVATE KEY": // SEC1, ASN.1
-		ecdKey, err := x509.ParseECPrivateKey(pemBlock.Bytes)
-		if err != nil {
-			return nil, errPemKeyFailedToParse
-		}
-
-		// verify supported curve name
-		if !slices.Contains(supportedECDSACurves, ecdKey.Curve.Params().Name) {
-			return nil, errKeyWrongType
-		}
-
-		// good to go
-		privateKey = ecdKey
 
 	case "PRIVATE KEY": // PKCS8
 		pkcs8Key, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes)
@@ -84,31 +62,23 @@ func pemKeyDecode(keyPem []byte) (crypto.PrivateKey, error) {
 
 		switch pkcs8Key := pkcs8Key.(type) {
 		case *rsa.PrivateKey:
+			rsaKey = pkcs8Key
+
 			// basic sanity check
-			err = pkcs8Key.Validate()
+			err = rsaKey.Validate()
 			if err != nil {
 				return nil, fmt.Errorf("pkcs15: pem key: failed sanity check (%s)", err)
 			}
 
-			// verify supported rsa bitlen
-			if !slices.Contains(supportedRSASizes, pkcs8Key.N.BitLen()) {
-				return nil, errKeyWrongType
+			// verify proper bitlen
+			if rsaKey.N.BitLen() != 1024 && rsaKey.N.BitLen() != 2048 {
+				return nil, errPemKeyWrongType
 			}
 
 			// good to go
-			privateKey = pkcs8Key
-
-		case *ecdsa.PrivateKey:
-			// verify supported curve name
-			if !slices.Contains(supportedECDSACurves, pkcs8Key.Curve.Params().Name) {
-				return nil, errKeyWrongType
-			}
-
-			// good to go
-			privateKey = pkcs8Key
 
 		default:
-			return nil, errKeyWrongType
+			return nil, errPemKeyWrongType
 		}
 
 	default:
@@ -116,12 +86,12 @@ func pemKeyDecode(keyPem []byte) (crypto.PrivateKey, error) {
 	}
 
 	// if rsaKey is nil somehow, error
-	if reflect.ValueOf(privateKey).IsNil() {
+	if rsaKey == nil {
 		return nil, errors.New("pkcs15: pem key: rsa key unexpectedly nil (report bug to project repo)")
 	}
 
 	// success!
-	return privateKey, nil
+	return rsaKey, nil
 }
 
 // pemCertDecode attempts to decode a pem encoded byte slice and then attempts
diff --git a/pkg/pkcs15/pem_parse.go b/pkg/pkcs15/pem_parse.go
index 19e44f1..dcd899a 100644
--- a/pkg/pkcs15/pem_parse.go
+++ b/pkg/pkcs15/pem_parse.go
@@ -1,8 +1,6 @@
 package pkcs15
 
 import (
-	"crypto"
-	"crypto/ecdsa"
 	"crypto/rsa"
 	"crypto/x509"
 )
@@ -10,61 +8,8 @@ import (
 // pkcs15KeyCert holds the data for a key and certificate pair; it provides
 // various methods to transform pkcs15 data
 type pkcs15KeyCert struct {
-	key  crypto.PrivateKey
+	key  *rsa.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
@@ -82,17 +27,10 @@ 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 0c2214d..19392f2 100644
--- a/pkg/pkcs15/pem_to_p15.go
+++ b/pkg/pkcs15/pem_to_p15.go
@@ -2,10 +2,7 @@ package pkcs15
 
 import (
 	"apc-p15-tool/pkg/tools/asn1obj"
-	"crypto/ecdsa"
-	"crypto/rsa"
 	"encoding/asn1"
-	"fmt"
 	"math/big"
 )
 
@@ -15,87 +12,39 @@ 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() (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 =
+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{
 			asn1obj.Sequence([][]byte{
-				// commonObjectAttributes - Label
-				asn1obj.Sequence([][]byte{
-					asn1obj.UTF8String(apcKeyLabel),
+				// AuthEnvelopedData Type ([4])
+				asn1obj.ExplicitCompound(4, [][]byte{
+					keyEnvelope,
 				}),
-				// 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
-	certObj := asn1obj.Sequence([][]byte{
+	cert := asn1obj.Sequence([][]byte{
 		// commonObjectAttributes - Label
 		asn1obj.Sequence([][]byte{
 			asn1obj.UTF8String(apcKeyLabel),
@@ -109,7 +58,6 @@ func (p15 *pkcs15KeyCert) ToP15KeyCert() (keyCert []byte, err error) {
 				p15.keyIdInt3(),
 				p15.keyIdInt6(),
 				p15.keyIdInt7(),
-				// 8 & 9 will return nil for EC keys (effectively omitting them)
 				p15.keyIdInt8(),
 				p15.keyIdInt9(),
 			}),
@@ -128,7 +76,7 @@ func (p15 *pkcs15KeyCert) ToP15KeyCert() (keyCert []byte, err error) {
 		}),
 	})
 
-	// build the object
+	// build the file
 
 	// ContentInfo
 	keyCert = asn1obj.Sequence([][]byte{
@@ -143,12 +91,12 @@ func (p15 *pkcs15KeyCert) ToP15KeyCert() (keyCert []byte, err error) {
 				asn1obj.Sequence([][]byte{
 					asn1obj.ExplicitCompound(0, [][]byte{
 						asn1obj.ExplicitCompound(0, [][]byte{
-							privKeyObj,
+							privateKey,
 						}),
 					}),
 					asn1obj.ExplicitCompound(4, [][]byte{
 						asn1obj.ExplicitCompound(0, [][]byte{
-							certObj,
+							cert,
 						}),
 					}),
 				}),
@@ -162,212 +110,129 @@ func (p15 *pkcs15KeyCert) ToP15KeyCert() (keyCert []byte, err error) {
 // 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() (key []byte, err error) {
-	// encrypted envelope is required
-	err = p15.computeEncryptedKeyEnvelope()
-	if err != nil {
-		return nil, err
-	}
+func (p15 *pkcs15KeyCert) toP15Key(keyEnvelope []byte) (key []byte, err error) {
+	// private key object (slightly different than the key+cert format)
+	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)}),
+		}),
 
-	// create private and public key objects
-	var pubKeyObj, privKeyObj []byte
-
-	switch privKey := p15.key.(type) {
-	case *rsa.PrivateKey:
-		// private key object (slightly different than the key+cert format)
-		privKeyObj =
+		//
+		asn1obj.ExplicitCompound(0, [][]byte{
 			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.Sequence([][]byte{
-						asn1obj.ExplicitCompound(0, [][]byte{
-							p15.keyIdInt2(),
-							p15.keyIdInt8(),
-							p15.keyIdInt9(),
-						}),
-					}),
+					p15.keyIdInt2(),
+					p15.keyIdInt8(),
+					p15.keyIdInt9(),
 				}),
+			}),
+		}),
 
-				// ObjectValue - indirect-protected
-				asn1obj.ExplicitCompound(1, [][]byte{
-					asn1obj.Sequence([][]byte{
-						// AuthEnvelopedData Type ([4])
-						asn1obj.ExplicitCompound(4, [][]byte{
-							p15.envelopedPrivateKey,
-						}),
-					}),
-				}),
-			})
-
-		// pub key stub
-		pubKeyObj =
+		// ObjectValue - indirect-protected
+		asn1obj.ExplicitCompound(1, [][]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)}),
+				// AuthEnvelopedData Type ([4])
+				asn1obj.ExplicitCompound(4, [][]byte{
+					keyEnvelope,
 				}),
+			}),
+		}),
+	})
 
-				asn1obj.ExplicitCompound(1, [][]byte{
-					asn1obj.Sequence([][]byte{
+	// 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)),
+				asn1obj.Sequence([][]byte{
+					// [0] Private Key
+					asn1obj.ExplicitCompound(0, [][]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(),
+							privateKey,
 						}),
 					}),
-				}),
-
-				// 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{
+					// [1] Public Key
+					asn1obj.ExplicitCompound(1, [][]byte{
 						asn1obj.ExplicitCompound(0, [][]byte{
 							asn1obj.Sequence([][]byte{
+								// commonObjectAttributes - Label
 								asn1obj.Sequence([][]byte{
-									asn1obj.ObjectIdentifier(asn1obj.OIDecPublicKey),
-									asn1obj.ObjectIdentifier(curveOID),
+									asn1obj.UTF8String(apcKeyLabel),
+								}),
+								// CommonKeyAttributes
+								asn1obj.Sequence([][]byte{
+									asn1obj.OctetString(p15.keyId()),
+									asn1obj.BitString([]byte{byte(0b10000010)}),
+									asn1obj.BitString([]byte{byte(0b01000000)}),
 								}),
-								asn1obj.BitString(ecdhKey.Bytes()),
-							}),
-						}),
-					}),
-				}),
-			})
 
-	default:
-		// bad key type
-		return nil, errKeyWrongType
-	}
-
-	// assemble complete object
-	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)),
-					asn1obj.Sequence([][]byte{
-						// [0] Private Keys
-						asn1obj.ExplicitCompound(0, [][]byte{
-							asn1obj.ExplicitCompound(0, [][]byte{
-								privKeyObj,
-							}),
-						}),
-						// [1] Public Keys
-						asn1obj.ExplicitCompound(1, [][]byte{
-							asn1obj.ExplicitCompound(0, [][]byte{
-								pubKeyObj,
+								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(p15.key.PublicKey.N),
+														asn1obj.Integer(big.NewInt(int64(p15.key.PublicKey.E))),
+													}),
+												),
+											}),
+										}),
+										// not 100% certain but appears to be rsa key byte len
+										asn1obj.Integer(big.NewInt(int64(p15.key.PublicKey.N.BitLen() / 8))),
+									}),
+								}),
 							}),
 						}),
 					}),
 				}),
 			}),
-		})
+		}),
+	})
 
 	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 59b538e..8c6b0fb 100644
--- a/pkg/pkcs15/private_key.go
+++ b/pkg/pkcs15/private_key.go
@@ -1,41 +1,24 @@
 package pkcs15
 
-import (
-	"apc-p15-tool/pkg/tools/asn1obj"
-	"crypto/ecdsa"
-	"crypto/rsa"
-)
+import "apc-p15-tool/pkg/tools/asn1obj"
 
 // privateKeyObject returns the ASN.1 representation of a private key
 func (p15 *pkcs15KeyCert) privateKeyObject() []byte {
-	var privKeyObj []byte
+	// ensure all expected vals are available
+	p15.key.Precompute()
 
-	switch privKey := p15.key.(type) {
-	case *rsa.PrivateKey:
-		privKey.Precompute()
+	pkey := asn1obj.Sequence([][]byte{
+		// P
+		asn1obj.IntegerExplicitValue(3, p15.key.Primes[0]),
+		// Q
+		asn1obj.IntegerExplicitValue(4, p15.key.Primes[1]),
+		// Dp
+		asn1obj.IntegerExplicitValue(5, p15.key.Precomputed.Dp),
+		// Dq
+		asn1obj.IntegerExplicitValue(6, p15.key.Precomputed.Dq),
+		// Qinv
+		asn1obj.IntegerExplicitValue(7, p15.key.Precomputed.Qinv),
+	})
 
-		// ensure all expected vals are available
-		privKeyObj = asn1obj.Sequence([][]byte{
-			// P
-			asn1obj.IntegerExplicitValue(3, privKey.Primes[0]),
-			// Q
-			asn1obj.IntegerExplicitValue(4, privKey.Primes[1]),
-			// Dp
-			asn1obj.IntegerExplicitValue(5, privKey.Precomputed.Dp),
-			// Dq
-			asn1obj.IntegerExplicitValue(6, privKey.Precomputed.Dq),
-			// Qinv
-			asn1obj.IntegerExplicitValue(7, privKey.Precomputed.Qinv),
-		})
-
-	case *ecdsa.PrivateKey:
-		// Only private piece is the integer D
-		privKeyObj = asn1obj.Integer(privKey.D)
-
-	default:
-		// panic if unsupported key
-		panic("private key type is unexpected and unsupported")
-	}
-
-	return privKeyObj
+	return pkey
 }
diff --git a/pkg/tools/asn1obj/oid.go b/pkg/tools/asn1obj/oid.go
index 70009c2..3975ded 100644
--- a/pkg/tools/asn1obj/oid.go
+++ b/pkg/tools/asn1obj/oid.go
@@ -11,10 +11,6 @@ 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