Erste Produktivversion
This commit is contained in:
71
tools/vapid-keys.py
Normal file
71
tools/vapid-keys.py
Normal file
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Erzeugt das VAPID-Schlüsselpaar für Web Push.
|
||||
|
||||
python3 tools/vapid-keys.py
|
||||
|
||||
VAPID ("Voluntary Application Server Identification") ist die Art, wie
|
||||
sich dieser Server gegenüber den Push-Diensten der Browserhersteller
|
||||
ausweist. Das Schlüsselpaar gehört dir - es ist kein Konto bei Google
|
||||
oder Apple nötig und es fließen keine Daten an Dritte, außer der
|
||||
verschlüsselten Nachricht selbst.
|
||||
|
||||
Der öffentliche Schlüssel geht an den Browser, der private bleibt auf dem
|
||||
Server. Wird der private Schlüssel getauscht, verlieren alle bestehenden
|
||||
Anmeldungen ihre Gültigkeit und müssen erneuert werden - deshalb einmal
|
||||
erzeugen und dann in Ruhe lassen.
|
||||
|
||||
Läuft ohne Zusatzpakete: `cryptography` ist bereits eine Abhängigkeit
|
||||
des Backends.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import sys
|
||||
|
||||
try:
|
||||
from cryptography.hazmat.primitives.asymmetric import ec
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
except ImportError:
|
||||
print(
|
||||
"Das Paket 'cryptography' fehlt. Entweder im Container ausführen:\n"
|
||||
" docker compose exec api python3 tools/vapid-keys.py\n"
|
||||
"oder lokal installieren: pip install cryptography",
|
||||
file=sys.stderr,
|
||||
)
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
def b64(data: bytes) -> str:
|
||||
"""base64url ohne Auffüllzeichen - so verlangen es Web Push und JWT."""
|
||||
return base64.urlsafe_b64encode(data).rstrip(b"=").decode("ascii")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
key = ec.generate_private_key(ec.SECP256R1())
|
||||
|
||||
# Privater Schlüssel: die 32 Byte des Skalars, nicht das PEM-Format.
|
||||
# py_vapid nimmt diese Form direkt an.
|
||||
private_value = key.private_numbers().private_value
|
||||
private_bytes = private_value.to_bytes(32, "big")
|
||||
|
||||
# Öffentlicher Schlüssel: unkomprimierter Punkt, 65 Byte (0x04 + X + Y).
|
||||
# Genau diese Form erwartet der Browser als applicationServerKey.
|
||||
public_bytes = key.public_key().public_bytes(
|
||||
encoding=serialization.Encoding.X962,
|
||||
format=serialization.PublicFormat.UncompressedPoint,
|
||||
)
|
||||
|
||||
print("# In die .env übernehmen. Vorhandene Zeilen ERSETZEN, nicht")
|
||||
print("# ergänzen: Bei doppelten Einträgen nimmt Docker Compose den")
|
||||
print("# letzten - und das ist oft die leere Vorlagenzeile.\n")
|
||||
print(f"VAPID_PRIVATE_KEY={b64(private_bytes)}")
|
||||
print(f"VAPID_PUBLIC_KEY={b64(public_bytes)}")
|
||||
print("# Kontaktadresse für die Push-Dienste - bei Problemen melden sie sich dort.")
|
||||
print("VAPID_SUBJECT=mailto:admin@example.de")
|
||||
print()
|
||||
print("# Der private Schlüssel gehört NICHT ins Versionsverwaltungssystem.")
|
||||
print("# Ein Wechsel entwertet alle bestehenden Anmeldungen.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user