We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Increase default work factor for PBKDF2 to 600,000 iterations
https://github.com/pallets/werkzeug/blob/bba2109e276ab876b8d64e2b967412cb6da1d865/src/werkzeug/security.py#L12

The value has not been updated for a few years. I propose increasing it to the same number as the next release of Django will use.

See https://github.com/django/django/pull/16521 and https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/werkzeug/security.py`
Content:
```
1 import hashlib
2 import hmac
3 import os
4 import posixpath
5 import secrets
6 import typing as t
7 
8 if t.TYPE_CHECKING:
9     pass
10 
11 SALT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
12 DEFAULT_PBKDF2_ITERATIONS = 260000
13 
14 _os_alt_seps: t.List[str] = list(
15     sep for sep in [os.sep, os.path.altsep] if sep is not None and sep != "/"
16 )
17 
18 
19 def gen_salt(length: int) -> str:
20     """Generate a random string of SALT_CHARS with specified ``length``."""
21     if length <= 0:
22         raise ValueError("Salt length must be positive")
23 
24     return "".join(secrets.choice(SALT_CHARS) for _ in range(length))
25 
26 
27 def _hash_internal(method: str, salt: str, password: str) -> t.Tuple[str, str]:
28     """Internal password hash helper.  Supports plaintext without salt,
29     unsalted and salted passwords.  In case salted passwords are used
30     hmac is used.
31     """
32     if method == "plain":
33         return password, method
34 
35     salt = salt.encode("utf-8")
36     password = password.encode("utf-8")
37 
38     if method.startswith("pbkdf2:"):
39         if not salt:
40             raise ValueError("Salt is required for PBKDF2")
41 
42         args = method[7:].split(":")
43 
44         if len(args) not in (1, 2):
45             raise ValueError("Invalid number of arguments for PBKDF2")
46 
47         method = args.pop(0)
48         iterations = int(args[0] or 0) if args else DEFAULT_PBKDF2_ITERATIONS
49         return (
50             hashlib.pbkdf2_hmac(method, password, salt, iterations).hex(),
51             f"pbkdf2:{method}:{iterations}",
52         )
53 
54     if salt:
55         return hmac.new(salt, password, method).hexdigest(), method
56 
57     return hashlib.new(method, password).hexdigest(), method
58 
59 
60 def generate_password_hash(
61     password: str, method: str = "pbkdf2:sha256", salt_length: int = 16
62 ) -> str:
63     """Hash a password with the given method and salt with a string of
64     the given length. The format of the string returned includes the method
65     that was used so that :func:`check_password_hash` can check the hash.
66 
67     The format for the hashed string looks like this::
68 
69         method$salt$hash
70 
71     This method can **not** generate unsalted passwords but it is possible
72     to set param method='plain' in order to enforce plaintext passwords.
73     If a salt is used, hmac is used internally to salt the password.
74 
75     If PBKDF2 is wanted it can be enabled by setting the method to
76     ``pbkdf2:method:iterations`` where iterations is optional::
77 
78         pbkdf2:sha256:80000$salt$hash
79         pbkdf2:sha256$salt$hash
80 
81     :param password: the password to hash.
82     :param method: the hash method to use (one that hashlib supports). Can
83                    optionally be in the format ``pbkdf2:method:iterations``
84                    to enable PBKDF2.
85     :param salt_length: the length of the salt in letters.
86     """
87     salt = gen_salt(salt_length) if method != "plain" else ""
88     h, actual_method = _hash_internal(method, salt, password)
89     return f"{actual_method}${salt}${h}"
90 
91 
92 def check_password_hash(pwhash: str, password: str) -> bool:
93     """Check a password against a given salted and hashed password value.
94     In order to support unsalted legacy passwords this method supports
95     plain text passwords, md5 and sha1 hashes (both salted and unsalted).
96 
97     Returns `True` if the password matched, `False` otherwise.
98 
99     :param pwhash: a hashed string like returned by
100                    :func:`generate_password_hash`.
101     :param password: the plaintext password to compare against the hash.
102     """
103     if pwhash.count("$") < 2:
104         return False
105 
106     method, salt, hashval = pwhash.split("$", 2)
107     return hmac.compare_digest(_hash_internal(method, salt, password)[0], hashval)
108 
109 
110 def safe_join(directory: str, *pathnames: str) -> t.Optional[str]:
111     """Safely join zero or more untrusted path components to a base
112     directory to avoid escaping the base directory.
113 
114     :param directory: The trusted base directory.
115     :param pathnames: The untrusted path components relative to the
116         base directory.
117     :return: A safe path, otherwise ``None``.
118     """
119     if not directory:
120         # Ensure we end up with ./path if directory="" is given,
121         # otherwise the first untrusted part could become trusted.
122         directory = "."
123 
124     parts = [directory]
125 
126     for filename in pathnames:
127         if filename != "":
128             filename = posixpath.normpath(filename)
129 
130         if (
131             any(sep in filename for sep in _os_alt_seps)
132             or os.path.isabs(filename)
133             or filename == ".."
134             or filename.startswith("../")
135         ):
136             return None
137 
138         parts.append(filename)
139 
140     return posixpath.join(*parts)
141
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/werkzeug/security.py b/src/werkzeug/security.py
--- a/src/werkzeug/security.py
+++ b/src/werkzeug/security.py
@@ -9,7 +9,7 @@
     pass
 
 SALT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-DEFAULT_PBKDF2_ITERATIONS = 260000
+DEFAULT_PBKDF2_ITERATIONS = 600000
 
 _os_alt_seps: t.List[str] = list(
     sep for sep in [os.sep, os.path.altsep] if sep is not None and sep != "/"

{"golden_diff": "diff --git a/src/werkzeug/security.py b/src/werkzeug/security.py\n--- a/src/werkzeug/security.py\n+++ b/src/werkzeug/security.py\n@@ -9,7 +9,7 @@\n     pass\n \n SALT_CHARS = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\"\n-DEFAULT_PBKDF2_ITERATIONS = 260000\n+DEFAULT_PBKDF2_ITERATIONS = 600000\n \n _os_alt_seps: t.List[str] = list(\n     sep for sep in [os.sep, os.path.altsep] if sep is not None and sep != \"/\"\n", "issue": "Increase default work factor for PBKDF2 to 600,000 iterations\nhttps://github.com/pallets/werkzeug/blob/bba2109e276ab876b8d64e2b967412cb6da1d865/src/werkzeug/security.py#L12\r\n\r\nThe value has not been updated for a few years. I propose increasing it to the same number as the next release of Django will use.\r\n\r\nSee https://github.com/django/django/pull/16521 and https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2.\n", "before_files": [{"content": "import hashlib\nimport hmac\nimport os\nimport posixpath\nimport secrets\nimport typing as t\n\nif t.TYPE_CHECKING:\n    pass\n\nSALT_CHARS = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\"\nDEFAULT_PBKDF2_ITERATIONS = 260000\n\n_os_alt_seps: t.List[str] = list(\n    sep for sep in [os.sep, os.path.altsep] if sep is not None and sep != \"/\"\n)\n\n\ndef gen_salt(length: int) -> str:\n    \"\"\"Generate a random string of SALT_CHARS with specified ``length``.\"\"\"\n    if length <= 0:\n        raise ValueError(\"Salt length must be positive\")\n\n    return \"\".join(secrets.choice(SALT_CHARS) for _ in range(length))\n\n\ndef _hash_internal(method: str, salt: str, password: str) -> t.Tuple[str, str]:\n    \"\"\"Internal password hash helper.  Supports plaintext without salt,\n    unsalted and salted passwords.  In case salted passwords are used\n    hmac is used.\n    \"\"\"\n    if method == \"plain\":\n        return password, method\n\n    salt = salt.encode(\"utf-8\")\n    password = password.encode(\"utf-8\")\n\n    if method.startswith(\"pbkdf2:\"):\n        if not salt:\n            raise ValueError(\"Salt is required for PBKDF2\")\n\n        args = method[7:].split(\":\")\n\n        if len(args) not in (1, 2):\n            raise ValueError(\"Invalid number of arguments for PBKDF2\")\n\n        method = args.pop(0)\n        iterations = int(args[0] or 0) if args else DEFAULT_PBKDF2_ITERATIONS\n        return (\n            hashlib.pbkdf2_hmac(method, password, salt, iterations).hex(),\n            f\"pbkdf2:{method}:{iterations}\",\n        )\n\n    if salt:\n        return hmac.new(salt, password, method).hexdigest(), method\n\n    return hashlib.new(method, password).hexdigest(), method\n\n\ndef generate_password_hash(\n    password: str, method: str = \"pbkdf2:sha256\", salt_length: int = 16\n) -> str:\n    \"\"\"Hash a password with the given method and salt with a string of\n    the given length. The format of the string returned includes the method\n    that was used so that :func:`check_password_hash` can check the hash.\n\n    The format for the hashed string looks like this::\n\n        method$salt$hash\n\n    This method can **not** generate unsalted passwords but it is possible\n    to set param method='plain' in order to enforce plaintext passwords.\n    If a salt is used, hmac is used internally to salt the password.\n\n    If PBKDF2 is wanted it can be enabled by setting the method to\n    ``pbkdf2:method:iterations`` where iterations is optional::\n\n        pbkdf2:sha256:80000$salt$hash\n        pbkdf2:sha256$salt$hash\n\n    :param password: the password to hash.\n    :param method: the hash method to use (one that hashlib supports). Can\n                   optionally be in the format ``pbkdf2:method:iterations``\n                   to enable PBKDF2.\n    :param salt_length: the length of the salt in letters.\n    \"\"\"\n    salt = gen_salt(salt_length) if method != \"plain\" else \"\"\n    h, actual_method = _hash_internal(method, salt, password)\n    return f\"{actual_method}${salt}${h}\"\n\n\ndef check_password_hash(pwhash: str, password: str) -> bool:\n    \"\"\"Check a password against a given salted and hashed password value.\n    In order to support unsalted legacy passwords this method supports\n    plain text passwords, md5 and sha1 hashes (both salted and unsalted).\n\n    Returns `True` if the password matched, `False` otherwise.\n\n    :param pwhash: a hashed string like returned by\n                   :func:`generate_password_hash`.\n    :param password: the plaintext password to compare against the hash.\n    \"\"\"\n    if pwhash.count(\"$\") < 2:\n        return False\n\n    method, salt, hashval = pwhash.split(\"$\", 2)\n    return hmac.compare_digest(_hash_internal(method, salt, password)[0], hashval)\n\n\ndef safe_join(directory: str, *pathnames: str) -> t.Optional[str]:\n    \"\"\"Safely join zero or more untrusted path components to a base\n    directory to avoid escaping the base directory.\n\n    :param directory: The trusted base directory.\n    :param pathnames: The untrusted path components relative to the\n        base directory.\n    :return: A safe path, otherwise ``None``.\n    \"\"\"\n    if not directory:\n        # Ensure we end up with ./path if directory=\"\" is given,\n        # otherwise the first untrusted part could become trusted.\n        directory = \".\"\n\n    parts = [directory]\n\n    for filename in pathnames:\n        if filename != \"\":\n            filename = posixpath.normpath(filename)\n\n        if (\n            any(sep in filename for sep in _os_alt_seps)\n            or os.path.isabs(filename)\n            or filename == \"..\"\n            or filename.startswith(\"../\")\n        ):\n            return None\n\n        parts.append(filename)\n\n    return posixpath.join(*parts)\n", "path": "src/werkzeug/security.py"}], "after_files": [{"content": "import hashlib\nimport hmac\nimport os\nimport posixpath\nimport secrets\nimport typing as t\n\nif t.TYPE_CHECKING:\n    pass\n\nSALT_CHARS = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\"\nDEFAULT_PBKDF2_ITERATIONS = 600000\n\n_os_alt_seps: t.List[str] = list(\n    sep for sep in [os.sep, os.path.altsep] if sep is not None and sep != \"/\"\n)\n\n\ndef gen_salt(length: int) -> str:\n    \"\"\"Generate a random string of SALT_CHARS with specified ``length``.\"\"\"\n    if length <= 0:\n        raise ValueError(\"Salt length must be positive\")\n\n    return \"\".join(secrets.choice(SALT_CHARS) for _ in range(length))\n\n\ndef _hash_internal(method: str, salt: str, password: str) -> t.Tuple[str, str]:\n    \"\"\"Internal password hash helper.  Supports plaintext without salt,\n    unsalted and salted passwords.  In case salted passwords are used\n    hmac is used.\n    \"\"\"\n    if method == \"plain\":\n        return password, method\n\n    salt = salt.encode(\"utf-8\")\n    password = password.encode(\"utf-8\")\n\n    if method.startswith(\"pbkdf2:\"):\n        if not salt:\n            raise ValueError(\"Salt is required for PBKDF2\")\n\n        args = method[7:].split(\":\")\n\n        if len(args) not in (1, 2):\n            raise ValueError(\"Invalid number of arguments for PBKDF2\")\n\n        method = args.pop(0)\n        iterations = int(args[0] or 0) if args else DEFAULT_PBKDF2_ITERATIONS\n        return (\n            hashlib.pbkdf2_hmac(method, password, salt, iterations).hex(),\n            f\"pbkdf2:{method}:{iterations}\",\n        )\n\n    if salt:\n        return hmac.new(salt, password, method).hexdigest(), method\n\n    return hashlib.new(method, password).hexdigest(), method\n\n\ndef generate_password_hash(\n    password: str, method: str = \"pbkdf2:sha256\", salt_length: int = 16\n) -> str:\n    \"\"\"Hash a password with the given method and salt with a string of\n    the given length. The format of the string returned includes the method\n    that was used so that :func:`check_password_hash` can check the hash.\n\n    The format for the hashed string looks like this::\n\n        method$salt$hash\n\n    This method can **not** generate unsalted passwords but it is possible\n    to set param method='plain' in order to enforce plaintext passwords.\n    If a salt is used, hmac is used internally to salt the password.\n\n    If PBKDF2 is wanted it can be enabled by setting the method to\n    ``pbkdf2:method:iterations`` where iterations is optional::\n\n        pbkdf2:sha256:80000$salt$hash\n        pbkdf2:sha256$salt$hash\n\n    :param password: the password to hash.\n    :param method: the hash method to use (one that hashlib supports). Can\n                   optionally be in the format ``pbkdf2:method:iterations``\n                   to enable PBKDF2.\n    :param salt_length: the length of the salt in letters.\n    \"\"\"\n    salt = gen_salt(salt_length) if method != \"plain\" else \"\"\n    h, actual_method = _hash_internal(method, salt, password)\n    return f\"{actual_method}${salt}${h}\"\n\n\ndef check_password_hash(pwhash: str, password: str) -> bool:\n    \"\"\"Check a password against a given salted and hashed password value.\n    In order to support unsalted legacy passwords this method supports\n    plain text passwords, md5 and sha1 hashes (both salted and unsalted).\n\n    Returns `True` if the password matched, `False` otherwise.\n\n    :param pwhash: a hashed string like returned by\n                   :func:`generate_password_hash`.\n    :param password: the plaintext password to compare against the hash.\n    \"\"\"\n    if pwhash.count(\"$\") < 2:\n        return False\n\n    method, salt, hashval = pwhash.split(\"$\", 2)\n    return hmac.compare_digest(_hash_internal(method, salt, password)[0], hashval)\n\n\ndef safe_join(directory: str, *pathnames: str) -> t.Optional[str]:\n    \"\"\"Safely join zero or more untrusted path components to a base\n    directory to avoid escaping the base directory.\n\n    :param directory: The trusted base directory.\n    :param pathnames: The untrusted path components relative to the\n        base directory.\n    :return: A safe path, otherwise ``None``.\n    \"\"\"\n    if not directory:\n        # Ensure we end up with ./path if directory=\"\" is given,\n        # otherwise the first untrusted part could become trusted.\n        directory = \".\"\n\n    parts = [directory]\n\n    for filename in pathnames:\n        if filename != \"\":\n            filename = posixpath.normpath(filename)\n\n        if (\n            any(sep in filename for sep in _os_alt_seps)\n            or os.path.isabs(filename)\n            or filename == \"..\"\n            or filename.startswith(\"../\")\n        ):\n            return None\n\n        parts.append(filename)\n\n    return posixpath.join(*parts)\n", "path": "src/werkzeug/security.py"}]}