nikivdev/code · error

invalid base58 secret: {e}

Error message

invalid base58 secret: {e}

What it means

decode_secret base58-decodes the body of a "sealerSecret_z"-prefixed secret. This error wraps bs58::decode failures: the body contains characters outside the base58 alphabet or other malformed encoding. Prefix was correct; the key material is not valid base58.

Source

Thrown at src/sealer_crypto.rs:85

    let sender_public = decode_id(sender_id)?;
    let recipient_key = StaticSecret::from(recipient_secret);
    let sender_key = PublicKey::from(sender_public);
    let shared_secret = recipient_key.diffie_hellman(&sender_key).to_bytes();
    let nonce = derive_nonce(nonce_material);
    let cipher = XSalsa20Poly1305::new(&shared_secret.into());
    let plaintext = cipher
        .decrypt(&nonce.into(), sealed_message)
        .map_err(|_| anyhow::anyhow!("failed to unseal message"))?;
    Ok(plaintext)
}

fn decode_secret(value: &str) -> Result<[u8; 32]> {
    let encoded = value
        .strip_prefix(SECRET_PREFIX)
        .ok_or_else(|| anyhow::anyhow!("invalid sealer secret prefix"))?;
    let bytes = bs58::decode(encoded)
        .into_vec()
        .map_err(|e| anyhow::anyhow!("invalid base58 secret: {e}"))?;
    bytes
        .as_slice()
        .try_into()
        .map_err(|_| anyhow::anyhow!("invalid secret key length"))
}

fn decode_id(value: &str) -> Result<[u8; 32]> {
    let encoded = value
        .strip_prefix(ID_PREFIX)
        .ok_or_else(|| anyhow::anyhow!("invalid sealer id prefix"))?;
    let bytes = bs58::decode(encoded)
        .into_vec()
        .map_err(|e| anyhow::anyhow!("invalid base58 id: {e}"))?;
    bytes
        .as_slice()
        .try_into()
        .map_err(|_| anyhow::anyhow!("invalid public key length"))
}

View on GitHub (pinned to a747e741ae)

Solutions

  1. Re-copy the secret from its authoritative source, preserving exact characters.
  2. Strip surrounding whitespace and remove line breaks before use.
  3. Validate the body is base58 before calling (regex + decode check).
  4. Regenerate the sealer identity if the value cannot be restored.

Example fix

// before
let s = "sealerSecret_z l0ng-key"; // space + '0' invalid
// after
let s = "sealerSecret_zIl0ngKeyCorrected"; // clean base58 body re-copied
Defensive patterns

Strategy: validation

Validate before calling

fn secret_body_is_base58(s: &str) -> bool {
    s.strip_prefix("sealerSecret_z")
        .map(|body| !body.is_empty() && body.chars().all(|c| {
            !"0OIl \t\n\r".contains(c)
        }))
        .unwrap_or(false)
}

Try / catch

match seal(sender_secret, recipient_id, nonce, msg) {
    Err(e) if e.to_string().starts_with("invalid base58 secret") => {
        eprintln!("secret body contains invalid base58 characters; re-copy the value");
        return Err(e);
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling seal or unseal with a secret whose body (after the prefix) contains invalid characters such as 0, O, I, l, whitespace, or punctuation.

Common situations: Copy-paste corruption, uppercase transformation by a shell/tool, line-wrapping in config files, or hand-typed secrets.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/5aca81954b01c506. Report an issue: GitHub.