115 lines
2.4 KiB
Plaintext
115 lines
2.4 KiB
Plaintext
== How to fix it in pyca
|
|
|
|
=== Code examples
|
|
|
|
==== Noncompliant code example
|
|
|
|
Code targeting scrypt:
|
|
|
|
[source,python,diff-id=207,diff-type=noncompliant]
|
|
----
|
|
from cryptography.hazmat.primitives import hashes
|
|
from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
|
|
|
|
def hash_password(password, salt):
|
|
scrypt = Scrypt(
|
|
salt=salt,
|
|
length=32,
|
|
n=1 << 10,
|
|
r=8,
|
|
p=1) # Noncompliant
|
|
|
|
return scrypt.derive(password)
|
|
----
|
|
|
|
Code targeting PBKDF2:
|
|
|
|
[source,python,diff-id=277,diff-type=noncompliant]
|
|
----
|
|
from cryptography.hazmat.primitives import hashes
|
|
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
|
|
|
def hash_password(password, salt):
|
|
pbkdf = PBKDF2HMAC(
|
|
algorithm=hashes.SHA256(),
|
|
length=32,
|
|
salt=salt,
|
|
iterations=480000) # Noncompliant
|
|
|
|
return pbkdf.derive(password)
|
|
----
|
|
|
|
|
|
==== Compliant solution
|
|
|
|
Code targeting scrypt:
|
|
|
|
[source,python,diff-id=207,diff-type=compliant]
|
|
----
|
|
from cryptography.hazmat.primitives import hashes
|
|
from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
|
|
|
|
def hash_password(password, salt):
|
|
scrypt = Scrypt(
|
|
salt=salt,
|
|
length=64,
|
|
n=1 << 17,
|
|
r=8,
|
|
p=1)
|
|
|
|
return scrypt.derive(password)
|
|
----
|
|
|
|
Code targeting PBKDF2:
|
|
|
|
[source,python,diff-id=277,diff-type=compliant]
|
|
----
|
|
from cryptography.hazmat.primitives import hashes
|
|
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
|
|
|
def hash_password(password, salt):
|
|
pbkdf = PBKDF2HMAC(
|
|
algorithm=hashes.SHA256(),
|
|
length=32,
|
|
salt=salt,
|
|
iterations=600_000) # Noncompliant
|
|
|
|
return pbkdf.derive(password)
|
|
----
|
|
|
|
|
|
=== How does this work?
|
|
|
|
include::../../common/fix/password-hashing.adoc[]
|
|
|
|
The following sections provide guidance on the usage of these secure
|
|
password-hashing algorithms as provided by pyca/cryptography.
|
|
|
|
include::../../common/fix/scrypt-parameters.adoc[]
|
|
|
|
To use values recommended by OWASP, you can use an object crafted as follows:
|
|
|
|
[source,python]
|
|
----
|
|
OWASP_1 = {
|
|
"n": 1 << 17,
|
|
"r": 8,
|
|
"p": 1,
|
|
"length": 64,
|
|
}
|
|
|
|
# To use this example, you can use the dictionary as a ``**kwargs`` variable:
|
|
scrypt(password, salt, **OWASP_1)
|
|
----
|
|
|
|
include::../../common/fix/pbkdf2-parameters.adoc[]
|
|
|
|
=== Pitfalls
|
|
|
|
include::../../common/pitfalls/pre-hashing.adoc[]
|
|
|
|
=== Going the extra mile
|
|
|
|
include::../../common/extra-mile/peppering.adoc[]
|
|
|