== 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[]

