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

replace Pycrypto - which is unsupported and buggy #2365

Closed
ghost opened this issue Jan 9, 2017 · 43 comments · Fixed by #4652
Closed

replace Pycrypto - which is unsupported and buggy #2365

ghost opened this issue Jan 9, 2017 · 43 comments · Fixed by #4652
Labels
area:bootloader Caused be or effecting the bootloader @high pull-request wanted Please submit a pull-request for this, maintainers will not actively work on this.

Comments

@ghost
Copy link

ghost commented Jan 9, 2017

[htgoebel is taking over this formerly empt comment]

pycrypto, which PyInstaller uses for byte-code encryption, needs to be replaced. Its officially "dead" and seriously buggy. Further pycrypto doe not work for Python 3.6 (see below). Replacement options seem to be:

  • pycryptdome - which calls it self a drop in replacement but does not work as expected (see below)
  • cryptography.

Maintainer note: If you want this to be fixed, please place an adequate(!) bounty or submit a pull-request. The requirement for byte-encryption is a commercial one (free software does not require byte-encryption since the cod is available anyway). So if you are earning money with using PyInstaller you should take parts of the development.

@ProjectThreepio
Copy link

Just wanted to point out in this bug too that PyCrypto is abandoned and it may actually be less effort to move to pycryptodome then to try to get PyCrypto working on Python 3.6.

@ghost
Copy link
Author

ghost commented Feb 2, 2017

Unfortunately using pycryptodome looks like a non-trivial problem. Aside from some easy-to-fix errors on Python 3, I received this daunting error:

Traceback (most recent call last):
  File "PyInstaller/loader/pyiboot01_bootstrap.py", line 25, in <module>
  File "/home/travis/build/pyinstaller/pyinstaller/PyInstaller/loader/pyimod03_importers.py", line 315, in load_module
    is_pkg, bytecode = self._pyz_archive.extract(real_fullname)
  File "/home/travis/build/pyinstaller/pyinstaller/PyInstaller/loader/pyimod02_archive.py", line 352, in extract
    obj = zlib.decompress(obj)
zlib.error: Error -3 while decompressing data: incorrect header check

I personally wouldn't benefit from this feature and I estimate that this could take up to a week to debug. If I may be so bold, I predict that this could turn into another fiasco like MERGE (which has been unfixed for well over a year now).

@ProjectThreepio
Copy link

Agreed it's non-trivial. pycryptodome is far from a drop-in replacement in this particular case. It may end up being a matter of re-writing the feature from the ground up. However, the feature is pretty limited in scope, so maybe that's not an absolute dealbreaker. Still easier than getting PyCrypto working in 3.6 ;)

@htgoebel htgoebel changed the title Pycrypto is not tested on Python 3.6 replace Pycrypto - which is unsupported and buggy Feb 2, 2017
@htgoebel htgoebel added @low good first issue This is a good issue if you want to start working on PyInstaller labels Feb 3, 2017
@ProjectThreepio
Copy link

For what it's worth, there are non-commercial uses for byte-encryption, if it's not the code you're trying to obfuscate per se, but sensitive information within that code (generally things you wish you didn't have to do, like hard-coded passwords). While the perfect solution would be to not do this at all, byte-encryption is a desirable band-aid until the perfect solution can be implemented. We use this for in-house scripts, and we're not commercial. I'm afraid I've seen this sort of sensitive data in infrastructure/maintenance scripts in lots of places, so I don't think we're unique.

@lambdaq
Copy link

lambdaq commented Feb 23, 2017

+1 for https://github.com/pyca/cryptography

@jftuga
Copy link

jftuga commented Jun 29, 2017

FWIW, I've been using https://github.com/pyca/cryptography in conjunction with netmiko for controlling SSH sessions under Python 3.6 and this works very well.

@answerquest
Copy link

answerquest commented Apr 24, 2018

Copying this over from #3316
Use pycryptodomex, and replace all Crypto terms in the python program's import statements with Cryptodome. The disambiguation is important : it eliminates so many complicated workarounds like hooks etc. It's a wholly different package now and pyinstaller is able to compile it without a hitch. I've posted details (what worked at my end.. I'm not any expert in this subject FYI) in this answer on stackoverflow.

Note: If pycryptodome is working fine for you in your program then this pycryptodomex replacement will help you pyinstaller your program without needing to do any hiddenimports etc. If you haven't able to move from pycrypto to pycryptodome even in your .py program then this solution is not for you.

@MichaelWS
Copy link

