diff --git a/pkg/app/cmd_install.go b/pkg/app/cmd_install.go
index eacda53..d94c00c 100644
--- a/pkg/app/cmd_install.go
+++ b/pkg/app/cmd_install.go
@@ -145,7 +145,7 @@ func (app *app) cmdInstall(cmdCtx context.Context, args []string) error {
 		// 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")
+			return errors.New("install: web ui leaf cert does not match new cert (your cert may not be compatible with NMC; check for WARNINGs in this tool's output)")
 		}
 
 		app.stdLogger.Println("install: ups web ui cert verified")
diff --git a/pkg/app/pem_to_p15.go b/pkg/app/pem_to_p15.go
index d48d4a8..c878abb 100644
--- a/pkg/app/pem_to_p15.go
+++ b/pkg/app/pem_to_p15.go
@@ -2,8 +2,11 @@ package app
 
 import (
 	"apc-p15-tool/pkg/pkcs15"
+	"crypto/x509"
+	"encoding/asn1"
 	"fmt"
 	"slices"
+	"time"
 )
 
 // list of keys supported by the NMC2
@@ -13,6 +16,32 @@ var nmc2SupportedKeyTypes = []pkcs15.KeyType{
 	pkcs15.KeyTypeRSA3072, // officially not supported but works
 }
 
+// known good signing algorithms
+var knownSupportedNMC2SigningAlgs = []x509.SignatureAlgorithm{
+	x509.SHA256WithRSA,
+}
+
+var knownSupportedNMC3SigningAlgs = append(knownSupportedNMC2SigningAlgs, []x509.SignatureAlgorithm{
+	x509.ECDSAWithSHA384,
+}...)
+
+// known supported cert extensions
+var knownSupportedCriticalOIDs = []asn1.ObjectIdentifier{
+	{2, 5, 29, 15}, // keyUsage
+	{2, 5, 29, 19}, // basicConstraints
+	{2, 5, 29, 17}, // subjectAltName
+}
+
+var knownSupportedOIDs = append(knownSupportedCriticalOIDs, []asn1.ObjectIdentifier{
+	{2, 5, 29, 37},                     // extKeyUsage
+	{2, 5, 29, 14},                     // subjectKeyIdentifier
+	{2, 5, 29, 35},                     // authorityKeyIdentifier
+	{1, 3, 6, 1, 5, 5, 7, 1, 1},        // authorityInfoAccess
+	{2, 5, 29, 32},                     // certificatePolicies
+	{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2}, // googleSignedCertificateTimestamp
+	{2, 5, 29, 31},                     // cRLDistributionPoints
+}...)
+
 // 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
