Skip to content

Releases: mpiton/vortex-mod-mega

v1.0.0 — Initial release

05 May 06:05

Choose a tag to compare

First release of the MEGA WASM hoster plugin for Vortex.

Overview

vortex-mod-mega resolves public MEGA share URLs into download metadata + per-file decryption material so the Vortex core engine can stream encrypted bytes from the CDN, decrypt in place with AES-128-CTR, and verify integrity via the chunk-MAC fold against the URL's metaMac. No wait timer, no captcha, no subprocess — http capability only.

Both URL shapes are supported, modern and legacy:

  • File: https://mega.nz/file/<id>#<key> or https://mega.co.nz/#!<id>!<key>
  • Folder: https://mega.nz/folder/<id>#<key> or https://mega.co.nz/#F!<id>!<key>

Folder URLs are decrypted in-plugin: each child node's encrypted key blob is unwrapped via AES-128-ECB with the folder master key, the recovered 32-byte raw key is XOR-folded into the same MegaFileKey shape as a URL key, and the encrypted attribute blob is decrypted via AES-128-CBC (IV = 0₁₂₈) to recover the filename. Each child is then re-emitted as a synthetic mega.nz/file/<handle>#<key> URL the host re-feeds through the regular file-URL pipeline.

Plugin contract

Function Input Output
can_handle URL string \"true\" for any mega.nz file or folder URL, \"false\" otherwise
supports_playlist URL string \"true\" for folder URLs, \"false\" for file URLs
extract_links URL string JSON {kind: \"file\"|\"folder\", files: [FileLink]} with EncryptionInfo
resolve_stream_url {url} JSON Encrypted CDN URL (host fetches the bytes, decrypts in stream)

FileLink.encryption.scheme = \"mega-aes128-ctr\" carries the per-file AES key, IV and metaMac (all hex-encoded). Hosts unaware of this scheme must refuse the download — the bytes from direct_url are ciphertext.

Crypto core

  • AES-128-CTR streaming via RustCrypto (aes + ctr), counter is iv ‖ 0₆₄, in-place decrypt
  • Chunk MAC with MEGA's canonical schedule (128, 256, 384, …, 1024 KiB, then 1 MiB) — one CBC-MAC per chunk, all chunk MACs folded through one final CBC-MAC, file MAC = XOR of the two 8-byte halves of the result
  • MAC mismatchPluginError::MacMismatch (host marks the download as corrupted)
  • Memory bounds — caller-controlled buffer, decryptor state grows only with chunk_macs.len() (~64 KB for a 4 GB stream)

API & error handling

JSON-RPC over https://g.api.mega.co.nz/cs?id=<seq>:

  • g command — single-file resolution, returns encrypted CDN URL + size
  • f command — folder enumeration, returns the node tree

MEGA error vocabulary maps onto the Vortex plugin-error type:

MEGA / HTTP PluginError
-9 (ENOENT) Offline
-3, -6 (EAGAIN) RateLimited
Other negative codes ApiError(code)
HTTP 404 / 410 Offline
HTTP 429 / 509 RateLimited
HTTP other 4xx/5xx HttpStatus

Tests

  • 61 native unit tests across error, url_matcher, key_parser, crypto, api_client, node_parser, lib
  • 4 WASM smoke tests for can_handle / supports_playlist
  • 1 end-to-end folder decryption test (loads the WASM artefact via Extism, stubs http_request to return a synthetic f response built with real AES-128-ECB key wrapping + AES-128-CBC attribute encryption, asserts decrypted child handle / filename / size)

cargo clippy --all-targets -- -D warnings clean, cargo fmt clean.

Checksums

Both assets are published below. Their SHA-256 are pinned in vortex/registry/registry.toml.

Asset SHA-256
vortex_mod_mega.wasm ee4fd7716f56802e43cef2804ddf6a49346177b716afffc974867a3316290f07
plugin.toml c9420281eb587afc938142c5f70104b0febb176fe68cd2ec441c275c0b4ef805

License

GPL-3.0