osiris/tracker/management/commands/generate_vapid_keys.py

40 lines
1.4 KiB
Python

import base64
from cryptography.hazmat.primitives import serialization
from django.core.management.base import BaseCommand
from py_vapid import Vapid01
def b64(raw: bytes) -> str:
"""base64url without padding — the encoding both the browser and py_vapid want."""
return base64.urlsafe_b64encode(raw).decode().rstrip("=")
class Command(BaseCommand):
help = "Generate a VAPID key pair for Web Push. Run once, then keep the values."
def handle(self, *args, **options):
vapid = Vapid01()
vapid.generate_keys()
# The private scalar, raw: py_vapid's from_string() takes exactly this.
private = vapid.private_key.private_numbers().private_value.to_bytes(32, "big")
# The public point, uncompressed: what the browser wants as
# applicationServerKey when subscribing.
public = vapid.public_key.public_bytes(
serialization.Encoding.X962,
serialization.PublicFormat.UncompressedPoint,
)
self.stdout.write(
self.style.SUCCESS(
"Add these to the environment (keep the private key secret):\n"
)
)
self.stdout.write(f"VAPID_PUBLIC_KEY={b64(public)}")
self.stdout.write(f"VAPID_PRIVATE_KEY={b64(private)}")
self.stdout.write(
"\nChanging these later invalidates every existing subscription: "
"each device would have to re-enable reminders."
)