Why an SSL certificate won't import into CompleteFTP, and how to fix it

Almost every certificate that fails to import into CompleteFTP fails for one of a small number of reasons, and the message you get is the same regardless of which one it is, a dialog titled Could not load certificate, saying:

Failed to load server certificate from <path>. Please ensure a private key has been supplied and that the correct password has been used

That single message covers a wrong password, a key that doesn't belong to the certificate, a key in a format CompleteFTP won't parse, a file whose extension selects the wrong parser, and a Windows key-store permission problem. This article separates them and gives the command-line route for Linux.

It covers the server certificate used for FTPS and HTTPS. SSH/SFTP host keys and user public keys are a different mechanism and are not covered here, an SSL certificate has no effect on SFTP.

The short version

  1. The private key file's extension decides how it is parsed. In CompleteFTP Manager the private key file must be named .pvk (Microsoft PVK) or .pem (OpenSSL PEM). A .key or .pfx file selected at the key prompt is rejected, rename a PEM-format key to .pem.
  2. A private key generated by CompleteFTP's CSR wizard is PEM, not PVK, and is not encrypted, from 25.1.0 onward. It is written in PEM format with a .pem extension, and the password the wizard asked for is discarded, so when prompted for it at import time an empty password works, whatever you typed. On 25.0.6 and earlier the wizard wrote an encrypted PVK and the password is real; open the file to tell which you have, PEM begins -----BEGIN.
  3. Know which password you are being asked for. For a .pfx/.p12 it is the password on the PKCS#12 file, and it is always required. For a separate private key file it is the key's own password, which is used only if that key is actually encrypted, if it is not, any value including blank is accepted. Either way, a rejected password is usually not a password problem. See "When it doesn't work" below.
  4. Only RSA keys work. An EC/ECDSA certificate cannot be used as a CompleteFTP server certificate.
  5. Click APPLY CHANGES. The import dialog writes the certificate into the pending configuration; nothing reaches the server until you apply.

On Linux, or to script it, there is no dialog, use the CLI:

completeftp site cert import "Default Site" /path/to/certificate.crt "" /path/to/private.key ""

The CLI takes the certificate, its password, the private key file and the key's password, and applies the change itself. Pass "" for a password that doesn't exist.

What CompleteFTP actually accepts

There are two file slots: a certificate file, and, only if the certificate file does not already contain the private key, a private key file.

Slot CompleteFTP Manager CLI / JSS
Certificate file .cer, .crt, .pem, .pfx, .p12 in the file dialog. .p7b also works but the dialog's filter hides it, so you have to type the file name. Any name; the extension chooses the parser. pfx/p12 → PKCS#12, p7b → PKCS#7, anything else → PEM or DER.
Private key file .pvk or .pem only. Any other extension raises Unknown private key format: <path>. Any name, but the content must be PEM. A PVK file cannot be used on this route.

Inside those containers:

Format Accepted Notes
PKCS#12 / PFX (.pfx, .p12) Yes Certificate and key in one file. The key must be exportable.
PKCS#7 (.p7b) Yes Certificates only, no private key, so you will be prompted for one.
PEM certificate (-----BEGIN CERTIFICATE-----) Yes Multiple certificates in one file are read; but only in CompleteFTP Manager. See "Intermediate and root certificates".
DER / binary certificate (.cer, .crt) Yes Detected by the absence of BEGIN CERTIFICATE in the file.
PEM key, PKCS#1 (-----BEGIN RSA PRIVATE KEY-----) Yes Encrypted (Proc-Type: 4,ENCRYPTED) or plain.
PEM key, PKCS#8 (-----BEGIN PRIVATE KEY-----) Yes Plain.
PEM key, PKCS#8 encrypted (-----BEGIN ENCRYPTED PRIVATE KEY-----) Yes Including PBES2/PBKDF2 with AES-CBC, which is what OpenSSL 3.x produces by default.
PVK (.pvk) Manager only Microsoft's format: RC4-encrypted with an SHA-1-derived key.
OpenSSH key (-----BEGIN OPENSSH PRIVATE KEY-----) No Convert first: ssh-keygen -p -m PEM -f key.
EC / ECDSA key, any container No See "Only RSA keys work" below.
DSA key No Parsed, then rejected because it is not RSA.

DEK algorithms accepted in a traditional encrypted PEM key are AES-128/192/256, DES, DES-EDE, DES-EDE3, Blowfish and RC2, in CBC, CFB, ECB or OFB mode.

Where the certificate lives, and what uses it

  • There is one certificate per site, held in CompleteFTP's own configuration database (config.db), not in the Windows certificate store.
  • FTPS and HTTPS on a site share that one certificate. In CompleteFTP Manager the field appears twice, as Server certificate (also used in HTTPS) under Advanced FTP/FTPS Settings, and as Server certificate under Advanced HTTP/HTTPS Settings, but both edit the same value. Setting it in one place sets it in the other.
  • The Admin site has its own certificate. The admin interface (port 14983 for SFTP, and its own HTTPS port) is a separate site, so a certificate installed on your data site does not apply to it. In Enterprise MFT, turn on Show system users/folders/sites in the Options menu to see the Admin site under Sites. In Standard and Professional, use the Admin panel → Show advanced administrator connection settings.
  • Multiple sites require Enterprise MFT. In the other editions there is one data site and therefore one server certificate for it.
  • The server reloads the certificate automatically when the stored bytes change. A service restart is not required, but existing connections keep using the old one.

The procedure

CompleteFTP Manager

  1. Settings (or Sites in Enterprise MFT) → FTP/FTPSAdvanced FTP/FTPS SettingsSecurity SettingsServer certificate, then the ... button.
  2. Click Import a certificate from a file. Answer Yes to The existing certificate will be overwritten.
  3. Choose the certificate file. If you choose a name whose extension isn't recognised you get Please select a file with one of the following extensions: cer, pem, pfx, p12.
  4. For a PFX or P12 you are asked for the file's password (Please enter the password of the PFX/P12 File). For a PEM file that also contains an encrypted private key you are asked for the key's password instead.
  5. If the certificate file has no private key in it, you are asked to Choose a private key file, .pvk or .pem, and then for its password.
  6. The dialog now shows the certificate's details. Click OK.
  7. Click APPLY CHANGES in the main window. This step is the one most often missed: until you click it the certificate has not reached the server.

Two things to expect while this runs. The file is parsed on the UI thread, so CompleteFTP Manager can show Not Responding for several seconds, that is normal, wait rather than killing it. And the identity fields shown at step 6 are read from whichever certificate the manager picks as the leaf, which is not always the one you expect when the file contains a chain (see below).

CLI (the only interface on Linux)

# what is installed now
completeftp site cert export "Default Site"

# certificate and key in one PFX
completeftp site cert import "Default Site" /etc/ssl/cert.pfx "pfxpassword"

# certificate and key as separate files
completeftp site cert import "Default Site" /etc/ssl/cert.crt "" /etc/ssl/cert.key "keypassword"

# self-signed, for testing only
completeftp site cert generate "Default Site" ftp.example.com "Example Ltd" IT London ENG GB \
     2026-01-01 2029-01-01 2048

site cert import applies the change itself, there is no separate apply step. site list gives you the site names, including the Admin site, which is listed last.

The CLI is enabled out of the box on Linux. Run it as root or as the completeftp account, which are the accounts that can reach the server. On Windows the admin CLI is off by default and has to be enabled with --enable-admin-cli on the service's binary path.

Three differences from the manager worth knowing:

  • The CLI does not care what the private key file is called, as long as its contents are PEM.
  • The CLI cannot read a PVK file at all. Convert it first: openssl rsa -inform pvk -in key.pvk -out key.pem.
  • Pass the certificate and the private key as separate files, or use a PFX. A single PEM file containing both the certificate and the key is not handled on this route: the certificate is read but the key inside it is ignored, and the import fails with

    Certificate file doesn't include private key, so this must be supplied separately

    This is a defect in the CLI/JSS import path, not something you have done wrong.

When it doesn't work

Ordered by how often each comes up in support tickets.

1. The private key is fine. The file extension isn't

In CompleteFTP Manager the private key parser is chosen from the file's extension, not its contents: .pvk is read as a Microsoft PVK blob, .pem as PEM, and anything else is refused outright with

System.IO.IOException: Unknown private key format: C:\certs\wildcard.pfx

The key file dialog offers All Files as well as PVK or PEM Files, which makes it easy to select a .key, .pfx or extensionless file and get that error. Copy the file to a name ending in .pem and try again.

