Should secrets include a fallback for hmac.compare_digest?
Now that PEP 506 has been approved, I've checked in the secrets module, but an implementation question has come up regarding compare_digest. Currently, the module tries to import hmac.compare_digest, and if that fails, then it falls back to a Python version. But since compare_digest has been available since 3.3, I'm now questioning whether the fallback is useful at all. Perhaps for alternate Python implementations? So, two questions: - should secrets include a fallback? - if so, what is the preferred way of doing this? # option 1: fallback if compare_digest is missing try: from hmac import compare_digest except ImportError: def compare_digest(a, b): ... # option 2: "C accelerator idiom" def compare_digest(a, b): ... try: from hmac import compare_digest except ImportError: pass Option 1 is closer to how I would write hybrid 2/3 code, but option 2 is how PEP 399 suggests it should be written. https://www.python.org/dev/peps/pep-0399/ Currently, hmac imports compare_digest from _operator. There's no Python version in operator either. Should there be? -- Steve
It's easy to implement this function (in the native language of your Python implemenation), it's short. I'm not sure that a Python version is really safe. The secrets module is for Python 3.6, in this version the hmac already "requires" the compare_digest() function no? Victor
On Fri, Apr 15, 2016 at 10:26:31AM +0200, Victor Stinner wrote:
It's easy to implement this function (in the native language of your Python implemenation), it's short. I'm not sure that a Python version is really safe.
The secrets module is for Python 3.6, in this version the hmac already "requires" the compare_digest() function no?
The current version looks like this: try: from hmac import compare_digest except ImportError: # fallback version defined but I'm having second thoughts about this. I don't think it needs to support older versions of Python, but perhaps it needs to support implementations which don't include compare_digest? This isn't just a question about the secrets module. PEP 399 suggests than any C classes/functions should have a pure Python version as fallback, but compare_digest doesn't. I don't know whether it should or not. https://www.python.org/dev/peps/pep-0399/ -- Steve
2016-04-15 11:21 GMT+02:00 Steven D'Aprano <steve@pearwood.info>:
This isn't just a question about the secrets module. PEP 399 suggests than any C classes/functions should have a pure Python version as fallback, but compare_digest doesn't. I don't know whether it should or not.
The hmac module is responsible to providing a fallback, not the secrets module. Victor
On 15 April 2016 at 10:35, Victor Stinner <victor.stinner@gmail.com> wrote:
2016-04-15 11:21 GMT+02:00 Steven D'Aprano <steve@pearwood.info>:
This isn't just a question about the secrets module. PEP 399 suggests than any C classes/functions should have a pure Python version as fallback, but compare_digest doesn't. I don't know whether it should or not.
The hmac module is responsible to providing a fallback, not the secrets module.
Agreed. The library docs state that the hmac module provides compare_digest, so you are therefore entitled to unconditionally import it (just as end user code would). Paul
On 15 April 2016 at 14:52, Steven D'Aprano <steve@pearwood.info> wrote:
Now that PEP 506 has been approved, I've checked in the secrets module, but an implementation question has come up regarding compare_digest.
Currently, the module tries to import hmac.compare_digest, and if that fails, then it falls back to a Python version. But since compare_digest has been available since 3.3, I'm now questioning whether the fallback is useful at all. Perhaps for alternate Python implementations?
So, two questions:
- should secrets include a fallback?
It definitely *shouldn't* include a fallback, as the function needs to be writen in C (or some other not-normal-Python-code language) in order to provide the appropriate timing guarantees. We added hmac.compare_digest in response to Python web frameworks providing their own pure Python "constant time" comparison functions that were nevertheless still subject to remote timing atacks. I'd forgotten about the hmac vs operator indirection, but it's still better to import the public API from hmac (since operator._compare_digest is a Python implementation detail, and you may as well make it easy to extract the secrets module for use in earlier versions - 2.7 also gained hmac.compare_digest as part of PEP 466). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
participants (4)
-
Nick Coghlan
-
Paul Moore
-
Steven D'Aprano
-
Victor Stinner