/api/system/load-password

POST

Load the file-decryption password into RAM. While the password is loaded, encrypted (Type 10) coin files can be decrypted in memory as needed, and coin encryption operations become possible.

POST http://localhost:8080/api/system/load-password
⚠️ Renamed endpoint

This endpoint replaces /api/system/login. The old URL is no longer registered. Its counterpart, /api/system/logout, is replaced by /api/system/shutdown, which deletes the password from RAM and shuts the core down.

Description

/api/system/load-password accepts a password in a form-encoded POST body and holds the derived key in RAM. It is deliberately not called "login": no account exists, and nothing is stored on disk. The password is the only thing standing between the encrypted coin files and their authenticity numbers — the server keeps it (as a derived key) in memory until /api/system/shutdown is called or the process exits.

How the password is verified: encrypted Type 10 coin files intentionally contain no password check of any kind — nothing on disk can prove a password right or wrong. The core verifies a candidate password by decrypting one coin and asking the RAIDA (detect). If the RAIDA rejects the result, the response is bad password. This requires network access.

Current build status

The Type 10 encrypted file format is being implemented. In the current build this endpoint stores the password and returns success without RAIDA verification (there are no Type 10 files yet to verify against). The bad password response described here activates together with Type 10 support. Track the plan in core/docs/file-encryption/.

⚠️ Security Notes
  • POST only. GET requests are rejected with 405 — a password in a URL would be written to Client_Data/main.log and to any proxy or browser history logs.
  • Lost password = lost coins. Once files are encrypted, there is no recovery if the password is forgotten. The GUI must warn the user and require the password to be typed twice when encrypting for the first time.
  • UTF-8 byte exactness. The key is derived from the raw bytes the client sends. Encode non-ASCII characters as UTF-8 (form-encode with --data-urlencode / FormData) so every client derives the same key.
  • Use HTTPS in any deployment that is not loopback-only.

Client Flow — what to call, in what order

  1. Call GET /api/system/encryption-status at startup, before showing the dashboard.
    • If encrypted files exist and no key is loaded, prompt for the password before the dashboard appears.
    • If no encrypted files exist, no prompt is needed. The wallet is decrypted.
  2. Send the password with POST /api/system/load-password.
  3. On bad password (once Type 10 verification is live), let the user retry. On success, show the dashboard.
  4. To encrypt a decrypted wallet, call /api/system/encrypt_existing_files. To decrypt, call /api/system/decrypt_existing_files.
  5. When the user logs out, call POST /api/system/shutdown — it deletes the password from RAM and shuts the core down; the GUI should then exit too.

Parameters

Parameter Location Type Required Description
password POST body (form-encoded) string Required The user's password as raw UTF-8 bytes. Any characters are accepted. Minimum 1 byte; maximum 4096 bytes (HTTP layer ceiling).

Response

Success — 200 OK

{
  "command": "load-password",
  "success": true,
  "message": "Password loaded into RAM. Verification is deferred until Type 10 encrypted files exist (RAIDA confirmation).",
  "key_set": true
}

Response Fields

FieldTypeDescription
key_setboolAlways true on a 200 response. The derived key is now in RAM.

Error Responses

400 — Password missing

{
  "error": true,
  "message": "Missing required parameter: password",
  "code": 400
}

405 — GET not allowed

{
  "error": true,
  "message": "Use POST: a password in a GET URL would be written to server and proxy logs",
  "code": 405
}

Bad password (activates with Type 10 support)

When encrypted Type 10 files exist, the core verifies the candidate password by decrypting one coin and running RAIDA detect. If the RAIDA rejects it, the response reports bad password and the key is cleared so the user can retry. If the RAIDA is unreachable, the result is inconclusive: the wallet opens locked/read-only until verification succeeds.

500 — Internal failure

Returned when the key could not be derived or installed. Should not happen in normal operation.

Example Usage

curl -X POST \
  -H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" \
  --data-urlencode "password=¥CheeseCake£" \
  "http://localhost:8080/api/system/load-password"
const body = new URLSearchParams();
body.set('password', '¥CheeseCake£');

const res = await fetch('http://localhost:8080/api/system/load-password', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' },
  body: body
});
const data = await res.json();
// data.key_set === true → password is in RAM; show the dashboard.
import requests

url = 'http://localhost:8080/api/system/load-password'
resp = requests.post(url, data={'password': '¥CheeseCake£'})
print(resp.json())
# {'command': 'load-password', 'success': True, 'key_set': True, ...}

Related Endpoints