The reverse mistake is worse, because it reports a password problem. A PEM-format key named .pvk is handed to the PVK reader, which fails to recognise the header and throws

System.Security.Cryptography.CryptographicException: Invalid data and/or password

That message is raised both for a wrong password and for a file that is not a PVK at all. If you are certain of the password, suspect the format: a real PVK file begins with the bytes 1E F1 B5 B0, while a PEM file begins with -----BEGIN.

2. The key file contains a certificate as well, with the certificate first

CompleteFTP reads exactly one PEM object from the private key file. If the file starts with a certificate block, which is what openssl pkcs12 -in file.pfx -out all.pem produces, the first object read is the certificate, and the import fails with

Wrong type returned from ReadObject(): Org.BouncyCastle.X509.X509Certificate

(the class name varies between builds). Split the file so that the key file contains only the -----BEGIN ... PRIVATE KEY----- block, or use -nocerts:

openssl pkcs12 -in file.pfx -nocerts -out key.pem

Leading Bag Attributes / subject= / issuer= lines before the BEGIN marker are harmless and do not need to be removed.

3. The password is rejected but OpenSSL says it is correct

Work through these in order.

  • Is the key actually encrypted? If it is not, the password box is decorative: any value, including blank, is accepted. A key generated by CompleteFTP's own CSR wizard is not encrypted on 25.1.0 and later, despite the wizard asking you to set and confirm a password. So "the password I set when I generated the CSR doesn't work" and "a blank password works" are both expected on those releases. On 25.0.6 and earlier the wizard produced an encrypted PVK, so there the password does matter and a rejection means something else, most often the file-extension trap above.
  • Does the key match the certificate? Compare the public keys; identical hashes mean they are a pair.

    openssl x509 -in certificate.crt -pubkey -noout | openssl pkey -pubin -outform DER | openssl dgst -sha256
    openssl pkey -in private.key -pubout -outform DER | openssl dgst -sha256

    If they differ, no password will help, you need the key that was generated with the CSR this certificate was issued against, or a re-key. Older releases said so plainly: Error: The public key of the certificate does not match the value specified.

  • Is it a PKCS#12 password or a private key password? For a .pfx the prompt wants the password on the PKCS#12 file. For a separate key file it wants the password on the key. They are frequently different, and people enter the wrong one.
  • On the CLI, a genuinely wrong key password is reported precisely: Could not decrypt key. Please check the password. If you get the generic manager message instead, the cause is one of the others in this list.

If you no longer have the private key at all, there is nothing to import. A certificate cannot be installed without its key, in CompleteFTP or in any other server. If the CSR was generated by CompleteFTP, the key was written to the file you chose at that time and exists nowhere else. Your only route is to re-key the certificate with the CA.

4. Keyset does not exist and friends. Windows key-store permissions

System.Security.Cryptography.CryptographicException: Keyset does not exist
System.Security.Cryptography.CryptographicException: Access denied
Key not valid for use in specified state

Importing a certificate on Windows makes CompleteFTP Manager write a key container through the Windows crypto API, and the account it needs is the account running CompleteFTP Manager, not the service account. This is why the same file imports on one machine and not another, and why the manager's log shows it touching a path under the interactive user's profile:

C:\Users\<username>\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-...

In order of likelihood:

  • The user running the manager has no write access to %APPDATA%\Microsoft\Crypto\RSA. Run the manager as a user who does, or as Administrator. (Running as Administrator is a diagnostic, not a fix, if it works, fix the permissions.)
  • A stale key container from an earlier import is in the way. PEM key imports all reuse a single fixed container name, so a container left behind by a different user or a failed attempt collides with the new one. Move the contents of %APPDATA%\Microsoft\Crypto\RSA to a backup directory and retry, or retry under a different Windows account. Create a new self-signed certificate has the same weakness, every generation uses one fixed container name, which is why that can fail with Key not valid for use in specified state on a machine where an ordinary import also fails.
  • The private key in the PFX is marked non-exportable. OpenSSL will not warn you about this; Windows will:

    certutil -dump yourfile.pfx

    If the Private Key entry says Not exportable, re-export the PFX with an exportable key, or split it into a separate PEM certificate and PEM key:

    openssl pkcs12 -in file.pfx -clcerts -nokeys -out certificate.pem
    openssl pkcs12 -in file.pfx -nocerts -nodes  -out key.pem

