-
Notifications
You must be signed in to change notification settings - Fork 670
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
Getting a token takes nearly a second #820
Comments
up |
This is probably caused by https://forum.djangoproject.com/t/stop-increasing-default-pbkdf2-iteration-count/25539, if you change the password hasher or reduce the steps this will reduce the performance (but you will require to recreate all hashes... and theoretically the application will be less secure) |
@aperezlillo Affecting password security to gain performance is a bad idea. import time
import jwt
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
key_str = key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
)
# key = serialization.load_pem_private_key(key_str.encode(), password=None)
t = time.perf_counter()
tok = jwt.encode(payload={}, key=key, algorithm="RS256")
print((time.perf_counter() - t) * 1000)
t = time.perf_counter()
tok = jwt.encode(payload={}, key=key_str, algorithm="RS256")
print((time.perf_counter() - t) * 1000) |
I ran some tests, while majority of time is spent on checking if password is valid: In [4]: %timeit hashlib.pbkdf2_hmac("sha256", b"abcde", b"abcde", 600_000)
153 ms ± 665 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) generating a new access token for user could be made faster: ...:
...: import jwt
...: from cryptography.hazmat.primitives import serialization
...: from cryptography.hazmat.primitives.asymmetric import rsa
In [3]: key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
...: key_str = key.private_bytes(
...: encoding=serialization.Encoding.PEM,
...: format=serialization.PrivateFormat.PKCS8,
...: encryption_algorithm=serialization.NoEncryption(),
...: )
...:
In [4]: %timeit jwt.encode(payload={}, key=key, algorithm="RS256")
181 µs ± 6.21 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
In [5]: %timeit jwt.encode(payload={}, key=key_str, algorithm="RS256")
23.9 ms ± 152 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) |
Hi @ThirVondukr, thx for your answer, I was just answering the original question. I agree with you that changing this configuration is not recommended, but when you know the root cause of the problem you can make trade-offs, or as you made, trying to improve that piece of code. As you figured out, the main problem is with the password validation, not the token creation that is almost negligible. Depending on the hardware pbkdf2_hmac can take up Not sure how to address the main issue, could be worth to investigate alternative hashing libraries, or configurations. |
@aperezlillo I don't think you really can address the issue without compromising some of the security - if it's easier to validate password hash then it would be easier to crack it. |
Hi
I am trying out this library with Django 5 and python 3.12.
It works as expected, but getting a token for a user takes nearly a second. Around 950ms. Why? Is there some setting that improoves the generation time?
The text was updated successfully, but these errors were encountered: