Skip to content

Instantly share code, notes, and snippets.

@1upbyte
Created May 28, 2026 04:50
Show Gist options
  • Select an option

  • Save 1upbyte/ba31e1416c5082230606a50b4656e45a to your computer and use it in GitHub Desktop.

Select an option

Save 1upbyte/ba31e1416c5082230606a50b4656e45a to your computer and use it in GitHub Desktop.
Convert Werkzeug scrypt hashes to a hashcat format
import base64
import argparse
import sys
print(f"NOTE: You need to use --self-test-disable in Hashcat", file=sys.stderr)
def convert_to_hashcat(werkzeug_hash: str) -> str:
# Split Werkzeug data
parts = werkzeug_hash.strip().split("$")
if len(parts) < 3:
raise ValueError("invalid werkzeug hash format")
params = parts[0].split(":")
if len(params) < 4:
raise ValueError("invalid werkzeug params")
N = params[1]
r = params[2]
p = params[3]
salt = parts[1]
hashed_val = parts[2]
# Standard Werkzeug strings usually have raw string salts and hex hashes.
salt_bytes = salt.encode('utf-8')
hash_bytes = bytes.fromhex(hashed_val)
# Encode to Base64 (Keep the padding '=' for this specific format)
salt_b64 = base64.b64encode(salt_bytes).decode('utf-8')
hash_b64 = base64.b64encode(hash_bytes).decode('utf-8')
# Construct the requested Hashcat format
return f"SCRYPT:{N}:{r}:{p}:{salt_b64}:{hash_b64}"
def process_file(path: str):
try:
with open(path, 'r') as f:
for line in f:
line = line.strip()
if not line:
continue
try:
out = convert_to_hashcat(line)
print(out)
except Exception as e:
print(f"Error processing line: {line} -> {e}", file=sys.stderr)
except FileNotFoundError:
print(f"File not found: {path}", file=sys.stderr)
sys.exit(1)
def main():
parser = argparse.ArgumentParser(description='Convert Werkzeug scrypt hashes to Hashcat format')
parser.add_argument('file', help='file containing one Werkzeug hash per line')
args = parser.parse_args()
process_file(args.file)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment