-
Notifications
You must be signed in to change notification settings - Fork 790
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
CAST5 file decryption hangs indefinitely #1668
Comments
Hey 👋 Could you perhaps generate a new test key and file using V4, in a similar setup as these files were generated in, then check if they also reproduce the issue, and if so share them here, to make it easier to reproduce? |
When you say "the decryption process hangs indefinitely", does it mean that the code after If it's |
Yes, the call to decrypt() never returns, but only when using node >= 18 and openPGP.js 5.10.1. The file decrypts successfully using the exact same code using node 16 and openPGP.js > 5.10.1. After debugging a bit more, we have a few more insights to share - the following is sanitized output from using GPG directly:
These are the config flags we're using for decryption:
Since the encrypted file contains sensitive information, we'd like to exhaust all potential avenues for debugging before sending it over - are there any other suggestions you can offer? |
@twiss - unfortunately, the files sent to us are encrypted by our clients using a variety of different mechanisms - it is unclear what method our client used to encrypt this file, but we have been unable to reproduce the issue outside of this file. (We have tried OpenPGP V4, V5, and GPG) We have no issues decrypting this file using GPG, OpenPGP V4, or OpenPGP V5 and Node 16. The only time it breaks is with OpenPGP V5 and Node 18+. This feels like a race condition somewhere; if the file were corrupted, I don't imagine we'd be able to decrypt it at all - but that is not the case. Do you have any suggestions for ways we can continue to debug this and/or reproduce this issue? |
I don't think we can do much without the file itself. Based on the GPG output, it's a very old & messy file, with a deprecated encryption mechanism. The reason why re-encrypting it works, is simply because it gets re-encrypted using a modern construction.
Can you try and spot where it hangs? One way to do this, without a debugger, is to edit the OpenPGP.js package.json in the node_modules, to point to the non-minified OpenPGP.js dist for Node. Then you can try and change the code in the target openpgpjs bundle under dist, by adding console.logs in I think the issue might be related to #1449 , even tho it's unclear to me why the Node version would make a difference . Edit: just to be sure, are you testing on Node 16 and 18 on the same machine, or different ones? |
Thank you for the guidance @larabr - confirming that the tests for Node 16 and Node 18 are being run on the same machine using NVM to handle swapping between runtimes. I'll try your suggestion for adding logs to the non-minified dist and see if I can pinpoint where this is breaking - if that doesn't work I'll reach out to see if we can dig into this together. Really appreciate your help here! |
I have a few updates to share after debugging against the non-minified dist:
From stepping through the code, the readToEnd method for the stream doesn't get a return value from the final call to this._read() and hangs indefinitely. |
Thanks for the info @T-parrish , we'll look into what might be going wrong with the streaming. BTW for this specific file, due to its legacy construction (require passing |
Attempted to pass a manually converted Web Stream to the
I also tried reading the entire file into a Uint8Array - in this case, it seems like it may finish decrypting over the span of several hours (file size ~520kb) :
Stepping through the
It's unclear if the file will actually finish decrypting once the size of the decblock container reaches 0 or if this is unexpected behavior, but this seems like it could be an important detail to share. Hope this helps, but let me know if I can provide any more context / information. |
Ah, you're reaching the JS implementation of CFB. That's a bit surprising as normally it's built-in to Node Crypto, and we use the native implementation if it's available. However, it seems that Cast5-CFB was removed in Node 18: $ nvm use 16
Now using node v16.20.2 (npm v8.19.4)
$ node -e 'console.log(require("crypto").getCiphers().includes("cast5-cfb"))'
true
$ nvm use 18
Now using node v18.17.1 (npm v9.6.7)
$ node -e 'console.log(require("crypto").getCiphers().includes("cast5-cfb"))'
false (while e.g. AES-*-CFB is still there). The behavior you mentioned is expected, I believe, so this would point to it being more of a performance issue rather than an infinite loop, for example. (And, thanks for the additional details!) Though, it's still a bit surprising to me that decrypting 520kb would take several hours. I'm also not sure why it'd be different in OpenPGP.js v4, I don't think we changed much here. Perhaps, could you step through the decryption using v4 as well and see if there's any observable difference? |
Thanks for digging into this @T-parrish , there is actually a CFB-decryption performance issue for legacy (non-AES) ciphers, I could repro in the browser even for files with the MDC. The affected code should be the same as v4 though. Did you test v4 on Node 18 too? |
@T-parrish we just released v5.10.2 🙂 |
When attempting to decrypt a 512kb csv file, the decryption process hangs indefinitely and the CPU spins up to 100%.
A few other details of note:
This seems like a race condition of some sort, but I could be wrong. Any help or suggestions to debug this would be greatly appreciated - we would love to upgrade our codebase to OpenPGP V5 but without understanding the root cause of this issue and building tests to catch this moving forward, we are unable to do so.
The text was updated successfully, but these errors were encountered: