Ya publiqué una pregunta similar aquí , pero me di cuenta de que mi problema podría tener más que ver con el certificado x509 que con JWS en general.
Aquí está la cosa, soy bastante nuevo en JWS, y Apple ahora los transmite como parte de su comunicación de servidor a servidor. Estoy tratando de entender cómo garantizar completamente la validez del JWS, porque por lo que entiendo, la verificación de la firma solo implica que no se manipuló todo el JWS. No sé cómo verificar realmente que esta carga útil proviene de una fuente confiable (también conocida como Apple) .
Esto es lo que tengo hasta ahora (PHP):
//1. explode jws and decode what's needed $components = explode('.', $jws); $headerJson = json_decode(base64_decode($components[0]),true); $signature = base64Url_decode($components[2]); //2. extract all certificates from 'x5c' header foreach ($headerJson['x5c'] as $x5c){ $c = '-----BEGIN CERTIFICATE-----'.PHP_EOL; $c .= chunk_split($x5c,64,PHP_EOL); $c .= '-----END CERTIFICATE-----'.PHP_EOL; $certificates[] = openssl_x509_read($c); } //3. verify validity of certificate chain (each one is signed by the next, except root cert) for($i = 0; $i < count($certificates); $i++){ if ($i == count($certificates) - 1){ if (openssl_x509_verify($certificates[$i], $certificates[$i]) != 1){ throw new Exception("Invalid Root Certificate"); } } else{ if (openssl_x509_verify($certificates[$i], $certificates[$i+1]) != 1){ throw new Exception("Invalid Certificate"); } } } //4. get public_key from first certificate $public_key = openssl_pkey_get_public($certificates[0]); //5. verify entire token, including signature (using the Firebase library) $parsed_token = (array) \Firebase\JWT\JWT::decode($jws, $public_key, ['ES256']); //helper function: a simple base64 url decoder function base64Url_decode($data){ return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT)); }¡Gracias!
Gracias a @IMSoP por indicarme la dirección correcta. Cuando un JWS contiene una cadena de certificados (cabecera x5c ), se supone que debemos tener una copia de estos certificados válidos (o al menos la raíz, ya que valida el resto de la cadena). En mi caso, pude encontrarlos en la web de Apple .
Una vez que los descargue, es tan fácil como:
openssl_x509_verify($jws_root_cert, $downloaded_apple_root_cert);