Last active
October 31, 2020 15:31
-
-
Save qgustavor/1308ce4970a7a9eaeef058466d1ec630 to your computer and use it in GitHub Desktop.
Simple MEGA downloader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export async function getMegaFile (megaUrl) { | |
const { handler, wrappedKey } = parseMegaUrl(megaUrl) | |
const url = await getDownloadUrl(handler) | |
const response = await fetch(url) | |
if (!response.ok) throw Error('MEGA request failed with ' + response.statusText) | |
const data = await response.arrayBuffer() | |
return decryptAesCtr(data, unwrapMegaKey(wrappedKey)) | |
} | |
function unwrapMegaKey (originalKey) { | |
const key = new Uint8Array(originalKey) | |
for (let i = 0; i < 16; i++) key[i] = key[i] ^ key[16 + i] | |
return key | |
} | |
async function decryptAesCtr (data, key) { | |
const keyWrapper = await window.crypto.subtle.importKey('raw', key.slice(0, 16), { | |
name: 'AES-CTR' | |
}, false, ['decrypt']) | |
const counter = new Uint8Array(16) | |
counter.set(key.slice(16, 24), 0) | |
const plainText = await crypto.subtle.decrypt({ | |
name: 'AES-CTR', | |
counter, | |
length: 64 | |
}, keyWrapper, data) | |
return plainText | |
} | |
export function parseMegaUrl (megaUrl) { | |
const parsedUrl = new URL(megaUrl) | |
const handler = parsedUrl.pathname.split('/').pop() | |
const wrappedKey = decodeBase64(parsedUrl.hash.substr(1)) | |
return { handler, wrappedKey } | |
} | |
export async function getDownloadUrl (handler) { | |
const response = await fetch('https://g.api.mega.co.nz/cs', { | |
method: 'POST', | |
body: JSON.stringify([{ | |
a: 'g', | |
g: 1, | |
ssl: 2, | |
p: handler | |
}]) | |
}) | |
if (!response.ok) throw Error(`MEGA returned with ${response.statusText}`) | |
const data = await response.json() | |
return data[0].g | |
} | |
function decodeBase64 (s) { | |
let i | |
// atob also works without = padding | |
// https://infra.spec.whatwg.org/#forgiving-base64-decode | |
const d = atob(s.replace(/-/g, '+').replace(/_/g, '/')) | |
const b = new Uint8Array(d.length) | |
for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i) | |
return b | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment