在 python 中验证 StoreKit 2 事务 jwsRepresentation 的正确方法是什么?

Tay*_*hes 3 python storekit jwt swift

从文档中尚不清楚您实际上如何验证服务器端 StoreKit 2 事务中的jwsRepresentation字符串。

Apple App Store 通知 V2中的“signedPayload”似乎也是相同的,但除了在设备上的客户端验证之外,也没有关于实际验证的文档。

是什么赋予了?我们用这个 JWS/JWT 做什么?

Tay*_*hes 5

(免责声明:我是加密货币新手,所以如果我在整个过程中使用了错误的术语等,请检查我)

\n

中的 JWSjwsRepresentation以及通知 V2 JSON 正文中的 是 JWT \xe2\x80\x94,您可以在jwt.iosignedPayload上获取一个并查看它。这项工作是验证 JWT 签名,并在您充分确信它确实来自 Apple 后提取有效负载。然后,有效负载本身包含可用于升级用户帐户等的信息。服务器端一旦数据可信。

\n

要验证 JWT,您需要找到 JWT 标头集合中指定的用于签署 JWT 的签名"x5c",验证证书链,然后验证该签名是否确实来自 Apple。

\n

第一步:从 Apple 加载众所周知的根证书和中级证书。

\n
import requests\nfrom OpenSSL import crypto\n\nROOT_CER_URL = "https://www.apple.com/certificateauthority/AppleRootCA-G3.cer"\nG6_CER_URL = "https://www.apple.com/certificateauthority/AppleWWDRCAG6.cer"\n\nroot_cert_bytes: bytes = requests.get(ROOT_CER_URL).content\nroot_cert = crypto.load_certificate(crypto.FILETYPE_ASN1, root_cert_bytes)\n\ng6_cert_bytes: bytes = requests.get(G6_CER_URL).content\ng6_cert = crypto.load_certificate(crypto.FILETYPE_ASN1, g6_cert_bytes)\n
Run Code Online (Sandbox Code Playgroud)\n

第二步:从 JWT 标头中获取证书链

\n
import jwt  # PyJWT library\n\n# Get the signing keys out of the JWT header. The header will look like:\n# {"alg": "ES256", "x5c": ["...base64 cert...", "...base64 cert..."]}\nheader = jwt.get_unverified_header(apple_jwt_string)\n\nprovided_certificates: List[crypto.X509] = []\nfor cert_base64 in header[\'x5c\']:\n    cert_bytes = base64url_decode(cert_base64)\n    cert = crypto.load_certificate(crypto.FILETYPE_ASN1, cert_bytes)\n    provided_certificates.append(cert)\n
Run Code Online (Sandbox Code Playgroud)\n

第三步:验证该链是否如您所想——这可确保证书链由真正的 Apple 根证书和中间证书签名。

\n
# First make sure these are the root & intermediate certs from Apple:\nassert provided_certificates[-2].digest(\'sha256\') == g6_cert.digest(\'sha256\')\nassert provided_certificates[-1].digest(\'sha256\') == root_cert.digest(\'sha256\')\n\n# Now validate that the cert chain is cryptographically legit:\nstore = crypto.X509Store()\nstore.add_cert(root_cert)\nstore.add_cert(g6_cert)\nfor cert in provided_certificates[:-2]:\n    try:\n        crypto.X509StoreContext(store, cert).verify_certificate()\n    except crypto.X509StoreContextError:\n        logging.error("Invalid certificate chain in JWT: %s", apple_jwt)\n        return None\n    store.add_cert(cert)\n
Run Code Online (Sandbox Code Playgroud)\n

最后:使用标头中现在受信任的证书加载并验证 JWT。

\n
# Now that the cert is validated, we can use it to verify the actual signature\n# of the JWT. PyJWT does not understand this certificate if we pass it in, so\n# we have to get the cryptography library\'s version of the same key:\ncryptography_version_of_key = provided_certificates[0].get_pubkey().to_cryptography_key()\ntry:\n    return jwt.decode(apple_jwt, cryptography_version_of_key, algorithms=["ES256"])\nexcept Exception:\n    logging.exception("Problem validating Apple JWT")\n    return None\n
Run Code Online (Sandbox Code Playgroud)\n

瞧,您现在可以使用 App Store 中经过验证的 JWT 正文。

\n

整个解决方案的要点:https://gist.github.com/taylorhughes/3968575b40dd97f851f35892931ebf3e

\n