40 lines
1.4 KiB
Python
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."
|
|
)
|