e2c55556ac
- Replace symmetric SECRET_KEY with JWT_PRIVATE_KEY / JWT_PUBLIC_KEY (PEM) - Add iat claim to every token - Add expand_newlines validator in config for single-line .env PEM values - Add scripts/generate_jwt_keys.py key-generation helper - Update security-auditor agent JWT checklist with RS256 enforcement rules - Mark RS256 as done in TODO.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
46 lines
1.4 KiB
Python
46 lines
1.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Generate a 4096-bit RSA key pair for JWT RS256 signing.
|
|
|
|
Usage (from repo root):
|
|
python scripts/generate_jwt_keys.py
|
|
|
|
Output: prints the two env var assignments to paste into backend/.env
|
|
"""
|
|
|
|
from cryptography.hazmat.primitives import serialization
|
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
from cryptography.hazmat.backends import default_backend
|
|
|
|
|
|
def main() -> None:
|
|
private_key = rsa.generate_private_key(
|
|
public_exponent=65537,
|
|
key_size=4096,
|
|
backend=default_backend(),
|
|
)
|
|
|
|
private_pem = private_key.private_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PrivateFormat.TraditionalOpenSSL,
|
|
encryption_algorithm=serialization.NoEncryption(),
|
|
).decode()
|
|
|
|
public_pem = private_key.public_key().public_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
).decode()
|
|
|
|
# Collapse newlines to \n so the value fits on one .env line
|
|
private_oneline = private_pem.replace("\n", "\\n")
|
|
public_oneline = public_pem.replace("\n", "\\n")
|
|
|
|
print("# Paste these lines into backend/.env\n")
|
|
print(f'JWT_PRIVATE_KEY="{private_oneline}"')
|
|
print(f'JWT_PUBLIC_KEY="{public_oneline}"')
|
|
print("\n# Keep JWT_PRIVATE_KEY secret — never commit it.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|