Separately, the service account needs read/write access to C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys, because that is where the server side loads the stored certificate's key. That is the right advice for a server that can't use an already-imported certificate, and the wrong advice for an import that fails in the manager. None of this applies on Linux, where no Windows key store is involved.

5. It imported, but the server can't load it

Look in the server log, not the manager log. The chain of symptoms is:

ERROR SecureConfiguration Failed to load server certificate: Access is denied.
ERROR SecureConfiguration Server certificate does not have a private key!

and then, on an HTTPS or implicit-FTPS port,

ERROR SocketListener OnConnected failed: The certificate cannot be set to a null reference when creating a server socket.

which the browser reports as a connection reset (ERR_CONNECTION_RESET, PR_CONNECT_RESET_ERROR) with plain HTTP still working. On an explicit-FTPS port the same condition gives the client a bare 431 Server error and logs

ERROR AuthCommand User attempted AUTH but no certificate available

On Windows the account running the service needs read/write access to C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys, because that is the machine key store the server loads the certificate's key from. If the log says Failed to load server certificate: Access is denied., see "If you are on an older release" below before changing permissions, that exact message was a regression in one release.

You may also see, at import time, An internal error occurred when the certificate was being saved to the configuration (private key lost). That check runs only on the separate-key-file path and means the key was associated in memory but did not survive being written to the configuration, the same key-store permission problem, caught earlier. Failed to load certificate with private key in the manager log is the earlier stage of the same failure: the key file parsed, but Windows would not attach the resulting key to the certificate.

A related pair comes from the socket layer rather than the configuration layer. Alongside The certificate cannot be set to a null reference when creating a server socket. you may see If a certificate is specified, it must have a private key., that one means the certificate loaded but its key did not, which almost always means the key is not RSA (section 6).

6. Only RSA keys work

A certificate whose key is EC/ECDSA cannot be used as a CompleteFTP server certificate in any current release. In CompleteFTP Manager the import fails after the password prompt with

The certificate key algorithm is not supported.

(that text comes from .NET, when the manager reads the key size for display). On the CLI and JSS route the message is CompleteFTP's own:

Only certificates with RSA keys are currently supported.

The server side agrees: the TLS layer refuses ECDSA credentials and logs ECDHE_ECDSA certificates not supported. Those suites are not in the server's offered list, so a client that supports only ECDSA fails to negotiate cleanly rather than breaking mid-handshake. Use an RSA certificate. DSA and Ed25519 keys are likewise not usable here. Ed25519 is supported for SSH host keys, which is a different setting.

7. After OK the dialog shows the CA's details instead of yours

When the file contains more than one certificate, the manager picks the "leaf" heuristically: the one that has a private key, failing that the one whose Basic Constraints say it is not a CA, and failing that simply the first certificate in the file. With some chains that lands on the intermediate or root, so the Server name/address and Organization fields change to the CA's after you click OK.

This is a display problem, not a failed import. Don't judge the result from the dialog, check what the server actually presents:

openssl s_client -connect ftp.example.com:990 -showcerts
openssl s_client -connect ftp.example.com:443 -showcerts

The same dialog shows (Error) in red, or [Not set], when the stored certificate cannot be read at all.

8. The manager can't be used at all

On Linux there is no manager, so if you are looking for the import dialog on a Linux installation, it does not exist. Use completeftp site cert import. The Linux code path is also the simpler one, no Windows key store, so sections 4 and 5 do not apply.

Intermediate and root certificates

CompleteFTP will read a certificate file containing your certificate plus the CA's intermediates, concatenate them, yours first, and it will store them. But the chain CompleteFTP presents to clients at handshake time is rebuilt on the server machine from the leaf certificate, using the operating system's certificate stores. It is not taken from the file you imported.

The practical consequence: if clients report an incomplete or untrusted chain, install the CA's intermediate certificate into the server machine's Intermediate Certification Authorities (Local Computer) store. With a public CA this usually happens by itself, because Windows fetches and caches intermediates. With an internal PKI it will not. The chain build also performs an online revocation check, so a server with no outbound access to the CA's CRL/OCSP endpoints may produce a partial chain.

