Developer platform · 2 / 9

Set up the signing tool and publisher key

cdnca-plugin is one offline executable that only touches local files: it does not sign in, upload or review. One publisher key is used for the long term; do not create a new one per version.

← All tutorials

Download and verify

Pick the file for your system and download SHA256SUMS too; select only the target file’s line, then verify. Stop and do not run it if the hash differs.

CDNCA_DOWNLOADS='https://developer.cdnca.com/downloads/cdnca-plugin'
CDNCA_CLI_FILE='cdnca-plugin-linux-amd64'   # ARM64: cdnca-plugin-linux-arm64
curl --fail --location --show-error --output "$CDNCA_CLI_FILE" "$CDNCA_DOWNLOADS/$CDNCA_CLI_FILE" &&
curl --fail --location --show-error --output SHA256SUMS "$CDNCA_DOWNLOADS/SHA256SUMS" &&
awk -v name="$CDNCA_CLI_FILE" '$2 == name { print; found=1 } END { if (!found) exit 1 }' SHA256SUMS > SHA256SUMS.selected &&
sha256sum -c SHA256SUMS.selected &&
chmod +x "$CDNCA_CLI_FILE" &&
CDNCA_PLUGIN_CLI="$(pwd -P)/$CDNCA_CLI_FILE"
CDNCA_DOWNLOADS='https://developer.cdnca.com/downloads/cdnca-plugin'
CDNCA_CLI_FILE='cdnca-plugin-darwin-arm64'
curl --fail --location --show-error --output "$CDNCA_CLI_FILE" "$CDNCA_DOWNLOADS/$CDNCA_CLI_FILE" &&
curl --fail --location --show-error --output SHA256SUMS "$CDNCA_DOWNLOADS/SHA256SUMS" &&
awk -v name="$CDNCA_CLI_FILE" '$2 == name { print; found=1 } END { if (!found) exit 1 }' SHA256SUMS > SHA256SUMS.selected &&
shasum -a 256 -c SHA256SUMS.selected &&
chmod +x "$CDNCA_CLI_FILE" &&
CDNCA_PLUGIN_CLI="$(pwd -P)/$CDNCA_CLI_FILE"
$CdncaDownloads = 'https://developer.cdnca.com/downloads/cdnca-plugin'
$CdncaFile = 'cdnca-plugin-windows-amd64.exe'
Invoke-WebRequest "$CdncaDownloads/$CdncaFile" -OutFile $CdncaFile -ErrorAction Stop
Invoke-WebRequest "$CdncaDownloads/SHA256SUMS" -OutFile SHA256SUMS -ErrorAction Stop
$CdncaSumLines = @(Select-String -Path SHA256SUMS -Pattern '^[a-f0-9]{64}\s+\*?cdnca-plugin-windows-amd64\.exe#x27;)
if ($CdncaSumLines.Count -ne 1) { throw 'SHA256SUMS has no unique line for this file' }
$CdncaExpected = ($CdncaSumLines[0].Line -split '\s+')[0]
if ((Get-FileHash $CdncaFile -Algorithm SHA256).Hash.ToLower() -ne $CdncaExpected) { throw 'hash mismatch' }
$CdncaPluginCli = (Resolve-Path $CdncaFile).Path

The commands below use Linux/macOS. On Windows use the same subcommands and flags as & $CdncaPluginCli <subcommand> … in PowerShell. The tool has exactly four subcommands: keygen, pubkey, sign-challenge, sign-manifest; it exits 1 on failure and 2 on a usage error.

Create the publisher key once

Keep the private key outside your project; never commit, upload or send it.

CDNCA_KEY_DIR="$HOME/.config/cdnca-publisher"
mkdir -m 700 -p "$CDNCA_KEY_DIR"
CDNCA_PUBLISHER_KEY="$CDNCA_KEY_DIR/publisher.key"

"$CDNCA_PLUGIN_CLI" keygen -out "$CDNCA_PUBLISHER_KEY"
"$CDNCA_PLUGIN_CLI" pubkey -key "$CDNCA_PUBLISHER_KEY"

keygen never overwrites an existing file, writes the key with mode 0600 and prints the public key; pubkey prints it again any time. A lost key cannot be recovered, only replaced by a new registration, so back it up somewhere controlled.

Register the key and claim a namespace

  1. Seller site “Publisher keys” → “Register key”: enter the namespace and the public key, click “Get the message to sign”.
  2. Copy the whole “Message (base64url)” into the command below as is; do not decode or rebuild it.
  3. Paste the output into “Signature (base64url)” and click “Register”.
"$CDNCA_PLUGIN_CLI" sign-challenge \
  -key "$CDNCA_PUBLISHER_KEY" \
  -message '<message-from-the-page>'
RuleValue
Namespace3–96 characters of lower-case letters and digits, segmented by dots or hyphens, e.g. com.example
Reservedio.cdnca is for the platform only
Challenge lifetime15 minutes, single use; fetch a new one when it expires
Who can registerThe owner only

The tool first checks the message really is the platform’s challenge for this key and refuses otherwise, so the key cannot be tricked into signing anything else. The first successful registration claims the namespace. How to confirm: the namespace and an active key appear in the list.

Sign a manifest

"$CDNCA_PLUGIN_CLI" sign-manifest \
  -key "$CDNCA_PUBLISHER_KEY" \
  -in manifest.json \
  -out manifest.signed.json
  • The tool canonicalises the manifest, computes the digest and writes integrity (Ed25519, key_id, payload_sha256, signature), replacing any existing one.
  • metadata.publisher.id must be your claimed namespace and key_id an active key of it.
  • A manifest may only contain objects, arrays and strings; numbers, booleans or null are rejected. This applies to the manifest only, not to numbers and booleans the theme, rule or configuration models allow.
  • Any change after signing needs a new signature. A signature proves publisher and byte integrity only; it does not replace scanning or testing.