The SFTP server accepts a public key in place of a password. The partner proves they hold the matching private key, and no password is sent, stored in a script, or typed.
Most users do not need this. Entering a password works, and it is the right choice for a person who logs in by hand. Public keys exist for the unattended case: a nightly job that must run with nobody at the keyboard and no password written into a batch file.
Both sides have work to do, and they happen in a fixed order. The partner generates the key and sends the sysop half of it; the sysop installs that half against the user record. Nothing works until both halves are done, which is the usual reason a first attempt falls back to a password prompt.
The system password must be stamped. Public key authentication is served by wcServer on behalf of the module, and wcServer refuses the request outright when no system password is set. The server log says so plainly:
LoginUserPublicKey: REFUSED -- no System Password is set
Setting the password in wcConfig is not sufficient by itself -- it must be stamped with wcsyspw. This catches sites whose configuration looks correct and whose key logins fail anyway.
Enable the feature. Run wcConfig | SFTP Server | General and tick:
[X] Allow publickey authentication
Restart wcOnline. The startup line in the module log reports the result, and is the quickest way to confirm the server is listening for keys at all:
config: publickey=on authkeydir=(user record only)
This is per computer. A multi-machine site enables it on each server that should accept keys; a key installed for a user is in the user database and is therefore common to all of them, but a server with the option off will still ask that user for a password.
A key pair is two files. The one WITHOUT an extension is the private key and never leaves the partner's machine. The one ending .pub is the public key and is what the sysop needs.
Windows 10, Windows 11 and Windows Server -- OpenSSH is included, so this runs in a plain Command Prompt or PowerShell:
ssh-keygen -t ed25519 -C "acme-nightly" -f %userprofile%\.ssh\wildcat
macOS and Linux:
ssh-keygen -t ed25519 -C "acme-nightly" -f ~/.ssh/wildcat
Either produces two files:
wildcat -- the private key. Keep it. Do not send it to anyone, including the sysop.
wildcat.pub -- the public key. This is the one to send.
ED25519 is recommended. ssh-rsa is also accepted for a client that cannot do ED25519; use -t rsa -b 4096 instead.
The passphrase question. ssh-keygen offers to protect the private key with a passphrase. The honest trade-off:
For an unattended job, press Enter twice and use no passphrase. A passphrase must be typed on every use, which is precisely what an unattended job cannot do. The private key file then becomes the secret, and is protected by the file permissions of the machine holding it.
For a person logging in by hand, set a passphrase. It costs one prompt and means a stolen key file is not by itself a working login.
PuTTY and WinSCP users generate with PuTTYgen instead. Choose EdDSA (or RSA), press Generate, then copy the box labelled Public key for pasting into OpenSSH authorized_keys file. That box is what the sysop needs -- not the file saved by the "Save public key" button, which is in PuTTY's own format and the server will not accept it.
Send the contents of the .pub file, as text. It is a single long line:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK8s4... acme-nightly
It must stay on one line. Mail clients and chat windows wrap long lines, and a wrapped key will not install. Sending it as an attachment avoids the problem.
A public key is not a secret. It is safe to send by ordinary mail. If the partner sends something beginning -----BEGIN OPENSSH PRIVATE KEY-----, they have sent the wrong file: tell them to discard that key pair, generate a new one, and send the .pub. A private key that has travelled by mail should never be used.
Two ways in, both reaching the same place.
From the Sysop User Editor: open the user, go to the Security page and choose:
[ K] SSH Public Keys
Or run the utility directly:
wcrun wcsFtpPubkey
It lists, adds, deletes and tests keys for a user. Paste the whole line when it asks for the key. The utility refuses a private key, refuses anything that does not start with a recognised type such as ssh-ed25519 or ssh-rsa, and renumbers the remaining keys after a delete.
A user name containing spaces may be entered with dots -- winserver.support for winserver support -- the same convenience the SFTP login itself accepts.
-i takes the PRIVATE key, not the .pub file. This is the single most common mistake and it does not announce itself: pointing -i at the .pub makes the client unable to sign, so it silently falls back to asking for a password.
sftp -i %userprofile%\.ssh\wildcat claude@sftp.example.com
A login name containing spaces is given with dots:
sftp -i %userprofile%\.ssh\wildcat winserver.support@sftp.example.com
A successful key login reaches the prompt with no password asked. The module log records which method was used:
node 4 cid 143 auth OK [claude] id=5 via PUBLICKEY (ssh-ed25519)
It asks for a password anyway. Nearly always -i pointing at the .pub file. Point it at the private key -- the file with no extension.
The log says "publickey matched" and it still asks for a password. Those are two different steps. Matched means the server recognised the key as belonging to that user; the client must then prove it holds the private half, and that is what failed. Same cause as above: the client had no private key to sign with.
Nothing at all in the log about publickey. The option is off on this computer, or wcOnline was not restarted after it was ticked. Check the startup line from section 1.
"REFUSED -- no System Password is set". Run wcsyspw. Setting the password in wcConfig alone does not stamp it.
It works from one machine and not another. The private key lives on the machine that connects. A key generated on a workstation is not present on the server running the nightly job.
It works for one server and not another. Section 1 is per computer. The key is in the user database and is shared; the option is not.
Permissions. OpenSSH refuses to use a private key that other accounts can read, and says so. On Windows the file must be owned by the account using it with inherited permissions removed; on macOS and Linux use chmod 600.
Turn on [X] Verbose session trace on the Key/Auth/Ident page to see each authentication step in the trace log. On the client side, sftp -v shows which key it offered and what the server answered, and is usually faster at finding the answer than the server log.
Keys are stored in the user record, in the [SFTP] section, one per numbered variable:
[SFTP]
AuthorizedKey1=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... partner@acme
AuthorizedKey2=ssh-rsa AAAAB3NzaC1yc2EAAAA...
A user may hold up to 16 keys. That is deliberate: a partner running jobs from several machines gives each machine its own key, so one machine can be revoked without disturbing the others. Revoking is deleting that key from the user record; nothing else changes and no other machine notices.
Because the keys are part of the user record they travel with the user database, are included in its backup, and are visible to every computer in the installation.
A key identifies a user, not a person. Anyone holding the private key file is that user. Treat the file as you would the password it replaces.
Access profiles still apply. A key login is subject to the same SFTP access, file area rights and time limits as a password login. It changes how the user proves who they are and nothing else.
The logon hook still runs. sftplogon (or ftplogon) runs after a key login exactly as after a password login, so a hook that sets the starting file group and area behaves identically.
Login attempt limits still apply. A failed key attempt is counted by IP tracking the same way a failed password is.
See Wildcat! SFTP Server Setup and Configuration for the server itself, and FTPLOGON Hook Example for the hook mechanism.