Skip to content

Conversation

@coodos
Copy link
Contributor

@coodos coodos commented Dec 15, 2025

Description of change

Issue Number

Type of change

  • Breaking (any change that would cause existing functionality to not work as expected)
  • New (a change which implements a new feature)
  • Update (a change which updates existing functionality)
  • Fix (a change which fixes an issue)
  • Docs (changes to the documentation)
  • Chore (refactoring, build scripts or anything else that isn't user-facing)

How the change has been tested

Change checklist

  • I have ensured that the CI Checks pass locally
  • I have removed any unnecessary logic
  • My code is well documented
  • I have signed my commits
  • My code follows the pattern of the application
  • I have self reviewed my code

Summary by CodeRabbit

  • New Features

    • Added broader signature and public-key format support (0x‑hex, multibase/base58, base64/base64url), automatic DER↔raw signature normalization, and improved environment compatibility for base58 handling.
  • Bug Fixes

    • More resilient verification flow with early input validation, clearer aggregated error messages, fallback decoding strategies for non-standard encodings, and reliable certificate/JWKS iteration when verifying signatures.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 15, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Reworks signature-validator: adds decoding/parsing helpers, broadens public-key and signature decoding (0x-hex, 'z'+hex, base58btc, base64/url, DER/SPKI/raw), makes base58btc dynamic import resilient, and refactors certificate resolution and verifySignature with aggregated error handling.

Changes

Cohort / File(s) Summary
Core module & control flow
infrastructure/signature-validator/src/index.ts
Large refactor of verifySignature: early input validation, iterative certificate-based verification, normalized signature handling (DER→raw), expanded try/catch and aggregated failure reporting.
Decoding & parsing helpers
infrastructure/signature-validator/src/index.ts
Adds decodeHexString, looksLikeRawUncompressedEcKey, looksLikeDerSpki, looksLikeDerEcdsaSignature, derToRawEcdsa, tryDecodeBase64Like; extends decodeMultibasePublicKey and decodeSignature to handle 0x-hex, z+hex, base58btc, base64/base64url, and DER detection/normalization.
Dependency loading
infrastructure/signature-validator/src/index.ts
Replaces prior Function-based dynamic import path for base58btc with a try/catch: attempt normal dynamic import() then fall back to Function-based dynamic import while preserving runtime error details.
Certificate & registry handling
infrastructure/signature-validator/src/index.ts
getKeyBindingCertificates tightened: resolves eVault URL, fetches /whois, validates and consistently returns keyBindingCertificates or an empty array.
Formatting / types
infrastructure/signature-validator/src/index.ts
Indentation/formatting changes; VerifySignatureOptions / VerifySignatureResult declarations unchanged semantically.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant Validator as SignatureValidator
  participant Whois as eVault/Whois
  participant Registry as Registry(JWKS)
  participant Base58 as base58btc (dynamic)

  Client->>Validator: verifySignature(options, signature, payload)
  Validator->>Validator: validate inputs, normalize signature (try DER→raw)
  Validator->>Whois: GET /whois (resolve eVault URL)
  Whois-->>Validator: keyBindingCertificates (array)
  Validator->>Registry: fetch JWKS for each certificate issuer / registry
  Registry-->>Validator: JWKS (keys)
  Validator->>Base58: dynamic import attempt (import() -> fallback)
  Base58-->>Validator: base58 decode function
  Validator->>Validator: attempt JWT verification / import public key per certificate
  alt verification success
    Validator-->>Client: verification result (success)
  else all failed
    Validator-->>Client: aggregated error (all attempts failed)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus areas:
    • base58btc dynamic-import fallback and error propagation
    • decodeSignature / decodeMultibasePublicKey edge cases (0x-hex, 'z'+hex, base64 variants)
    • DER ↔ raw ECDSA conversion correctness and boundary checks
    • Certificate iteration and aggregated error composition
    • getKeyBindingCertificates response validation

Possibly related PRs

Poem

🐰 I nibble bytes beneath the moon,
I hop through hex and base58 tune.
DER to raw, a careful bite,
certificates passed in moonlight.
Hooray — the validators hum bright! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description contains only the template structure with no actual content filled in; all sections remain empty with unchecked checkboxes. Complete all required sections: provide an Issue Number, specify the Type of change, explain how changes were tested, and describe the actual modifications made to the signature validator.
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'chore: fix btc-base-58 slice' is vague and does not clearly convey the substantial changes made to the signature validator module. Provide a more specific title that reflects the main scope of changes, such as 'refactor: improve signature and key decoding with multi-format support' or 'chore: enhance btc-base58 imports and signature verification logic'.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b030d7c and ee3bdf0.

📒 Files selected for processing (1)
  • infrastructure/signature-validator/src/index.ts (5 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
infrastructure/signature-validator/src/index.ts (2)

80-83: DER length field check may be overly simplistic.

The check bytes[1] >= 0x20 && bytes[1] <= 0x82 conflates direct length values with the long-form length indicator. When bytes[1] is 0x81 or 0x82, it signals that the actual length is in the following 1 or 2 bytes respectively, not a direct length value. This heuristic may still work for typical SPKI keys but could produce false positives/negatives for edge cases.


194-199: Consider adding a comment for the silent catch.

The empty catch block silently swallows base58 decode failures as part of the fallback logic. While intentional, a brief comment would clarify this is expected behavior.

   if (signature.startsWith("z") && base58Alphabet.test(signature.slice(1))) {
     try {
       const base58btc = await getBase58btc();
       base58Bytes = base58btc.decode(signature);
-    } catch (error) {
+    } catch {
+      // Silently ignore - will try other decodings
     }
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c752ab1 and f795e6f.

📒 Files selected for processing (1)
  • infrastructure/signature-validator/src/index.ts (7 hunks)
🧰 Additional context used
🪛 GitHub Actions: Build All Packages
infrastructure/signature-validator/src/index.ts

[error] 240-240: TS2304: Cannot find name 'debugLog'.

🪛 GitHub Actions: Check Code
infrastructure/signature-validator/src/index.ts

[error] 240-240: Cannot find name 'debugLog'. (TS2304) in infrastructure/signature-validator postinstall during npm run build.

🪛 GitHub Actions: Check Format
infrastructure/signature-validator/src/index.ts

[error] 240-240: infrastructure/signature-validator postinstall: npm run build. TS2304: Cannot find name 'debugLog' (src/index.ts:240,5).

🔇 Additional comments (5)
infrastructure/signature-validator/src/index.ts (5)

8-36: LGTM!

The dual-path dynamic import approach with caching is a sensible pattern for handling ESM/CJS module compatibility. The error propagation properly includes context from the original failure.


135-171: LGTM!

The multi-format public key decoding logic correctly handles the various encoding formats with appropriate validation and fallback behavior.


254-282: LGTM!

The certificate retrieval logic correctly handles the two-step resolution process with appropriate timeout configuration and graceful handling when no certificates exist.


357-364: LGTM with note on curve assumption.

The signature normalization and buffer preparation are correct. The hardcoded size: 32 in derToRawEcdsa is appropriate for P-256 (which uses 32-byte integers), matching the namedCurve: "P-256" used throughout the verification logic.


391-443: LGTM!

The adaptive key import logic correctly distinguishes between raw uncompressed EC points and DER SPKI formats. The verification loop appropriately continues on failures and returns immediately on success.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
infrastructure/signature-validator/src/index.ts (2)

177-241: Clean up empty conditional and clarify base58 vs base64 precedence

  1. The if (base64Bytes) { } block at Lines 185‑186 is a no‑op and can be safely removed.
-    if (base64urlPattern.test(signature)) {
-        base64Bytes = tryDecodeBase64Like(signature);
-        if (base64Bytes) {
-        }
-    }
+    if (base64urlPattern.test(signature)) {
+        base64Bytes = tryDecodeBase64Like(signature);
+    }
  1. For signatures that:
    • start with 'z' and
    • are valid base58 characters (base58Alphabet),
      you decode them both as base64 and as base58. If the decoded bytes are not DER‑shaped, the fallback if (base64Bytes) return base64Bytes; if (base58Bytes) return base58Bytes; means you’ll always prefer the base64 interpretation, even though a leading 'z' strongly suggests multibase base58btc.

If you ever expect non‑DER, raw ECDSA signatures encoded as z‑prefixed base58btc, they’d be misinterpreted as base64 by this logic. You might want to:

  • prefer base58Bytes when signature.startsWith("z") && base58Bytes in the non‑DER fallback, or
  • gate the base64 path more strictly for z‑prefixed inputs.

Example adjustment:

-    // Otherwise return the first successful decode
-    if (base64Bytes) return base64Bytes;
-    if (base58Bytes) return base58Bytes;
+    // Otherwise return the most plausible decode
+    if (signature.startsWith("z") && base58Bytes) return base58Bytes;
+    if (base64Bytes) return base64Bytes;
+    if (base58Bytes) return base58Bytes;

Please double‑check this against the actual formats you expect in production.


301-459: Treat empty certificate sets as failure, not success

When no key binding certificates are found, verifySignature currently returns valid: true:

if (keyBindingCertificates.length === 0) {
    return {
        valid: true,
    };
}

This means that if certificate lookup fails or a user has no certificates, any signature will be treated as valid, which is a significant security risk.

Suggest instead treating this as an error:

-        if (keyBindingCertificates.length === 0) {
-            return {
-                valid: true,
-            };
-        }
+        if (keyBindingCertificates.length === 0) {
+            return {
+                valid: false,
+                error: "No key binding certificates found for eName",
+            };
+        }

The rest of the verification loop (JWT + public‑key import + WebCrypto verify with aggregated errors) looks robust and is a nice improvement over a single‑shot attempt.

🧹 Nitpick comments (3)
infrastructure/signature-validator/src/index.ts (3)

8-35: Dynamic base58btc import flow looks solid; minor error‑message nit

The two‑stage import with caching is good and should fix the ESM/CJS interop issue. One small nit: inside the catch, the thrown error message interpolates err from the first attempt, even if the fallback dynamicImport is what actually failed. Consider either:

  • capturing the fallback error and using that in the message, or
  • emitting a more generic “both import strategies failed” message.

This is purely cosmetic; behavior is otherwise fine.


63-125: DER/hex helpers are correct for P‑256; looksLikeDerSpki currently unused

The hex and ECDSA DER helpers look correct for P‑256 (single‑byte length, 32‑byte r/s, uncompressed 65‑byte EC point) and match how you use them later in verifySignature.

looksLikeDerSpki is currently not referenced anywhere; if you don’t plan to use it soon, consider removing it to avoid dead code, or wiring it into the key‑import decision logic.


227-241: Base64‑like helper is fine, but duplicates fallback logic

tryDecodeBase64Like does the right padding and URL‑safe normalization for base64/base64url. Note there’s some duplication with the final base64 fallback block in decodeSignature (Lines 211‑218). If you end up evolving this further, consider centralizing base64 decoding in a single helper (this one) to keep behavior consistent.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f795e6f and b030d7c.

📒 Files selected for processing (1)
  • infrastructure/signature-validator/src/index.ts (5 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-04-16T18:04:28.983Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 99
File: infrastructure/w3id/tests/w3id.test.ts:48-57
Timestamp: 2025-04-16T18:04:28.983Z
Learning: In test files, suggestions to add defensive coding patterns (like extra null checks) are often unnecessary, as tests are designed to fail explicitly when expectations aren't met. The test in `infrastructure/w3id/tests/w3id.test.ts` validates that `id.logs` is an instance of `IDLogManager` before accessing its repository property.

Applied to files:

  • infrastructure/signature-validator/src/index.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (2)
infrastructure/signature-validator/src/index.ts (2)

134-169: Public‑key multibase decoding logic LGTM

Handling 0x hex, z+hex (SoftwareKeyManager), and standard z base58btc with a clear error on invalid input is straightforward and correct. Returning raw bytes and deferring format interpretation to the caller (SPKI vs raw EC point) keeps responsibilities nicely separated.


249-277: Certificate fetch flow looks good; behavior on malformed whois is clear

The two‑step /resolve/whois flow, with explicit timeouts and a clear Error when uri is missing, is solid. Returning [] when keyBindingCertificates is absent or not an array is a reasonable normalization, though note this interacts with verifySignature’s keyBindingCertificates.length === 0 branch (see separate comment there).

@coodos coodos merged commit 46f3dd6 into main Dec 15, 2025
3 of 4 checks passed
@coodos coodos deleted the fix/btc-base-58-slice branch December 15, 2025 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants