123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using UnityEngine;
-
- namespace UnityEditor.Purchasing
- {
- class ObfuscationGenerator
- {
- const string m_GeneratedCredentialsTemplateFilename = "IAPGeneratedCredentials.cs.template";
- const string m_GeneratedCredentialsTemplateFilenameNoExtension = "IAPGeneratedCredentials.cs";
-
- const string k_AppleCertPath = "Packages/com.unity.purchasing/Editor/AppleIncRootCertificate.cer";
- const string k_AppleStoreKitTestCertPath = "Packages/com.unity.purchasing/Editor/StoreKitTestCertificate.cer";
-
- const string k_AppleClassIncompleteErr = "Invalid Apple Root Certificate";
- const string k_AppleStoreKitTestClassIncompleteErr = "Invalid Apple StoreKit Test Certificate";
-
- internal static string ObfuscateAppleSecrets()
- {
- var appleError = WriteObfuscatedAppleClassAsAsset();
-
- AssetDatabase.Refresh();
-
- return appleError;
- }
-
- internal static string ObfuscateGoogleSecrets(string googlePlayPublicKey)
- {
- var googleError = WriteObfuscatedGooglePlayClassAsAsset(googlePlayPublicKey);
-
- AssetDatabase.Refresh();
-
- return googleError;
- }
-
- /// <summary>
- /// Generates specified obfuscated class files.
- /// </summary>
- internal static void ObfuscateSecrets(bool includeGoogle, ref string appleError, ref string googleError, string googlePlayPublicKey)
- {
- try
- {
- // First things first! Obfuscate! XHTLOA!
- appleError = WriteObfuscatedAppleClassAsAsset();
-
- if (includeGoogle)
- {
- googleError = WriteObfuscatedGooglePlayClassAsAsset(googlePlayPublicKey);
- }
- }
- catch (Exception e)
- {
- Debug.LogWarning(e.StackTrace);
- }
-
- // Ensure all the Tangle classes exist, even if they were not generated at this time.
- if (!DoesGooglePlayTangleClassExist())
- {
- try
- {
- WriteObfuscatedClassAsAsset(TangleFileConsts.k_GooglePlayClassPrefix, 0, new int[0], new byte[0], false);
- }
- catch (Exception e)
- {
- Debug.LogWarning(e.StackTrace);
- }
- }
-
- AssetDatabase.Refresh();
- }
-
- static string WriteObfuscatedAppleClassAsAsset()
- {
- var err = WriteObfuscatedAppleClassAsAsset(k_AppleCertPath, k_AppleClassIncompleteErr, TangleFileConsts.k_AppleClassPrefix);
-
- if (err == null)
- {
- err = WriteObfuscatedAppleClassAsAsset(k_AppleStoreKitTestCertPath, k_AppleStoreKitTestClassIncompleteErr, TangleFileConsts.k_AppleStoreKitTestClassPrefix);
- }
-
- return err;
- }
-
- static string WriteObfuscatedAppleClassAsAsset(string certPath, string classIncompleteErr, string classPrefix)
- {
- string appleError = null;
- var key = 0;
- var order = new int[0];
- var tangled = new byte[0];
- try
- {
- var bytes = File.ReadAllBytes(certPath);
- order = new int[bytes.Length / 20 + 1];
-
- // TODO: Integrate with upgraded Tangle!
-
- tangled = TangleObfuscator.Obfuscate(bytes, order, out key);
- }
- catch (Exception e)
- {
- Debug.LogWarning($"{classIncompleteErr}. Generating incomplete credentials file. " + e);
- appleError = $" {classIncompleteErr}";
- }
-
- WriteObfuscatedClassAsAsset(classPrefix, key, order, tangled, tangled.Length != 0);
-
- return appleError;
- }
-
- static string WriteObfuscatedGooglePlayClassAsAsset(string googlePlayPublicKey)
- {
- string googleError = null;
- var key = 0;
- var order = new int[0];
- var tangled = new byte[0];
- try
- {
- var bytes = Convert.FromBase64String(googlePlayPublicKey);
- order = new int[bytes.Length / 20 + 1];
-
- tangled = TangleObfuscator.Obfuscate(bytes, order, out key);
- }
- catch (Exception e)
- {
- Debug.LogWarning("Invalid Google Play Public Key. Generating incomplete credentials file. " + e);
- googleError =
- " The Google Play License Key is invalid. GooglePlayTangle was generated with incomplete credentials.";
- }
- WriteObfuscatedClassAsAsset(TangleFileConsts.k_GooglePlayClassPrefix, key, order, tangled, tangled.Length != 0);
-
- return googleError;
- }
-
- static string FullPathForTangleClass(string classnamePrefix)
- {
- return Path.Combine(TangleFileConsts.k_OutputPath, string.Format($"{classnamePrefix}{TangleFileConsts.k_ObfuscationClassSuffix}"));
- }
-
- internal static bool DoesAppleTangleClassExist()
- {
- return ObfuscatedClassExists(TangleFileConsts.k_AppleClassPrefix) &&
- ObfuscatedClassExists(TangleFileConsts.k_AppleStoreKitTestClassPrefix);
- }
-
- internal static bool DoesGooglePlayTangleClassExist()
- {
- return ObfuscatedClassExists(TangleFileConsts.k_GooglePlayClassPrefix);
- }
-
- static bool ObfuscatedClassExists(string classnamePrefix)
- {
- return File.Exists(FullPathForTangleClass(classnamePrefix));
- }
-
- static void WriteObfuscatedClassAsAsset(string classnamePrefix, int key, int[] order, byte[] data, bool populated)
- {
- var substitutionDictionary = new Dictionary<string, string>()
- {
- {"{NAME}", classnamePrefix.ToString()},
- {"{KEY}", key.ToString()},
- {"{ORDER}", String.Format("{0}",String.Join(",", Array.ConvertAll(order, i => i.ToString())))},
- {"{DATA}", Convert.ToBase64String(data)},
- {"{POPULATED}", populated.ToString().ToLowerInvariant()} // Defaults to XML-friendly values
- };
-
- var templateText = LoadTemplateText(out var templateRelativePath);
-
- if (templateText != null)
- {
- var outfileText = templateText;
-
- // Apply the parameters to the template
- foreach (var pair in substitutionDictionary)
- {
- outfileText = outfileText.Replace(pair.Key, pair.Value);
- }
- Directory.CreateDirectory(TangleFileConsts.k_OutputPath);
- File.WriteAllText(FullPathForTangleClass(classnamePrefix), outfileText);
- }
- }
-
- /// <summary>
- /// Loads the template file.
- /// </summary>
- /// <returns>The template file's text.</returns>
- /// <param name="templateRelativePath">Relative Assets/ path to template file.</param>
- static string LoadTemplateText(out string templateRelativePath)
- {
- var assetGUIDs =
- AssetDatabase.FindAssets(m_GeneratedCredentialsTemplateFilenameNoExtension);
- string templateGUID = null;
- templateRelativePath = null;
-
- if (assetGUIDs.Length > 0)
- {
- templateGUID = assetGUIDs[0];
- }
- else
- {
- Debug.LogError(String.Format("Could not find template \"{0}\"",
- m_GeneratedCredentialsTemplateFilename));
- }
-
- string templateText = null;
-
- if (templateGUID != null)
- {
- templateRelativePath = AssetDatabase.GUIDToAssetPath(templateGUID);
-
- var templateAbsolutePath =
- Path.GetDirectoryName(Application.dataPath)
- + Path.DirectorySeparatorChar
- + templateRelativePath;
-
- templateText = File.ReadAllText(templateAbsolutePath);
- }
-
- return templateText;
- }
- }
- }
|