Skip to content

Fixed Aptos verifyMessage to use SDK's own Ed25519 verification#79

Open
SergeyG-Solicy wants to merge 1 commit intomainfrom
fix/aptos-verify-message
Open

Fixed Aptos verifyMessage to use SDK's own Ed25519 verification#79
SergeyG-Solicy wants to merge 1 commit intomainfrom
fix/aptos-verify-message

Conversation

@SergeyG-Solicy
Copy link
Copy Markdown
Contributor

@SergeyG-Solicy SergeyG-Solicy commented Mar 12, 2026

Summary by CodeRabbit

  • Refactor
    • Improved Aptos signature verification by leveraging official SDK methods instead of manual implementation, enhancing reliability and maintainability.

@SergeyG-Solicy SergeyG-Solicy requested a review from tcsenpai March 12, 2026 11:13
@qodo-code-review
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Use Aptos SDK's native Ed25519 verification instead of node-forge

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Replaced node-forge dependency with Aptos SDK's native Ed25519 verification
• Simplified verifyMessage implementation using SDK's built-in cryptographic methods
• Removed manual signature and public key validation logic
• Eliminated external dependency on node-forge library
Diagram
flowchart LR
  A["verifyMessage method"] --> B["Create Ed25519PublicKey from string"]
  A --> C["Create Ed25519Signature from bytes"]
  B --> D["Call SDK's verifySignature method"]
  C --> D
  D --> E["Return boolean result"]
  F["Remove node-forge dependency"] -.-> E
Loading

Grey Divider

File Changes

1. src/multichain/core/aptos.ts 🐞 Bug fix +7/-20

Replace node-forge with Aptos SDK Ed25519 verification

• Added imports for Ed25519PublicKey and Ed25519Signature from Aptos SDK
• Removed node-forge import dependency
• Refactored verifyMessage method to use SDK's native Ed25519PublicKey.verifySignature() instead
 of forge.pki.ed25519.verify()
• Eliminated manual validation of signature and public key byte lengths

src/multichain/core/aptos.ts


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review bot commented Mar 12, 2026

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Remediation recommended

1. Public key not validated 🐞 Bug ⛯ Reliability
Description
APTOS.verifyMessage now constructs Ed25519PublicKey directly from the provided publicKey
string without applying the repo’s hex normalization/validation or enforcing expected key/signature
lengths. As a result, malformed/odd-length/non-hex public keys are no longer rejected by
deterministic application-layer checks before reaching SDK verification.
Code

src/multichain/core/aptos.ts[R434-440]

+            const pubKey = new Ed25519PublicKey(publicKey)
+            const sig = new Ed25519Signature(hexToUint8Array(signature))