Do not put a root or intermediate certificate in the certificate slot on its own. It will import, because CompleteFTP does not validate imported certificates, and the site will then present the wrong certificate.

For client certificate verification (Clients must supply certificatesRequire valid certificate, not available in the Standard Edition), CompleteFTP has no trust store of its own: the client's issuer must be in the Windows Trusted Root Certification Authorities store. That is what this message means:

The certificate could not be verified: UntrustedRoot - A certification chain processed correctly but terminated in a root certificate not trusted by the trust provider.

Two current defects worth knowing about

  • The CSR wizard's private key password is collected and discarded on 25.1.0 and later. The key file written alongside the CSR is an unencrypted PEM key. Treat that file as a secret in its own right, and expect a blank password to be accepted when you import. 26.1.0 added a confirmation field to that prompt, which makes the wizard look more careful about a password it still throws away.
  • .pvk-named PEM keys left over from an older install are the single most common cause of "the password is definitely correct" reports. Renaming to .pem fixes them; the CSR wizard stopped producing PVK at 25.1.0.

If you are on an older release

All of these are fixed. If you are on an affected release, upgrading is the fix, there is no configuration workaround for any of them.

Symptom Affected Fixed in
Index was out of range. Must be non-negative and less than the size of the collection. importing most PFX files 24.1.0 25.0.0
Failed to load server certificate: Access is denied. when the service runs as anything other than SYSTEM 26.0.0 26.0.1
Unable to cast object of type 'AsymmetricCipherKeyPair' to type 'RsaPrivateCrtKeyParameters' on some PEM keys before 13.1.0 13.1.0
Failed to find certificate's private key. Error: -2146885621, a bare Windows error number instead of a reason; it meant a key-store permission problem 25.0.x and earlier 25.1.0

After the import succeeds

  • Click APPLY CHANGES.
  • Reconnect a client. Existing sessions keep the old certificate; there is no need to restart the service, but there is a need to make a new connection.
  • Verify what is being served, per port, with openssl s_client -connect <host>:<port> -showcerts. Run it against every HTTPS and FTPS port you have, including the Admin site's, a certificate installed on one site does not appear on another.
  • If clients now report untrusted or unknown certificate rather than a failed import, the certificate is installed and the remaining problem is trust: a self-signed certificate (the default, CN localhost) is in no client's trust store, and a CA-issued certificate whose CN/SAN does not match the hostname the client dialled will be rejected too. NET::ERR_CERT_COMMON_NAME_INVALID when browsing https://localhost is this, not an import failure.
  • Export includes the private key only for .pfx and .p12. Export the current certificate to a file writes the key alongside the certificate when the filename ends in .pfx or .p12, and never when it ends in .cer or .pem. If you are copying a certificate to a second server, a cluster node, or a rebuilt machine, export to .pfx. Some older support advice says a self-signed certificate generated inside CompleteFTP can never be exported with its key; that is no longer the case on current releases. (completeftp site cert export <site> --exportPrivateKey true does the same from the CLI, emitting PEM.)

What to send support

If none of the above resolves it, the useful artefacts are the manager log and the server log, both at debug level, covering the failed import.

  • Manager: in the connect dialog choose Other settings..., set the manager logging level to Full diagnostic (slow), connect, retry the import, then collect C:\Users\<username>\AppData\Local\EnterpriseDT\CompleteFTP\Logs\Diagnostics.log.
  • Server: MonitoringLog FilesServer logging level = DebugAPPLY CHANGES, then collect C:\ProgramData\Enterprise Distributed Technologies\Complete FTP\Logs\Diagnostics.log (/var/log/completeftp/Diagnostics.log on Linux).

The manager log line you are looking for names the file and the underlying exception:

2026-07-30 09:44:21,636 ERROR CertForm [] Failed to load server certificate from C:\certs\wildcard.crt
System.IO.IOException: Unknown private key format: C:\certs\wildcard.pfx

Also useful: the first and last lines of your private key file (they identify the format without disclosing the key), and openssl pkcs12 -info -in <file> output for a PFX. Note that the Save diagnostics zip deliberately strips SSL certificates from its copy of the configuration, so it will not tell anyone what you imported.

If you send certificate and key files, zip them with a password. A production private key should not be sent at all, re-key instead.

Related