mirror of
https://silica.codes/BedrockReverse/PremiumPacksInstaller.git
synced 2025-04-18 10:51:36 +12:00
234 lines
8.6 KiB
C#
234 lines
8.6 KiB
C#
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Dynamic;
|
|
using System.Net;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace PlayFab
|
|
{
|
|
|
|
public class PlayFab
|
|
{
|
|
|
|
public static string PLAYFAB_VERSION = "XPlatCppSdk-3.6.190304";
|
|
public static string CPP_REST_VERSION = "cpprestsdk/2.9.0";
|
|
|
|
public static string TITLE_ID = "20CA2";
|
|
public static string TITLE_SECRET = "S8RS53ZEIGMYTYG856U3U19AORWXQXF41J7FT3X9YCWAC7I35X";
|
|
public static byte[] PUBLIC_KEY = null;
|
|
|
|
|
|
public static string ENTITY_TOKEN = null;
|
|
public static string ENTITY_ID = null;
|
|
public static string ENTITY_TYPE = null;
|
|
|
|
|
|
|
|
public static dynamic GetProductInformation(string uuid)
|
|
{
|
|
dynamic dyn = new ExpandoObject();
|
|
dyn.ItemId = uuid;
|
|
dyn.ETag = "";
|
|
|
|
return POST(dyn, "/Catalog/GetPublishedItem");
|
|
}
|
|
public static dynamic Search(string query, string filter = "", int skip = 0, string orderBy= "creationDate DESC")
|
|
{
|
|
dynamic dyn = new ExpandoObject();
|
|
dyn.count = true;
|
|
dyn.filter = filter;
|
|
dyn.search = query;
|
|
dyn.orderBy = orderBy;
|
|
dyn.top = 300;
|
|
dyn.skip = skip;
|
|
|
|
return POST(dyn, "/Catalog/Search");
|
|
}
|
|
|
|
public static dynamic POST(dynamic data, string url, string clientsecret = null, bool incSDK = false)
|
|
{
|
|
McClient wc = new McClient();
|
|
string body = JsonConvert.SerializeObject(data, (incSDK ? Formatting.Indented : Formatting.None));
|
|
|
|
// Pretend to be minecraft ...
|
|
|
|
wc.Headers.Set("Accept", "application/json");
|
|
wc.Headers.Set("Accept-Language", "en-US");
|
|
wc.Headers.Set("Accept-Encoding", "gzip, deflate, br");
|
|
wc.Headers.Set("User-Agent", CPP_REST_VERSION);
|
|
wc.Headers.Set("x-playfabsdk", PLAYFAB_VERSION);
|
|
wc.Headers.Set("x-reporterrorassuccess", "true");
|
|
wc.Headers.Set("content-type", "application/json; charset=utf-8");
|
|
|
|
if (clientsecret != null)
|
|
{
|
|
|
|
string signature;
|
|
string timestamp = DateTime.UtcNow.ToString("O");
|
|
|
|
using (SHA256 hash = SHA256.Create())
|
|
{
|
|
string msg = body + "." + timestamp + "." + clientsecret;
|
|
byte[] bytesToHash = Encoding.UTF8.GetBytes(msg);
|
|
signature = Convert.ToBase64String(hash.ComputeHash(bytesToHash));
|
|
}
|
|
|
|
wc.Headers.Set("x-playfab-signature", signature);
|
|
wc.Headers.Set("x-playfab-timestamp", timestamp);
|
|
}
|
|
if (ENTITY_TOKEN != null)
|
|
wc.Headers.Set("x-entitytoken", ENTITY_TOKEN);
|
|
string response = wc.UploadString(GetPlayfabApiUrl() + url + (incSDK ? SdkMsg() : ""), body);
|
|
dynamic resp = JsonConvert.DeserializeObject(response);
|
|
wc.Dispose();
|
|
|
|
return resp.data;
|
|
|
|
}
|
|
public static string RefreshEntityTokenBullshit()
|
|
{
|
|
dynamic dyn = new ExpandoObject();
|
|
dyn.Entity = new ExpandoObject();
|
|
dyn.Entity.Id = ENTITY_ID;
|
|
dyn.Entity.Type = ENTITY_TYPE;
|
|
|
|
dynamic resp = POST(dyn, "/Authentication/GetEntityToken", null, true);
|
|
ENTITY_TOKEN = resp.EntityToken.ToString();
|
|
return ENTITY_TOKEN;
|
|
}
|
|
public static string SdkMsg()
|
|
{
|
|
return "?sdk=" + PLAYFAB_VERSION;
|
|
}
|
|
public static string GenerateClientSecret()
|
|
{
|
|
Random r = new Random(Guid.NewGuid().GetHashCode());
|
|
byte[] clientSecret = new byte[0x20];
|
|
r.NextBytes(clientSecret);
|
|
return Convert.ToBase64String(clientSecret);
|
|
}
|
|
public static string GenerateCustomId()
|
|
{
|
|
Random r = new Random(Guid.NewGuid().GetHashCode());
|
|
byte[] customId = new byte[0x10];
|
|
r.NextBytes(customId);
|
|
return "MCPF" + BitConverter.ToString(customId).Replace("-", "").ToUpper();
|
|
}
|
|
|
|
public static string GetPlayfabApiUrl()
|
|
{
|
|
return "https://" + TITLE_ID + ".playfabapi.com";
|
|
}
|
|
|
|
// How 2 find TitleSharedSecret:
|
|
// 1- delete all mc data
|
|
// 2- open fiddler
|
|
// 3- open minecraft
|
|
// 4- check for https://20ca2.playfabapi.com/Client/GetTitlePublicKey...
|
|
public static void GetPublicKeyAndMicrosoftTakesABigL()
|
|
{
|
|
dynamic dyn = new ExpandoObject();
|
|
dyn.TitleId = TITLE_ID;
|
|
dyn.TitleSharedSecret = TITLE_SECRET;
|
|
|
|
dynamic resp = POST(dyn, "/Client/GetTitlePublicKey", null, true);
|
|
PUBLIC_KEY = Convert.FromBase64String(resp.RSAPublicKey.ToString());
|
|
}
|
|
|
|
public static string EncryptCustomIdLoginToken(string customId, string clientSecret)
|
|
{
|
|
dynamic dyn = new ExpandoObject();
|
|
dyn.CustomId = customId;
|
|
dyn.PlayerSecret = clientSecret;
|
|
|
|
|
|
return EncryptRequest(JsonConvert.SerializeObject(dyn));
|
|
}
|
|
|
|
public static string LoginWithCustomId(bool newUser = true, string customId = null, string clientSecret = null)
|
|
{
|
|
dynamic dyn = new ExpandoObject();
|
|
|
|
if (newUser)
|
|
dyn.CreateAccount = true;
|
|
else
|
|
dyn.CreateAccount = null;
|
|
dyn.CustomId = customId;
|
|
|
|
if (clientSecret == null)
|
|
clientSecret = GenerateClientSecret();
|
|
|
|
if (customId == null)
|
|
customId = GenerateCustomId();
|
|
|
|
if (newUser)
|
|
dyn.EncryptedRequest = EncryptCustomIdLoginToken(customId, clientSecret);
|
|
else
|
|
dyn.EncryptedRequest = null;
|
|
|
|
dyn.InfoRequestParameters = new ExpandoObject();
|
|
dyn.InfoRequestParameters.GetCharacterInventories = false;
|
|
dyn.InfoRequestParameters.GetCharacterList = false;
|
|
dyn.InfoRequestParameters.GetPlayerProfile = true;
|
|
dyn.InfoRequestParameters.GetPlayerStatistics = false;
|
|
dyn.InfoRequestParameters.GetTitleData = false;
|
|
dyn.InfoRequestParameters.GetUserAccountInfo = true;
|
|
dyn.InfoRequestParameters.GetUserData = false;
|
|
dyn.InfoRequestParameters.GetUserInventory = false;
|
|
dyn.InfoRequestParameters.GetUserReadOnlyData = false;
|
|
dyn.InfoRequestParameters.PlayerStatisticNames = null;
|
|
dyn.InfoRequestParameters.ProfileConstraints = null;
|
|
dyn.InfoRequestParameters.TitleDataKeys = null;
|
|
dyn.InfoRequestParameters.UserDataKeys = null;
|
|
dyn.InfoRequestParameters.UserReadOnlyDataKeys = null;
|
|
|
|
dyn.PlayerSecret = null;
|
|
dyn.TitleId = TITLE_ID;
|
|
|
|
|
|
dynamic resp = POST(dyn, "/Client/LoginWithCustomID", newUser ? null : clientSecret, true);
|
|
|
|
Config.WriteConfValue("CustomId", customId);
|
|
Config.WriteConfValue("ClientSecret", clientSecret);
|
|
|
|
ENTITY_TOKEN = resp.EntityToken.EntityToken.ToString();
|
|
ENTITY_ID = resp.PlayFabId.ToString();
|
|
ENTITY_TYPE = "master_player_account";
|
|
|
|
return ENTITY_TOKEN;
|
|
}
|
|
|
|
public static string EncryptRequest(string plaintext)
|
|
{
|
|
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
|
|
{
|
|
rsa.ImportCspBlob(PUBLIC_KEY);
|
|
byte[] bytesToEncrypt = Encoding.UTF8.GetBytes(plaintext);
|
|
byte[] encryptedBytes = rsa.Encrypt(bytesToEncrypt, false);
|
|
return Convert.ToBase64String(encryptedBytes);
|
|
}
|
|
}
|
|
|
|
public static string PullEntityTokenOutOfMyAss()
|
|
{
|
|
|
|
if (Config.GetConfValue("CustomId") == null && Config.GetConfValue("ClientSecret") == null)
|
|
{
|
|
GetPublicKeyAndMicrosoftTakesABigL();
|
|
LoginWithCustomId();
|
|
return RefreshEntityTokenBullshit();
|
|
}
|
|
else
|
|
{
|
|
string customId = Config.GetConfValue("CustomId");
|
|
string clientSecret = Config.GetConfValue("ClientSecret");
|
|
|
|
LoginWithCustomId(false, customId, clientSecret);
|
|
return RefreshEntityTokenBullshit();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|