what would be a sufficient bounty for this?

@ProjectThreepio
Copy link

I placed a modest bounty on this bug. It may not be sufficient, but if everyone chips in what they can, it may become adequate to get it fixed.

@ProjectThreepio
Copy link

FWIW, a developer has placed a $600 bounty goal on this bug. I've already committed $300 and am tapped out. Assistance would be appreciated. I don't know how these bounty goals work exactly, but presumably there's some interest at least right now, and that's a good thing.

@collinalexbell
Copy link

I'll work on this issue tomorrow.

@collinalexbell
Copy link

It seems someone has already made a pull request regarding this issue.

#4241

If that PR is insufficient, then I will work on the issue.

@gpraceman
Copy link

I'll chip in $100 to the bounty pool to get this issue fixed. It worked for me with Python 3.4, but now I've had to move up to 3.7.

@collinalexbell
Copy link

Depends on if PR #4241 is insufficient to fix this issue. We may just be waiting for a merge.

@ProjectThreepio
Copy link

That pull request may be the solution we're looking for... but it hasn't been touched in a month, and it fails some automated checks, so it's not getting merged without some love first.

Right now, the bug bounty is probably the place where we can do the most to make this happen:
https://www.bountysource.com/issues/40772962-replace-pycrypto-which-is-unsupported-and-buggy

@cittyinthecloud
Copy link

@ProjectThreepio @SlightlyCyborg Sorry, app for checking PR notifications was being buggy. I'm not sure what check it's failing, but I'm pretty sure it's codestyle

@cittyinthecloud
Copy link

Yep, it was line length :P, not used to it being 79, mine is usually 120

@ProjectThreepio
Copy link

veeshi commented earlier about another effort:

PR #4241 uses pyaes which hasn't had any commits since Sep 20, 2017. Since PyInstaller is well used IMHO it seems more appropriate to use PyCryptodome as @answerquest said as it is regularly updated, feature rich, large community and has performant block ciphers written in C unlike pyaes which is pure python.

While I'm not sure that means you must use a big established, long-supported module like PyCryptodome, cryptography is hard, so we should make an effort to ensure cryptographers are actively maintaining the modules we're using. That said, this is ultimately about code obfuscation and can be circumvented by a motivated attacker even under the best of circumstances, so it's not about the quality of the encryption per se, but about the long-term quality of the module's code.

No matter what solution ends up working, consider contributing to the bug bounty:
https://www.bountysource.com/issues/40772962-replace-pycrypto-which-is-unsupported-and-buggy

@mnboos
Copy link

mnboos commented Jan 28, 2020

Is mnboos still working on this or does he need someone else to work on addressing those limitations he identified?

Maybe I will continue working on it in the near future.

@naufraghi
Copy link
Contributor

The "problem" with bigger libraries is the the attack surface is bigger, and, considering AES CTR mode was introduced in 1979 (wikipedia), I expect most implementations to be quite stable.

The https://github.com/kokke/tiny-AES-c seems to be maintained (the author is responsive on issues and PRs), tested with official codes, and used / starred enough to have a lot of eyes pointed to highlight any security problem may arise in the future.

The wrapper itself is so minimal that could be printed on a t-shirt, and exposes the plain API, please audit it for any problem I may have overlooked.

In the case of PyCrypto, beside the unmaintained state, all the security advisories where not against the AES module, that is the only one included for encryption, but other modules.

So, IMHO, we should not search for a library with a commit each week, if not adding new unrelated features, that is not a good sign for a base crypto library, each commit may introduce bugs, and if there are no known security problems, the library (using 1979 knowledge) is fair to be stale.

That said, we already know that the encryption mode in PyInstaller is an easy obstacle for a motivated cracker, even without involving any crypto attack, so I'd better favor an easy implementation that has minimal impact on the overall code, easier to maintain and evolve, just to represent the security trade-off the feature is offering, avoid tampering and easy reverse engineering and not much more.

Here is a WIP branch: #4652 (opened a PR to trigger the CI)

PS. just in case, I'm not interested in reclaiming the bounty