@@ -37,7 +66,10 @@ func (app *app) pemToAPCP15(keyPem, certPem []byte, parentCmdName string) (keyFi
 	app.stdLogger.Printf("%s: successfully generated p15 key file content", parentCmdName)
 
 	// check key type for compat with NMC2
+	nmc2KeyType := false
 	if slices.Contains(nmc2SupportedKeyTypes, p15.KeyType()) {
+		nmc2KeyType = true
+
 		app.stdLogger.Printf("%s: key type is supported by NMC2, generating p15 key+cert file content...", parentCmdName)
 
 		// make file bytes
@@ -54,11 +86,87 @@ func (app *app) pemToAPCP15(keyPem, certPem []byte, parentCmdName string) (keyFi
 
 		// 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)
 	}
 
+	// check various parts of cert and log compatibility warnings
+	warned := false
+
+	// key not supported for NMC2
+	if !nmc2KeyType {
+		app.stdLogger.Printf("WARNING: %s: key type is %s and is not supported by NMC2.", parentCmdName, p15.KeyType().String())
+		warned = true
+	}
+
+	// signature algorithm (see: https://github.com/gregtwallace/apc-p15-tool/issues/18)
+	if !nmc2KeyType {
+		// definitely not for NMC2
+		if !slices.Contains(knownSupportedNMC3SigningAlgs, p15.Cert.SignatureAlgorithm) {
+			app.stdLogger.Printf("WARNING: %s: Certificate signing algorithm is %s and it is not known if NMC3 supports this algorithm.", parentCmdName, p15.Cert.SignatureAlgorithm.String())
+			warned = true
+		}
+	} else {
+		// could be for either NMC2 or NMC3
+		if !slices.Contains(knownSupportedNMC2SigningAlgs, p15.Cert.SignatureAlgorithm) {
+			if !slices.Contains(knownSupportedNMC3SigningAlgs, p15.Cert.SignatureAlgorithm) {
+				// not in NMC2 or NMC3 list
+				app.stdLogger.Printf("WARNING: %s: Certificate signing algorithm is %s and is not supported by NMC2. It is also not known if NMC3 supports this algorithm.", parentCmdName, p15.Cert.SignatureAlgorithm.String())
+			} else {
+				// not in NMC2 list, but is in NMC3 list
+				app.stdLogger.Printf("WARNING: %s: Certificate signing algorithm is %s and it does not support NMC2.", parentCmdName, p15.Cert.SignatureAlgorithm.String())
+			}
+			warned = true
+		}
+	}
+
+	// if support by 2, check 2 list
+	// if not found on 2 list, check 3 list
+
+	// check validity dates
+	if time.Now().Before(p15.Cert.NotBefore) {
+		app.stdLogger.Printf("WARNING: %s: Current time (%s) is before certificate's NotBefore time (%s).",
+			parentCmdName, time.Now().Format(timeLoggingFormat), p15.Cert.NotBefore.Format(timeLoggingFormat))
+		warned = true
+	}
+
+	if time.Now().After(p15.Cert.NotAfter) {
+		app.stdLogger.Printf("WARNING: %s: Current time (%s) is after certificate's NotAfter time (%s).",
+			parentCmdName, time.Now().Format(timeLoggingFormat), p15.Cert.NotAfter.Format(timeLoggingFormat))
+		warned = true
+	}
+
+	// check extensions against known working extensions
+	for _, extension := range p15.Cert.Extensions {
+		// critical or not?
+		okOIDs := knownSupportedCriticalOIDs
+		criticalLogMsg := "Critical "
+		if !extension.Critical {
+			okOIDs = knownSupportedOIDs
+			criticalLogMsg = ""
+		}
+
+		// validate OIDs
+		ok := false
+		for _, okOID := range okOIDs {
+			if okOID.Equal(extension.Id) {
+				ok = true
+				break
+			}
+		}
+
+		if !ok {
+			app.stdLogger.Printf("WARNING: %s: %sExtension %s may not be supported by NMC.", parentCmdName, criticalLogMsg, extension.Id.String())
+		}
+	}
+
+	// log a message about possible failure
+	if warned {
+		app.stdLogger.Printf("WARNING: %s: Possible certificate compatibility issues were detected. If the resulting p15 file "+
+			"does not work with your NMC (e.g., a self-signed certificate is regenerated after you try to install the p15), "+
+			"modify your certificate to resolve the warnings and try again.", parentCmdName)
+	}
+
+	// end compatibility warnings
+
 	app.stdLogger.Printf("%s: apc p15 file(s) data succesfully generated", parentCmdName)
 
 	return keyFile, apcKeyCertFile, nil
diff --git a/pkg/pkcs15/keyid.go b/pkg/pkcs15/keyid.go
index 08a3ce4..cac7301 100644
--- a/pkg/pkcs15/keyid.go
+++ b/pkg/pkcs15/keyid.go
@@ -15,7 +15,7 @@ func (p15 *pkcs15KeyCert) keyId() []byte {
 
 	// SHA-1 Hash
 	hasher := sha1.New()
-	_, err := hasher.Write(p15.cert.RawSubjectPublicKeyInfo)
+	_, err := hasher.Write(p15.Cert.RawSubjectPublicKeyInfo)
 	if err != nil {
 		panic(err)
 	}
@@ -46,9 +46,9 @@ func (p15 *pkcs15KeyCert) keyIdInt3() []byte {
 	// object to hash
 	hashObj := asn1obj.Sequence([][]byte{
 		// issuerDistinguishedName
-		p15.cert.RawIssuer,
+		p15.Cert.RawIssuer,
 		// serialNumber
-		asn1obj.Integer(p15.cert.SerialNumber),
+		asn1obj.Integer(p15.Cert.SerialNumber),
 	})
 
 	// SHA-1 Hash
@@ -74,7 +74,7 @@ func (p15 *pkcs15KeyCert) keyIdInt6() []byte {
 
 	// SHA-1 Hash
 	hasher := sha1.New()
-	_, err := hasher.Write(p15.cert.RawIssuer)
+	_, err := hasher.Write(p15.Cert.RawIssuer)
 	if err != nil {
 		panic(err)
 	}
@@ -95,7 +95,7 @@ func (p15 *pkcs15KeyCert) keyIdInt7() []byte {
 
 	// SHA-1 Hash
 	hasher := sha1.New()
-	_, err := hasher.Write(p15.cert.RawSubject)
+	_, err := hasher.Write(p15.Cert.RawSubject)
 	if err != nil {
 		panic(err)
 	}
@@ -168,7 +168,7 @@ func (p15 *pkcs15KeyCert) keyIdInt9() []byte {
 	// 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()))
+	binary.BigEndian.PutUint32(time, uint32(p15.Cert.NotBefore.Unix()))
 	publicKeyPacket = append(publicKeyPacket, time...)
 
 	// the next part is key type specific
diff --git a/pkg/pkcs15/pem_parse.go b/pkg/pkcs15/pem_parse.go
index 19e44f1..9df0ecd 100644
--- a/pkg/pkcs15/pem_parse.go
+++ b/pkg/pkcs15/pem_parse.go
@@ -10,8 +10,8 @@ import (
 // pkcs15KeyCert holds the data for a key and certificate pair; it provides
 // various methods to transform pkcs15 data
 type pkcs15KeyCert struct {
+	Cert *x509.Certificate
 	key  crypto.PrivateKey
-	cert *x509.Certificate
 	// store the encrypted enveloped Private Key for re-use
 	envelopedPrivateKey []byte
 }
@@ -32,6 +32,31 @@ const (
 	KeyTypeUnknown
 )
 
+// String returns the private key type in a log friendly string format.
+func (keyType KeyType) String() string {
+	switch keyType {
+	case KeyTypeRSA1024:
+		return "RSA 1024-bit"
+	case KeyTypeRSA2048:
+		return "RSA 2048-bit"
+	case KeyTypeRSA3072:
+		return "RSA 3072-bit"
+	case KeyTypeRSA4096:
+		return "RSA 4096-bit"
+
+	case KeyTypeECP256:
+		return "ECDSA P-256"
+	case KeyTypeECP384:
+		return "ECDSA P-384"
+	case KeyTypeECP521:
+		return "ECDSA P-521"
+
+	default:
+	}
+
+	return "unknown key type"
+}
+
 // KeyType returns the private key type
 func (p15 *pkcs15KeyCert) KeyType() KeyType {
 	switch pKey := p15.key.(type) {
@@ -85,7 +110,7 @@ func ParsePEMToPKCS15(keyPem, certPem []byte) (*pkcs15KeyCert, error) {
 	// create p15 struct
 	p15 := &pkcs15KeyCert{
 		key:  key,
-		cert: cert,
+		Cert: cert,
 	}
 
 	// pre-calculate encrypted envelope
diff --git a/pkg/pkcs15/pem_to_p15.go b/pkg/pkcs15/pem_to_p15.go
index 0c2214d..a68aba2 100644
--- a/pkg/pkcs15/pem_to_p15.go
+++ b/pkg/pkcs15/pem_to_p15.go
@@ -43,9 +43,9 @@ func (p15 *pkcs15KeyCert) ToP15KeyCert() (keyCert []byte, err error) {
 					// CommonKeyAttributes - accessFlags (trailing 0s will drop)
 					asn1obj.BitString([]byte{byte(0b10110000)}),
 					// CommonKeyAttributes - startDate
-					asn1obj.GeneralizedTime(p15.cert.NotBefore),
+					asn1obj.GeneralizedTime(p15.Cert.NotBefore),
 					// CommonKeyAttributes - [0] endDate
-					asn1obj.GeneralizedTimeExplicitValue(0, p15.cert.NotAfter),
+					asn1obj.GeneralizedTimeExplicitValue(0, p15.Cert.NotAfter),
 				}),
 				// ObjectValue - indirect-protected
 				asn1obj.ExplicitCompound(1, [][]byte{
@@ -74,9 +74,9 @@ func (p15 *pkcs15KeyCert) ToP15KeyCert() (keyCert []byte, err error) {
 					// CommonKeyAttributes - accessFlags (trailing 0s will drop)
 					asn1obj.BitString([]byte{byte(0b10110000)}),
 					// CommonKeyAttributes - startDate
-					asn1obj.GeneralizedTime(p15.cert.NotBefore),
+					asn1obj.GeneralizedTime(p15.Cert.NotBefore),
 					// CommonKeyAttributes - [0] endDate
-					asn1obj.GeneralizedTimeExplicitValue(0, p15.cert.NotAfter),
+					asn1obj.GeneralizedTimeExplicitValue(0, p15.Cert.NotAfter),
 				}),
 				// ObjectValue - indirect-protected
 				asn1obj.ExplicitCompound(1, [][]byte{
@@ -114,15 +114,15 @@ func (p15 *pkcs15KeyCert) ToP15KeyCert() (keyCert []byte, err error) {
 				p15.keyIdInt9(),
 			}),
 			// CommonKeyAttributes - startDate
-			asn1obj.GeneralizedTime(p15.cert.NotBefore),
+			asn1obj.GeneralizedTime(p15.Cert.NotBefore),
 			// CommonKeyAttributes - [4] endDate
-			asn1obj.GeneralizedTimeExplicitValue(4, p15.cert.NotAfter),
+			asn1obj.GeneralizedTimeExplicitValue(4, p15.Cert.NotAfter),
 		}),
 		// actual certificate itself
 		asn1obj.ExplicitCompound(1, [][]byte{
 			asn1obj.Sequence([][]byte{
 				asn1obj.ExplicitCompound(0, [][]byte{
-					p15.cert.Raw,
+					p15.Cert.Raw,
 				}),
 			}),
 		}),