#! /usr/bin/env python3 import argparse import sys import logging import ipaddress import hashlib import base64 logger = logging.getLogger(__name__) def main() -> int: # Handle program arguments ap = argparse.ArgumentParser( prog="wg-peer-to-ipv6", description="Deterministically generate IPv6 addresses from WireGuard public keys", ) ap.add_argument("prefix", help="IPv6 prefix", type=ipaddress.IPv6Network) ap.add_argument("public_key", help="WireGuard public key") ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" ) args = ap.parse_args() # Configure logging logging.basicConfig( level=logging.DEBUG if args.verbose else logging.INFO, format="%(levelname)s: %(message)s", ) # Decode the public key public_key = base64.b64decode(args.public_key) # Hash the public key hash = hashlib.sha256(public_key).digest() # Figure out how many bits we have for the host part host_bits = args.prefix.max_prefixlen - args.prefix.prefixlen # Take that many bits from the hash host = int.from_bytes(hash, "big") >> (256 - host_bits) # Create the IPv6 address ipv6 = args.prefix.network_address + host print(ipv6) return 0 if __name__ == "__main__": sys.exit(main())