Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: MAC verification failed #21

Closed
cyrusbowman opened this issue Jun 6, 2017 · 6 comments
Closed

Error: MAC verification failed #21

cyrusbowman opened this issue Jun 6, 2017 · 6 comments

Comments

@cyrusbowman
Copy link

I believe there is something wrong here. Probably 25% of the time I get this error when downloading. The original fork doesn't have this issue, I believe because it uses it's own cipher implementation for MAC instead of cryptos aes-128-ecb.

Error: MAC verification failed
at Stream.end (../node_modules/megajs/dist/main.node-cjs.js:504:33)

@qgustavor
Copy link
Owner

qgustavor commented Jun 7, 2017 via email

@qgustavor
Copy link
Owner

qgustavor commented Jun 8, 2017

I checked the commit history and, sorry, it's messy so I can't show it to explain it better. I will explain the original code and mine:

  1. MEGA does encryption and decryption by using AES-CTR, authenticated by a MAC that they wrote;
  2. Old MEGA and tonistiigi's code use sjcl.js, which don't implement AES-CTR (it implements AES-CTR-MAC, but its MAC not compatible with MEGA's MAC), but it implement AES-ECB (as the sjcl.cipher.aes function) which can used to implement AES-CTR;
  3. Encrypting an stream works by computing the MAC based on the plaintext of each block then encrypting the block; decrypting does the inverse;
  4. The MAC is calculated starting with a nonce; this value is updated for each block processing by XORing it with the data processed then encrypting it using AES-ECB;
  5. The MEGA's developer documentation says that "File integrity is verified using chunked CTR-MAC. Chunk sizes start at 128 KB and increase to 1 MB"; tonistiigi's does it in this part of the code and mine in this part; There are some differences in this part:
    • My implementation use Buffers, tonistiigi's use Arrays;
    • In order to store each chunk MAC values tonistiigi's implementation use events and mine just use a simple array push;
    • As Node crypto module already handles AES-CTR my code don't needs to handle it;
  6. When encrypting or decrypting finishes the final MAC is calculated by condensing each chunk values; it works by taking a 0 filled array, then XORing it with the MAC of each chunk, encrypting it with the encryption key after each XOR operation, resulting in a 128 bit array (tonistiigi's implementation and mine);
  7. The result is reduced to a 64 bit array by XORing the first 64 bits with the last 64 bits; in my implementation this part is handled by aes.js, in tonistiigi's it's handled by mega.js;

So both implementations are equivalent in their results, but mine probably have better performance (but it can improved). Also note that there a test checking if this function is working in tonistiigi's and mine repositories. The values tested are the same (with a small difference in the test).

As I said before probably the issue is some not handled error. Do you tried the browser version? Other thing you can do is using a sniffer (as, following original implementation, downloading use HTTP) and try to check if MEGA returned an error at some point.

Edit: I mistook CTR with CBC. Fixed.

@cyrusbowman
Copy link
Author

I tried to build to test with the browser version but rollup is failing with the build.js script.

Error: 'default' is not exported by node_modules/duplexer/index.js (imported by node_modules/stream-combiner/index.js)

Thanks for the quick reply!
Cyrus

@qgustavor
Copy link
Owner

qgustavor commented Jun 9, 2017

What? Browser versions don't have dependencies: there isn't any "import " in the ES6 version and no "require(" in the UMD version.

You configured rollup right? plugin-node-resolve is configured to use browser: true? The Node version don't works in browsers unless replace the request module with one which works in browsers.

Edit - by the way you can load it in browser by using one of the two ways below:

<script src="https://unpkg.com/megajs@0.11.2/dist/main.browser-umd.js"></script>
<script type="module">
  import * as mega from 'https://unpkg.com/megajs@0.11.2/dist/main.browser-es.js'
  window.mega = mega // in order to export it as a global
</script>

@qgustavor
Copy link
Owner

What happened?

@qgustavor
Copy link
Owner

As there's no response I will close this issue. Maybe the problem was caused by #20, so in this case it will be fixed in future.

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

No branches or pull requests

2 participants