100 lines
2.5 KiB
Plaintext

== How to fix it in Flask
=== Code examples
==== Noncompliant code example
[source,python,diff-id=204,diff-type=noncompliant]
----
from flask import Flask, request
from flask_bcrypt import Bcrypt
app = Flask(__name__)
bcrypt = Bcrypt(app)
@app.get("/")
def hash():
password = request.args.get('password', '')
hashed_password = bcrypt.generate_password_hash(password, rounds=2) # Noncompliant
return f"<p>{hashed_password.decode('utf-8')}</p>"
----
==== Compliant solution
[source,python,diff-id=204,diff-type=compliant]
----
from flask import Flask, request
from flask_bcrypt import Bcrypt
app = Flask(__name__)
bcrypt = Bcrypt(app)
@app.get("/")
def hash():
password = request.args.get('password', '')
hashed_password = bcrypt.generate_password_hash(password)
return f"<p>{hashed_password.Decode('utf-8')}</p>"
----
=== How does this work?
include::../../common/fix/password-hashing.adoc[]
include::../../common/fix/bcrypt-parameters.adoc[]
include::../../common/fix/argon-parameters.adoc[]
To use values recommended by the Argon2 authors, you can use the two following objects:
* https://argon2-cffi.readthedocs.io/en/stable/api.html#argon2.profiles.RFC_9106_HIGH_MEMORY[argon2.profiles.RFC_9106_HIGH_MEMORY]
* https://argon2-cffi.readthedocs.io/en/stable/api.html#argon2.profiles.RFC_9106_LOW_MEMORY[argon2.profiles.RFC_9106_LOW_MEMORY]
To use values recommended by the OWASP, you can craft objects as follows:
[source, python]
----
import argon2
from argon2.low_level import ARGON2_VERSION, Type
OWASP_1 = argon2.Parameters(
type=Type.ID,
version=ARGON2_VERSION,
salt_len=16,
hash_len=32,
time_cost=1,
memory_cost=47104, # 46 MiB
parallelism=1)
# To apply the parameters to the Flask app:
def set_flask_argon2_parameters(app, parameters: argon2.Parameters):
app.config['ARGON2_SALT_LENGTH'] = parameters.salt_len
app.config['ARGON2_HASH_LENGTH'] = parameters.hash_len
app.config['ARGON2_TIME_COST'] = parameters.time_cost
app.config['ARGON2_MEMORY_COST'] = parameters.memory_cost
app.config['ARGON2_PARALLELISM'] = parameters.parallelism
# ----
# Or the unofficial way:
from flask import Flask
from flask_argon2 import Argon2
app = Flask(__name__)
argon2 = Argon2(app)
argon2.ph = OWASP_1
set_flask_argon2_parameters(app, OWASP_1)
----
=== Pitfalls
include::../../common/pitfalls/pre-hashing.adoc[]
=== Going the extra mile
include::../../common/extra-mile/argon-cli.adoc[]
include::../../common/extra-mile/peppering.adoc[]