import sys import base64 from typing import Tuple, Dict, List import json import urllib.error from urllib.request import urlopen import ssl import logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') # pip install cryptodome from Crypto.PublicKey import RSA # Funzione che decodifica una stringa codificata in base64url def base64urlDecode(encStr): # Effettua il padding della stringa affinche' possa essere divisa in bytes e decodifcata padding_factor = (4 - len(encStr) % 4) % 4 encStr += "=" * padding_factor return base64.urlsafe_b64decode(encStr) # Funzione per estrarre il modulo e l'esponente. La codifica e' Base64Url. # I byte ottenuto vanno convertiti con notazione intero big endian senza segno def keyComponentsExtractor(vDict: Dict, keyType='*') -> List: retList = [] if 'keys' in vDict.keys(): logging.debug("Chiave keys trovata!") for k in vDict['keys']: logging.debug("Chiave: " + str(k)) if keyType == '*' or 'use' in k and k['use'] == keyType: nInt = int.from_bytes(base64urlDecode(k['n']), byteorder='big', signed=False) eInt = int.from_bytes(base64urlDecode(k['e']), byteorder='big', signed=False) logging.debug("Modulo: " + str(nInt) + " Esponente: " + str(eInt)) retList.append((nInt, eInt)) return retList # Creo il contesto ignorando eventuali certificati self-signed sslContex = ssl.create_default_context() sslContex.check_hostname = False sslContex.verify_mode = ssl.CERT_NONE # Chiamo il servizio ed estraggo il json try: response = urlopen("https://www.googleapis.com/oauth2/v3/certs", context=sslContex) jsonResponse = json.load(response) logging.debug("Risposta JSON: " + str(jsonResponse)) except urllib.error.URLError as e: logging.error("" + str(e.reason)) sys.exit() # Estraggo le componenti modulo e esponente dalle chiavi contenuti nella risposta JSON # Se non viene specificato il tipo di chiave vengono restituite tutte le chiavi # sig = signature key, enc = encryption key -> ref Oauth spec componentsList = keyComponentsExtractor(jsonResponse, "sig") if not componentsList: logging.error("Lista delle componenti vuota!") sys.exit() logging.debug("Lista componenti chiavi estratti: " + str(componentsList)) # Creo i certificati pubblici e scrivo la chiave pubblica in un file keyfile = open("publicKey.txt", "w") for (n,e) in componentsList: pKey = RSA.construct((n, e)) print(pKey.export_key().decode(), file=keyfile)