-            // Validate input sizes
-            if (signatureBytes.length !== 64) {
-                throw new Error("Invalid signature length. Ed25519 signatures must be 64 bytes.")
-            }
-            if (publicKeyBytes.length !== 32) {
-                throw new Error("Invalid public key length. Ed25519 public keys must be 32 bytes.")
-            }
-
-            // Use node-forge for Ed25519 signature verification
-            const isValid = forge.pki.ed25519.verify({
-                message: message,
-                encoding: "utf8",
-                signature: signatureBytes,
-                publicKey: publicKeyBytes
+            return pubKey.verifySignature({
+                message,
+                signature: sig,
            })
-
-            return isValid
Evidence
The updated verifyMessage path validates/parses signature via hexToUint8Array, but passes
publicKey straight into the SDK constructor with no shared validation/normalization. The repo
already has a standard hex validator/normalizer (hexToUint8Array) and a standard hex formatter
(uint8ArrayToHex) used by signMessage, so skipping the validator for publicKey is inconsistent
and removes deterministic preflight checks at this layer.

src/multichain/core/aptos.ts[428-440]
src/encryption/unifiedCrypto.ts[62-106]
src/multichain/core/aptos.ts[408-414]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`APTOS.verifyMessage` currently passes `publicKey` directly into `Ed25519PublicKey(...)` without using the repo’s hex normalization/validation helper (`hexToUint8Array`) and without enforcing expected byte lengths. This removes deterministic, application-layer input validation and makes behavior depend entirely on SDK parsing.

### Issue Context
- `hexToUint8Array` already strips an optional `0x` prefix and rejects odd-length/non-hex input.
- `signMessage` produces `0x`-prefixed hex via `uint8ArrayToHex`.

### Fix Focus Areas
- src/multichain/core/aptos.ts[428-445]

### Suggested change (one safe approach)
1. Validate/normalize both inputs first:
  - `const sigBytes = hexToUint8Array(signature)` and check `sigBytes.length === 64`.
  - `const pubKeyBytes = hexToUint8Array(publicKey)` and check `pubKeyBytes.length === 32`.
2. Then construct SDK objects:
  - `const sig = new Ed25519Signature(sigBytes)`
  - `const pubKey = new Ed25519PublicKey(publicKey)` (or `pubKeyBytes` if the SDK constructor supports bytes)
3. Keep the rest of the verification flow unchanged.

This preserves consistent validation semantics regardless of SDK parsing behavior.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 12, 2026

Walkthrough

Refactors Ed25519 signature verification in the Aptos module by replacing manual node-forge-based verification with SDK-provided Ed25519PublicKey and Ed25519Signature classes. Removes input-size checks and delegates verification directly to the SDK's verifySignature method.

Changes

Cohort / File(s) Summary
Ed25519 Verification Refactoring
src/multichain/core/aptos.ts
Replaces manual Ed25519 verification using node-forge with SDK-provided cryptographic classes and their native verifySignature method. Removes redundant input-size validation and simplifies the verification logic.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 ✨ No more forging crypto by hand,
The SDK's Ed25519 takes its stand!
Signatures dance through cleaner code,
Verification's lighter down the road!
Refactored well, this change takes flight! 🚀

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: replacing manual Ed25519 verification with the SDK's built-in verification method in the Aptos module.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/aptos-verify-message

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.

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/multichain/core/aptos.ts`:
- Around line 434-439: The verification uses a raw JS string while signMessage
signs new TextEncoder().encode(message), causing a mismatch for hex-looking
strings; update the call to pubKey.verifySignature in Aptos-related code to pass
the same UTF-8 bytes (e.g., new TextEncoder().encode(message)) instead of the
raw string so Ed25519PublicKey.verifySignature and the earlier signMessage use
identical byte input.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 73e72635-527a-4e5a-aed8-876d9e1ddea1

📥 Commits

Reviewing files that changed from the base of the PR and between 81811d7 and 91bc40b.

📒 Files selected for processing (1)
  • src/multichain/core/aptos.ts

Comment on lines +434 to +439
const pubKey = new Ed25519PublicKey(publicKey)
const sig = new Ed25519Signature(hexToUint8Array(signature))

// Validate input sizes
if (signatureBytes.length !== 64) {
throw new Error("Invalid signature length. Ed25519 signatures must be 64 bytes.")
}
if (publicKeyBytes.length !== 32) {
throw new Error("Invalid public key length. Ed25519 public keys must be 32 bytes.")
}

// Use node-forge for Ed25519 signature verification
const isValid = forge.pki.ed25519.verify({
message: message,
encoding: "utf8",
signature: signatureBytes,
publicKey: publicKeyBytes
return pubKey.verifySignature({
message,
signature: sig,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

For the @aptos-labs/ts-sdkversion used in this repository, how does Ed25519PublicKey.verifySignature interpretmessage when it is passed a JavaScript string? Does it verify UTF-8 bytes, or does it expect hex/HexInput semantics?

💡 Result:

In @aptos-labs/ts-sdk (e.g., v1.16.0), Ed25519PublicKey.verifySignature({ message }) treats a JavaScript string as follows:

  • If the string is a valid hex string per the SDK’s Hex.isValid rules (optional 0x prefix, non-empty, even-length, only hex chars), it is interpreted as hex bytes (i.e., HexInput semantics), not UTF-8. [1][2]
  • Otherwise, it converts the string to UTF-8 bytes via Buffer.from(message, "utf8") and verifies those bytes. [2][1]

So: it’s “hex-if-it-looks-like-hex, otherwise UTF-8.” [2][1]

Sources: [1] https://app.unpkg.com/%40aptos-labs/ts-sdk%401.16.0/files/dist/esm/chunk-CX4BEIQT.mjs, [2] https://app.unpkg.com/%40aptos-labs/ts-sdk%401.16.0/files/dist/esm/chunk-F7EMGK4M.mjs, [3] https://app.unpkg.com/%40aptos-labs/ts-sdk%401.16.0/files/dist/esm/chunk-BCUSI3N6.mjs


Verify the same UTF-8 bytes that signMessage signs.

Line 412 signs new TextEncoder().encode(message), but Line 438 passes the raw JS string into verifySignature. The @aptos-labs/ts-sdk applies a heuristic when interpreting string input: if it looks like valid hex, it treats it as hex bytes; otherwise, it converts to UTF-8.

For the test case "Hello Aptos!", this works because it is not valid hex, so the SDK falls back to UTF-8. However, any message that happens to be a valid hex string (e.g., "aabbcc") will be signed as UTF-8 bytes but verified as hex bytes, causing verification to fail.

Encode the message before verification to make both paths use identical bytes and avoid this fragility.

Proposed fix
     async verifyMessage(
         message: string,
         signature: string,
         publicKey: string
     ): Promise<boolean> {
         try {
+            const messageBytes = new TextEncoder().encode(message)
             const pubKey = new Ed25519PublicKey(publicKey)
             const sig = new Ed25519Signature(hexToUint8Array(signature))
 
             return pubKey.verifySignature({
-                message,
+                message: messageBytes,
                 signature: sig,
             })
         } catch (error) {
             console.error("Failed to verify message:", error)
             return false
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/multichain/core/aptos.ts` around lines 434 - 439, The verification uses a
raw JS string while signMessage signs new TextEncoder().encode(message), causing
a mismatch for hex-looking strings; update the call to pubKey.verifySignature in
Aptos-related code to pass the same UTF-8 bytes (e.g., new
TextEncoder().encode(message)) instead of the raw string so
Ed25519PublicKey.verifySignature and the earlier signMessage use identical byte
input.

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.

1 participant