Skip to content

Instantly share code, notes, and snippets.

@LiEnby
Last active August 29, 2022 12:34
Show Gist options
  • Save LiEnby/d31334bd3d169b41918ffacda3b0ac1d to your computer and use it in GitHub Desktop.
Save LiEnby/d31334bd3d169b41918ffacda3b0ac1d to your computer and use it in GitHub Desktop.
Validate minecraft entitlements
#!/usr/bin/python3
# --=== Created by Li ===--
# Minecraft Entitlement Verifier
# Requires decrypted .ent (pre-1.19) or from PlayFab Api
# (i was too lazy to implement ent decryption)
#
# This script mathematically verifies if a given entitlement file was generated by Mojang or not.
#
# Usage:
# type plaintext.ent | py ent_validate.py (Windows)
# cat plaintext.ent | python3 ent_validate.py (Linux)
#
# required pip packages:
#
# pip3 install cryptography
# pip3 install requests
# pip3 install hashlib
# Public Domain
import cryptography
import hashlib
import requests
import os
import binascii
import json
import base64
import sys
from cryptography import x509
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
ISSUE_CERT = "ReceiptIssuerCertificate.pem"
def checkItem(itm):
receipt = itm['Receipt']
valid = verifyReceipt(receipt)
return valid
def verifyEnt(entitlements):
ent = json.loads(entitlements)
for itm in ent["Items"]:
if not checkItem(itm):
return False
for itm in ent["Subscriptions"]:
if not checkItem(itm):
return False
if not verifyReceipt(ent["Receipt"]):
return False
return True
def getReceiptIssuerCertificate():
if not os.path.exists(ISSUE_CERT):
pem = requests.get("https://20ca2.playfabapi.com/inventory/GetReceiptIssuerCertificateAsPem").json()["data"]["PemCert"].encode("UTF-8")
open(ISSUE_CERT, "wb").write(pem)
return pem
else:
pem = open(ISSUE_CERT, "rb").read()
return pem
def hashJWT(jwt):
parts = jwt.split(".")
sha256 = hashlib.sha256()
sha256.update(parts[0].encode("UTF-8")+b"."+parts[1].encode("UTF-8"))
return sha256.hexdigest()
def b64url(data):
data += "=" * (len(data) % 4)
return base64.urlsafe_b64decode(data)
def verifyReceipt(receipt):
expectedHash = hashJWT(receipt)
cert = x509.load_pem_x509_certificate(getReceiptIssuerCertificate())
pubkey = cert.public_key()
signature = b64url(receipt.split(".")[2])
gotHash = binascii.hexlify(pubkey.recover_data_from_signature(signature, padding.PKCS1v15(), hashes.SHA256)).decode("UTF-8")
if expectedHash == gotHash:
return True
else:
return False
if __name__ == "__main__":
v = verifyEnt(input())
if v:
print("Ent Verify Success")
else:
print("Ent Verify Fail")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment