nikivdev/code · error

invalid base58 sealer secret: {e}

Error message

invalid base58 sealer secret: {e}

What it means

After stripping the "sealerSecret_z" prefix, get_sealer_id base58-decodes the remainder. If bs58::decode fails (characters outside the base58 alphabet, whitespace, or mixed-alphabet input) this error wraps the decoder's message. The prefix was right but the encoded key material is corrupt.

Source

Thrown at src/sealer_crypto.rs:27

const SECRET_PREFIX: &str = "sealerSecret_z";
const ID_PREFIX: &str = "sealer_z";

pub fn new_x25519_private_key() -> Vec<u8> {
    let mut bytes = [0u8; 32];
    SysRng
        .try_fill_bytes(&mut bytes)
        .expect("system RNG should provide x25519 key material");
    bytes.to_vec()
}

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

    let public = PublicKey::from(&StaticSecret::from(bytes)).to_bytes();
    Ok(format!(
        "{}{}",
        ID_PREFIX,
        bs58::encode(public).into_string()
    ))
}

pub fn seal(
    message: &[u8],
    sender_secret: &str,
    recipient_id: &str,
    nonce_material: &[u8],

View on GitHub (pinned to a747e741ae)

Solutions

  1. Re-copy the secret carefully ensuring only base58 characters (no 0/O/I/l) follow the prefix.
  2. Trim whitespace/newlines from the value before passing it in.
  3. Regenerate the sealer identity if the original secret cannot be recovered.
  4. Validate the secret format with a pre-check: starts with "sealerSecret_z" and the rest is valid base58.

Example fix

// before
let s = "sealerSecret_z5Kd3NB0Ad2..."; // contains '0' (invalid in base58)
// after
let s = "sealerSecret_z5Kd3NBOAd2..."; // corrected character, or re-copy from source
Defensive patterns

Strategy: validation

Validate before calling

fn secret_body_is_base58(s: &str) -> bool {
    match s.strip_prefix("sealerSecret_z") {
        Some(body) => !body.is_empty()
            && body.bytes().all(|b| bs58_alphabet_contains(b)),
        None => false,
    }
}
// simpler pre-check: no 0, O, I, l, whitespace, or punctuation in the body

Try / catch

match get_sealer_id(secret) {
    Err(e) if e.to_string().starts_with("invalid base58 sealer secret") => {
        eprintln!("secret body is not valid base58; re-copy the value without modifications");
        // surface e for the exact decode failure
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling get_sealer_id with a secret whose base58 body contains invalid characters (0, O, I, l, spaces, newlines, quotes) or was truncated/modified after the prefix.

Common situations: Copy-paste mangling (line breaks inserted, lookalike characters typed), storing the secret through a system that uppercased it, or manual transcription of the key.

Related errors


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