naufraghi added a commit to naufraghi/pyinstaller that referenced this issue Jan 29, 2020
naufraghi added a commit to naufraghi/pyinstaller that referenced this issue Jan 29, 2020
naufraghi added a commit to naufraghi/pyinstaller that referenced this issue Jan 29, 2020
[tinyaes](https://github.com/naufraghi/tinyaes-py) is a minimal AES-only
library that wraps the C library [tiny-AES-c](https://github.com/kokke/tiny-AES-c).

Currently the library wraps only the CTR mode that can be used in
PyInstaller instead of the CFB mode used before.

Reading various sources, CFB is [somewhat similar to CBC](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_(CFB)))
and CTR is suggested as a go-to stream cipher (https://crypto.stackexchange.com/questions/6029/aes-cbc-mode-or-aes-ctr-mode-recommended and links)
that can be used instead of CBC.

See issue pyinstaller#2365

PR iterations:

- use tinyaes from pypi (installing from git triggers a key confirmation)
- make lint job happy
@ProjectThreepio
Copy link

The bounty for this bug has been boosted. BountySource's site appears to be having troubles right now, so it's hard to see this change.

naufraghi added a commit to naufraghi/pyinstaller that referenced this issue Feb 7, 2020
[tinyaes](https://github.com/naufraghi/tinyaes-py) is a minimal AES-only
library that wraps the C library [tiny-AES-c](https://github.com/kokke/tiny-AES-c).

Currently the library wraps only the CTR mode that can be used in
PyInstaller instead of the CFB mode used before.

Reading various sources, CFB is [somewhat similar to CBC](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_(CFB)))
and CTR is suggested as a go-to stream cipher (https://crypto.stackexchange.com/questions/6029/aes-cbc-mode-or-aes-ctr-mode-recommended and links)
that can be used instead of CBC.

See issue pyinstaller#2365

PR iterations:

- use tinyaes from pypi (installing from git triggers a key confirmation)
- make lint job happy
@Legorooj Legorooj added @high area:bootloader Caused be or effecting the bootloader and removed @low good first issue This is a good issue if you want to start working on PyInstaller labels Feb 8, 2020
@Legorooj
Copy link
Member

Legorooj commented Feb 9, 2020

@ProjectThreepio and anyone else who had committed to the bounty - is there a way for @htgoebel to claim it due to the fact @naufraghi isn't interested? To fund PyInstaller maintenance and development

@Legorooj
Copy link
Member

Legorooj commented Feb 9, 2020

Oh and if @naufraghi's solution doesn't work/satisfy, I'll be happy to implement this with cryptography.

@ProjectThreepio
Copy link

The bounty is for whoever can write code that makes whatever cut is required to get accepted into the production version of PyInstaller. So in a sense @htgoebel decides the matter, not me. If the person who writes that code doesn't want to claim it, I believe I can (and would) revert it to general PyInstaller project maintenance, or another PyInstaller bug.

@Legorooj
Copy link
Member

Legorooj commented Feb 9, 2020

@ProjectThreepio I agree. It should be repurposed at the least. As my second comment says, I could do this, but don't see the point of doing it if naufraghi's solution works - and if I do end up doing it, I'd donate half of the bounty to the team.

@naufraghi
Copy link
Contributor

I'm OK to give the bounty to the dev team, I very thank them for their work with PyInstaller!

I added a test suite to the wrapper, using hypothesis and found a bug, the bug is fixed, so I think I'll release tinyaes-py 1.0.0 later today and rebase the PR pointing the release (or a semver 1-ish one).

@Legorooj
Copy link
Member

I'll review the wrapper at some point soon as well. It's always good to have a second pair of eyes look over it! @naufraghi

@ProjectThreepio
Copy link

I had no idea PyInstaller was in such financial straits until now! Yes, absolutely redirect my bounty to general PyInstaller operations, ASAP!

@Legorooj
Copy link
Member

@ProjectThreepio thanks! I've only been on the team a week, and I offered htgoebel help with the GitHub end to start with. If he doesn't have to sort through the many support issues and other ones that don't need core developer attention, he'll be able to put more if his funded time towards PyInstaller core...

naufraghi added a commit to naufraghi/pyinstaller that referenced this issue Feb 17, 2020
[tinyaes](https://github.com/naufraghi/tinyaes-py) is a minimal AES-only
library that wraps the C library [tiny-AES-c](https://github.com/kokke/tiny-AES-c).

Currently the library wraps only the CTR mode that can be used in
PyInstaller instead of the CFB mode used before.

Reading various sources, CFB is [somewhat similar to CBC](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_(CFB)))
and CTR is suggested as a go-to stream cipher (https://crypto.stackexchange.com/questions/6029/aes-cbc-mode-or-aes-ctr-mode-recommended and links)
that can be used instead of CBC.

See issue pyinstaller#2365

PR iterations:

- use tinyaes from pypi (installing from git triggers a key confirmation)
- make lint job happy
- remove some unused imports
- better explain test for issue pyinstaller#1663
naufraghi added a commit to naufraghi/pyinstaller that referenced this issue Feb 17, 2020
[tinyaes](https://github.com/naufraghi/tinyaes-py) is a minimal AES-only
library that wraps the C library [tiny-AES-c](https://github.com/kokke/tiny-AES-c).

Currently the library wraps only the CTR mode that can be used in
PyInstaller instead of the CFB mode used before.

Reading various sources, CFB is [somewhat similar to CBC](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_(CFB)))
and CTR is suggested as a go-to stream cipher (https://crypto.stackexchange.com/questions/6029/aes-cbc-mode-or-aes-ctr-mode-recommended and links)
that can be used instead of CBC.

See issue pyinstaller#2365

PR iterations:

- use tinyaes from pypi (installing from git triggers a key confirmation)
- make lint job happy
- remove some unused imports
- better explain test for issue pyinstaller#1663
naufraghi added a commit to naufraghi/pyinstaller that referenced this issue Feb 21, 2020
[tinyaes](https://github.com/naufraghi/tinyaes-py) is a minimal AES-only
library that wraps the C library [tiny-AES-c](https://github.com/kokke/tiny-AES-c).

Currently the library wraps only the CTR mode that can be used in
PyInstaller instead of the CFB mode used before.

Reading various sources, CFB is [somewhat similar to CBC](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_(CFB)))
and CTR is suggested as a go-to stream cipher (https://crypto.stackexchange.com/questions/6029/aes-cbc-mode-or-aes-ctr-mode-recommended and links)
that can be used instead of CBC.

Closes pyinstaller#2365

PR iterations:

- use tinyaes from pypi (installing from git triggers a key confirmation)
- make lint job happy
- remove some unused imports
- better explain test for issue pyinstaller#1663
naufraghi added a commit to naufraghi/pyinstaller that referenced this issue Mar 21, 2020
[tinyaes](https://github.com/naufraghi/tinyaes-py) is a minimal AES-only
library that wraps the C library [tiny-AES-c](https://github.com/kokke/tiny-AES-c).

Currently the library wraps only the CTR mode that can be used in
PyInstaller instead of the CFB mode used before.

Reading various sources, CFB is [somewhat similar to CBC](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_(CFB)))
and CTR is suggested as a go-to stream cipher (https://crypto.stackexchange.com/questions/6029/aes-cbc-mode-or-aes-ctr-mode-recommended and links)
that can be used instead of CBC.

Closes pyinstaller#2365

PR iterations:

- use tinyaes from pypi (installing from git triggers a key confirmation)
- make lint job happy
- remove some unused imports
- better explain test for issue pyinstaller#1663
htgoebel pushed a commit to naufraghi/pyinstaller that referenced this issue Apr 19, 2020
This re-enables encrypting the Python bytecode (option ``--key``).

`tinyaes <https://github.com/naufraghi/tinyaes-py>`_
is a minimal AES-only library that wraps the C library
`tiny-AES-c <https://github.com/kokke/tiny-AES-c>`_.

Currently the library wraps only the CTR mode that can be used in
PyInstaller instead of the CFB mode used before.

Reading various sources, CFB is `somewhat similar to CBC
<https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_(CFB)>`_
and CTR is suggested as a go-to stream cipher
(see <https://crypto.stackexchange.com/questions/6029> and links)
that can be used instead of CBC.

Closes pyinstaller#2365.
Legorooj pushed a commit that referenced this issue May 31, 2020
#4652)

This re-enables encrypting the Python bytecode (`--key`) by replacing PyCrypto with tinyaes.

tinyaes is a minimal AES-only library that wraps the C library tiny-AES-c. See
https://github.com/naufraghi/tinyaes-py for source code. 

Closes #2365.
cool-RR pushed a commit to cool-RR/pyinstaller that referenced this issue Jun 20, 2020
pyinstaller#4652)

This re-enables encrypting the Python bytecode (`--key`) by replacing PyCrypto with tinyaes.

tinyaes is a minimal AES-only library that wraps the C library tiny-AES-c. See
https://github.com/naufraghi/tinyaes-py for source code. 

Closes pyinstaller#2365.
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 17, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area:bootloader Caused be or effecting the bootloader @high pull-request wanted Please submit a pull-request for this, maintainers will not actively work on this.
Projects
None yet
Development

Successfully merging a pull request may close this issue.