/// <summary> /// Construct an info object from a config file /// </summary> /// <param name="Config"></param> public bool InitFromConfig(ConfigFile Config) { // we must have the key section ConfigFileSection Section = null; if (Config.TryGetSection("DataDrivenPlatformInfo", out Section) == false) { return(false); } ConfigHierarchySection ParsedSection = new ConfigHierarchySection(new List <ConfigFileSection>() { Section }); // get string values if (ParsedSection.TryGetValue("IniParent", out IniParent) == false) { IniParent = ""; } // slightly nasty bool parsing for bool values string Temp; if (ParsedSection.TryGetValue("bIsConfidential", out Temp) == false || ConfigHierarchy.TryParse(Temp, out bIsConfidential) == false) { bIsConfidential = false; } return(true); }
/// <summary> /// Finds a config section with the given name /// </summary> /// <param name="SectionName">Name of the section to look for</param> /// <returns>The merged config section</returns> public ConfigHierarchySection FindSection(string SectionName) { ConfigHierarchySection Section; try { // Acquire a read lock and do a quick check for the config section NameToSectionLock.EnterUpgradeableReadLock(); if (!NameToSection.TryGetValue(SectionName, out Section)) { try { // Acquire a write lock and add the config section if another thread didn't just complete it NameToSectionLock.EnterWriteLock(); if (!NameToSection.TryGetValue(SectionName, out Section)) { // Find all the raw sections from the file hierarchy List <ConfigFileSection> RawSections = new List <ConfigFileSection>(); foreach (ConfigFile File in Files) { ConfigFileSection RawSection; if (File.TryGetSection(SectionName, out RawSection)) { RawSections.Add(RawSection); } } // Merge them together and add it to the cache Section = new ConfigHierarchySection(RawSections); NameToSection.Add(SectionName, Section); } } finally { NameToSectionLock.ExitWriteLock(); } } } finally { NameToSectionLock.ExitUpgradeableReadLock(); } return(Section); }
/// <summary> /// Finds a config section with the given name /// </summary> /// <param name="SectionName">Name of the section to look for</param> /// <returns>The merged config section</returns> public ConfigHierarchySection FindSection(string SectionName) { ConfigHierarchySection Section; if (!NameToSection.TryGetValue(SectionName, out Section)) { // Find all the raw sections from the file hierarchy List <ConfigFileSection> RawSections = new List <ConfigFileSection>(); foreach (ConfigFile File in Files) { ConfigFileSection RawSection; if (File.TryGetSection(SectionName, out RawSection)) { RawSections.Add(RawSection); } } // Merge them together and add it to the cache Section = new ConfigHierarchySection(RawSections); NameToSection.Add(SectionName, Section); } return(Section); }
/// <summary> /// Parse crypto settings from INI file /// </summary> public static CryptoSettings ParseCryptoSettings(DirectoryReference InProjectDirectory, UnrealTargetPlatform InTargetPlatform) { CryptoSettings Settings = new CryptoSettings(); ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, InProjectDirectory, InTargetPlatform); Ini.GetBool("PlatformCrypto", "PlatformRequiresDataCrypto", out Settings.bDataCryptoRequired); Ini.GetBool("PlatformCrypto", "PakSigningRequired", out Settings.PakSigningRequired); Ini.GetBool("PlatformCrypto", "PakEncryptionRequired", out Settings.PakEncryptionRequired); { // Start by parsing the legacy encryption.ini settings Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Encryption, InProjectDirectory, InTargetPlatform); Ini.GetBool("Core.Encryption", "SignPak", out Settings.bEnablePakSigning); string[] SigningKeyStrings = new string[3]; Ini.GetString("Core.Encryption", "rsa.privateexp", out SigningKeyStrings[0]); Ini.GetString("Core.Encryption", "rsa.modulus", out SigningKeyStrings[1]); Ini.GetString("Core.Encryption", "rsa.publicexp", out SigningKeyStrings[2]); if (String.IsNullOrEmpty(SigningKeyStrings[0]) || String.IsNullOrEmpty(SigningKeyStrings[1]) || String.IsNullOrEmpty(SigningKeyStrings[2])) { SigningKeyStrings = null; } else { Settings.SigningKey = new SigningKeyPair(); Settings.SigningKey.PrivateKey.Exponent = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[0]), 64); Settings.SigningKey.PrivateKey.Modulus = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[1]), 64); Settings.SigningKey.PublicKey.Exponent = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[2]), 64); Settings.SigningKey.PublicKey.Modulus = Settings.SigningKey.PrivateKey.Modulus; if ((Settings.SigningKey.PrivateKey.Exponent.Length > 64) || (Settings.SigningKey.PrivateKey.Modulus.Length > 64) || (Settings.SigningKey.PublicKey.Exponent.Length > 64) || (Settings.SigningKey.PublicKey.Modulus.Length > 64)) { throw new Exception(string.Format("[{0}] Signing keys parsed from encryption.ini are too long. They must be a maximum of 64 bytes long!", InProjectDirectory)); } } Ini.GetBool("Core.Encryption", "EncryptPak", out Settings.bEnablePakIndexEncryption); Settings.bEnablePakFullAssetEncryption = false; Settings.bEnablePakUAssetEncryption = false; Settings.bEnablePakIniEncryption = Settings.bEnablePakIndexEncryption; string EncryptionKeyString; Ini.GetString("Core.Encryption", "aes.key", out EncryptionKeyString); Settings.EncryptionKey = new EncryptionKey(); if (EncryptionKeyString.Length > 0) { if (EncryptionKeyString.Length < 32) { Log.WriteLine(LogEventType.Warning, "AES key parsed from encryption.ini is too short. It must be 32 bytes, so will be padded with 0s, giving sub-optimal security!"); } else if (EncryptionKeyString.Length > 32) { Log.WriteLine(LogEventType.Warning, "AES key parsed from encryption.ini is too long. It must be 32 bytes, so will be truncated!"); } Settings.EncryptionKey.Key = ParseAnsiStringToByteArray(EncryptionKeyString, 32); } } Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Crypto, InProjectDirectory, InTargetPlatform); string SectionName = "/Script/CryptoKeys.CryptoKeysSettings"; ConfigHierarchySection CryptoSection = Ini.FindSection(SectionName); // If we have new format crypto keys, read them in over the top of the legacy settings if (CryptoSection != null && CryptoSection.KeyNames.Count() > 0) { Ini.GetBool(SectionName, "bEnablePakSigning", out Settings.bEnablePakSigning); Ini.GetBool(SectionName, "bEncryptPakIniFiles", out Settings.bEnablePakIniEncryption); Ini.GetBool(SectionName, "bEncryptPakIndex", out Settings.bEnablePakIndexEncryption); Ini.GetBool(SectionName, "bEncryptUAssetFiles", out Settings.bEnablePakUAssetEncryption); Ini.GetBool(SectionName, "bEncryptAllAssetFiles", out Settings.bEnablePakFullAssetEncryption); // Parse encryption key string EncryptionKeyString; Ini.GetString(SectionName, "EncryptionKey", out EncryptionKeyString); if (!string.IsNullOrEmpty(EncryptionKeyString)) { Settings.EncryptionKey = new EncryptionKey(); Settings.EncryptionKey.Key = System.Convert.FromBase64String(EncryptionKeyString); Settings.EncryptionKey.Guid = Guid.Empty.ToString(); Settings.EncryptionKey.Name = "Embedded"; } // Parse secondary encryption keys List <EncryptionKey> SecondaryEncryptionKeys = new List <EncryptionKey>(); List <string> SecondaryEncryptionKeyStrings; if (Ini.GetArray(SectionName, "SecondaryEncryptionKeys", out SecondaryEncryptionKeyStrings)) { foreach (string KeySource in SecondaryEncryptionKeyStrings) { EncryptionKey NewKey = new EncryptionKey(); SecondaryEncryptionKeys.Add(NewKey); Regex Search = new Regex("\\(Guid=(?\'Guid\'.*),Name=\\\"(?\'Name\'.*)\\\",Key=\\\"(?\'Key\'.*)\\\"\\)"); Match Match = Search.Match(KeySource); if (Match.Success) { foreach (string GroupName in Search.GetGroupNames()) { string Value = Match.Groups[GroupName].Value; if (GroupName == "Guid") { NewKey.Guid = Value; } else if (GroupName == "Name") { NewKey.Name = Value; } else if (GroupName == "Key") { NewKey.Key = System.Convert.FromBase64String(Value); } } } } } Settings.SecondaryEncryptionKeys = SecondaryEncryptionKeys.ToArray(); // Parse signing key string PrivateExponent, PublicExponent, Modulus; Ini.GetString(SectionName, "SigningPrivateExponent", out PrivateExponent); Ini.GetString(SectionName, "SigningModulus", out Modulus); Ini.GetString(SectionName, "SigningPublicExponent", out PublicExponent); if (!String.IsNullOrEmpty(PrivateExponent) && !String.IsNullOrEmpty(PublicExponent) && !String.IsNullOrEmpty(Modulus)) { Settings.SigningKey = new SigningKeyPair(); Settings.SigningKey.PublicKey.Exponent = System.Convert.FromBase64String(PublicExponent); Settings.SigningKey.PublicKey.Modulus = System.Convert.FromBase64String(Modulus); Settings.SigningKey.PrivateKey.Exponent = System.Convert.FromBase64String(PrivateExponent); Settings.SigningKey.PrivateKey.Modulus = Settings.SigningKey.PublicKey.Modulus; } } // Parse project dynamic keychain keys if (InProjectDirectory != null) { ConfigHierarchy GameIni = ConfigCache.ReadHierarchy(ConfigHierarchyType.Game, InProjectDirectory, InTargetPlatform); if (GameIni != null) { string Filename; if (GameIni.GetString("ContentEncryption", "ProjectKeyChain", out Filename)) { FileReference ProjectKeyChainFile = FileReference.Combine(InProjectDirectory, "Content", Filename); if (FileReference.Exists(ProjectKeyChainFile)) { List <EncryptionKey> EncryptionKeys = new List <EncryptionKey>(); if (Settings.SecondaryEncryptionKeys != null) { EncryptionKeys.AddRange(Settings.SecondaryEncryptionKeys); } string[] Lines = FileReference.ReadAllLines(ProjectKeyChainFile); foreach (string Line in Lines) { string[] KeyParts = Line.Split(':'); if (KeyParts.Length == 4) { EncryptionKey NewKey = new EncryptionKey(); NewKey.Name = KeyParts[0]; NewKey.Guid = KeyParts[2]; NewKey.Key = System.Convert.FromBase64String(KeyParts[3]); EncryptionKey ExistingKey = EncryptionKeys.Find((EncryptionKey OtherKey) => { return(OtherKey.Guid == NewKey.Guid); }); if (ExistingKey != null && !CompareKey(ExistingKey.Key, NewKey.Key)) { throw new Exception("Found multiple encryption keys with the same guid but different AES keys while merging secondary keys from the project key-chain!"); } EncryptionKeys.Add(NewKey); } } Settings.SecondaryEncryptionKeys = EncryptionKeys.ToArray(); } } } } if (!Settings.bDataCryptoRequired) { CryptoSettings NewSettings = new CryptoSettings(); NewSettings.SecondaryEncryptionKeys = Settings.SecondaryEncryptionKeys; Settings = NewSettings; } else { if (!Settings.PakSigningRequired) { Settings.bEnablePakSigning = false; Settings.SigningKey = null; } if (!Settings.PakEncryptionRequired) { Settings.bEnablePakFullAssetEncryption = false; Settings.bEnablePakIndexEncryption = false; Settings.bEnablePakIniEncryption = false; Settings.EncryptionKey = null; Settings.SigningKey = null; } } // Check if we have a valid signing key that is of the old short form if (Settings.SigningKey != null && Settings.SigningKey.IsValid() && Settings.SigningKey.IsUnsecureLegacyKey()) { Log.TraceWarningOnce("Project signing keys found in '{0}' are of the old insecure short format. Please regenerate them using the project crypto settings panel in the editor!", InProjectDirectory); } // Validate the settings we have read if (Settings.bDataCryptoRequired && Settings.bEnablePakSigning && (Settings.SigningKey == null || !Settings.SigningKey.IsValid())) { Log.TraceWarningOnce("Pak signing is enabled, but no valid signing keys were found. Please generate a key in the editor project crypto settings. Signing will be disabled"); Settings.bEnablePakSigning = false; } if (Settings.bDataCryptoRequired && Settings.IsAnyEncryptionEnabled() && (Settings.EncryptionKey == null || !Settings.EncryptionKey.IsValid())) { Log.TraceWarningOnce("Pak encryption is enabled, but no valid encryption key was found. Please generate a key in the editor project crypto settings. Encryption will be disabled"); Settings.bEnablePakUAssetEncryption = false; Settings.bEnablePakFullAssetEncryption = false; Settings.bEnablePakIndexEncryption = false; Settings.bEnablePakIniEncryption = false; } return(Settings); }
/// <summary> /// Parse crypto settings from INI file /// </summary> public static CryptoSettings ParseCryptoSettings(DirectoryReference InProjectDirectory, UnrealTargetPlatform InTargetPlatform) { CryptoSettings Settings = new CryptoSettings(); ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, InProjectDirectory, InTargetPlatform); Ini.GetBool("PlatformCrypto", "PlatformRequiresDataCrypto", out Settings.bDataCryptoRequired); // For now, we'll just not parse any keys if data crypto is disabled for this platform. In the future, we might want to use // these keys for non-data purposes (other general purpose encryption maybe?) if (!Settings.bDataCryptoRequired) { return(Settings); } { // Start by parsing the legacy encryption.ini settings Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Encryption, InProjectDirectory, InTargetPlatform); Ini.GetBool("Core.Encryption", "SignPak", out Settings.bEnablePakSigning); string[] SigningKeyStrings = new string[3]; Ini.GetString("Core.Encryption", "rsa.privateexp", out SigningKeyStrings[0]); Ini.GetString("Core.Encryption", "rsa.modulus", out SigningKeyStrings[1]); Ini.GetString("Core.Encryption", "rsa.publicexp", out SigningKeyStrings[2]); if (String.IsNullOrEmpty(SigningKeyStrings[0]) || String.IsNullOrEmpty(SigningKeyStrings[1]) || String.IsNullOrEmpty(SigningKeyStrings[2])) { SigningKeyStrings = null; } else { Settings.SigningKey = new SigningKeyPair(); Settings.SigningKey.PrivateKey.Exponent = ParseHexStringToByteArray(SigningKeyStrings[0]); Settings.SigningKey.PrivateKey.Modulus = ParseHexStringToByteArray(SigningKeyStrings[1]); Settings.SigningKey.PublicKey.Exponent = ParseHexStringToByteArray(SigningKeyStrings[2]); Settings.SigningKey.PublicKey.Modulus = Settings.SigningKey.PrivateKey.Modulus; } Ini.GetBool("Core.Encryption", "EncryptPak", out Settings.bEnablePakIndexEncryption); Settings.bEnablePakFullAssetEncryption = false; Settings.bEnablePakUAssetEncryption = false; Settings.bEnablePakIniEncryption = Settings.bEnablePakIndexEncryption; string EncryptionKeyString; Ini.GetString("Core.Encryption", "aes.key", out EncryptionKeyString); Settings.EncryptionKey = new EncryptionKey(); Settings.EncryptionKey.Key = ParseAnsiStringToByteArray(EncryptionKeyString); } Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Crypto, InProjectDirectory, InTargetPlatform); string SectionName = "/Script/CryptoKeys.CryptoKeysSettings"; ConfigHierarchySection CryptoSection = Ini.FindSection(SectionName); // If we have new format crypto keys, read them in over the top of the legacy settings if (CryptoSection != null && CryptoSection.KeyNames.Count() > 0) { Ini.GetBool(SectionName, "bEnablePakSigning", out Settings.bEnablePakSigning); Ini.GetBool(SectionName, "bEncryptPakIniFiles", out Settings.bEnablePakIniEncryption); Ini.GetBool(SectionName, "bEncryptPakIndex", out Settings.bEnablePakIndexEncryption); Ini.GetBool(SectionName, "bEncryptUAssetFiles", out Settings.bEnablePakUAssetEncryption); Ini.GetBool(SectionName, "bEncryptAllAssetFiles", out Settings.bEnablePakFullAssetEncryption); // Parse encryption key string EncryptionKeyString; Ini.GetString(SectionName, "EncryptionKey", out EncryptionKeyString); if (!string.IsNullOrEmpty(EncryptionKeyString)) { Settings.EncryptionKey = new EncryptionKey(); Settings.EncryptionKey.Key = System.Convert.FromBase64String(EncryptionKeyString); if (Settings.EncryptionKey.Key.Length != 32) { throw new Exception("The encryption key specified in the crypto config file must be 32 bytes long!"); } } // Parse signing key string PrivateExponent, PublicExponent, Modulus; Ini.GetString(SectionName, "SigningPrivateExponent", out PrivateExponent); Ini.GetString(SectionName, "SigningModulus", out Modulus); Ini.GetString(SectionName, "SigningPublicExponent", out PublicExponent); if (!String.IsNullOrEmpty(PrivateExponent) && !String.IsNullOrEmpty(PublicExponent) && !String.IsNullOrEmpty(Modulus)) { Settings.SigningKey = new SigningKeyPair(); Settings.SigningKey.PublicKey.Exponent = System.Convert.FromBase64String(PublicExponent); Settings.SigningKey.PublicKey.Modulus = System.Convert.FromBase64String(Modulus); Settings.SigningKey.PrivateKey.Exponent = System.Convert.FromBase64String(PrivateExponent); Settings.SigningKey.PrivateKey.Modulus = Settings.SigningKey.PublicKey.Modulus; } } return(Settings); }
/// <summary> /// Return all data driven infos found /// </summary> /// <returns></returns> public static Dictionary <string, ConfigDataDrivenPlatformInfo> GetAllPlatformInfos() { // need to init? if (PlatformInfos == null) { PlatformInfos = new Dictionary <string, ConfigDataDrivenPlatformInfo>(); Dictionary <string, string> IniParents = new Dictionary <string, string>(); foreach (DirectoryReference EngineConfigDir in UnrealBuildTool.GetAllEngineDirectories("Config")) { // look through all config dirs looking for the data driven ini file foreach (string FilePath in Directory.EnumerateFiles(EngineConfigDir.FullName, "DataDrivenPlatformInfo.ini", SearchOption.AllDirectories)) { FileReference FileRef = new FileReference(FilePath); // get the platform name from the path string IniPlatformName; if (FileRef.IsUnderDirectory(DirectoryReference.Combine(UnrealBuildTool.EngineDirectory, "Config"))) { // Foo/Engine/Config/<Platform>/DataDrivenPlatformInfo.ini IniPlatformName = Path.GetFileName(Path.GetDirectoryName(FilePath)); } else { // Foo/Engine/Platforms/<Platform>/Config/DataDrivenPlatformInfo.ini IniPlatformName = Path.GetFileName(Path.GetDirectoryName(Path.GetDirectoryName(FilePath))); } // load the DataDrivenPlatformInfo from the path ConfigFile Config = new ConfigFile(FileRef); ConfigDataDrivenPlatformInfo NewInfo = new ConfigDataDrivenPlatformInfo(); // we must have the key section ConfigFileSection Section = null; if (Config.TryGetSection("DataDrivenPlatformInfo", out Section)) { ConfigHierarchySection ParsedSection = new ConfigHierarchySection(new List <ConfigFileSection>() { Section }); // get string values string IniParent; if (ParsedSection.TryGetValue("IniParent", out IniParent)) { IniParents[IniPlatformName] = IniParent; } // slightly nasty bool parsing for bool values string Temp; if (ParsedSection.TryGetValue("bIsConfidential", out Temp) == false || ConfigHierarchy.TryParse(Temp, out NewInfo.bIsConfidential) == false) { NewInfo.bIsConfidential = false; } // get a list of additional restricted folders IReadOnlyList <string> AdditionalRestrictedFolders; if (ParsedSection.TryGetValues("AdditionalRestrictedFolders", out AdditionalRestrictedFolders) && AdditionalRestrictedFolders.Count > 0) { NewInfo.AdditionalRestrictedFolders = AdditionalRestrictedFolders.Select(x => x.Trim()).Where(x => x.Length > 0).ToArray(); } // create cache it PlatformInfos[IniPlatformName] = NewInfo; } } } // now that all are read in, calculate the ini parent chain, starting with parent-most foreach (KeyValuePair <string, ConfigDataDrivenPlatformInfo> Pair in PlatformInfos) { string CurrentPlatform; // walk up the chain and build up the ini chain List <string> Chain = new List <string>(); if (IniParents.TryGetValue(Pair.Key, out CurrentPlatform)) { while (!string.IsNullOrEmpty(CurrentPlatform)) { // insert at 0 to reverse the order Chain.Insert(0, CurrentPlatform); if (IniParents.TryGetValue(CurrentPlatform, out CurrentPlatform) == false) { break; } } } // bake it into the info if (Chain.Count > 0) { Pair.Value.IniParentChain = Chain.ToArray(); } } } return(PlatformInfos); }
/// <summary> /// Parse crypto settings from INI file /// </summary> public static CryptoSettings ParseCryptoSettings(DirectoryReference InProjectDirectory, UnrealTargetPlatform InTargetPlatform) { CryptoSettings Settings = new CryptoSettings(); ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, InProjectDirectory, InTargetPlatform); Ini.GetBool("PlatformCrypto", "PlatformRequiresDataCrypto", out Settings.bDataCryptoRequired); // For now, we'll just not parse any keys if data crypto is disabled for this platform. In the future, we might want to use // these keys for non-data purposes (other general purpose encryption maybe?) if (!Settings.bDataCryptoRequired) { return(Settings); } { // Start by parsing the legacy encryption.ini settings Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Encryption, InProjectDirectory, InTargetPlatform); Ini.GetBool("Core.Encryption", "SignPak", out Settings.bEnablePakSigning); string[] SigningKeyStrings = new string[3]; Ini.GetString("Core.Encryption", "rsa.privateexp", out SigningKeyStrings[0]); Ini.GetString("Core.Encryption", "rsa.modulus", out SigningKeyStrings[1]); Ini.GetString("Core.Encryption", "rsa.publicexp", out SigningKeyStrings[2]); if (String.IsNullOrEmpty(SigningKeyStrings[0]) || String.IsNullOrEmpty(SigningKeyStrings[1]) || String.IsNullOrEmpty(SigningKeyStrings[2])) { SigningKeyStrings = null; } else { Settings.SigningKey = new SigningKeyPair(); Settings.SigningKey.PrivateKey.Exponent = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[0]), 64); Settings.SigningKey.PrivateKey.Modulus = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[1]), 64); Settings.SigningKey.PublicKey.Exponent = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[2]), 64); Settings.SigningKey.PublicKey.Modulus = Settings.SigningKey.PrivateKey.Modulus; if ((Settings.SigningKey.PrivateKey.Exponent.Length > 64) || (Settings.SigningKey.PrivateKey.Modulus.Length > 64) || (Settings.SigningKey.PublicKey.Exponent.Length > 64) || (Settings.SigningKey.PublicKey.Modulus.Length > 64)) { throw new Exception(string.Format("[{0}] Signing keys parsed from encryption.ini are too long. They must be a maximum of 64 bytes long!", InProjectDirectory)); } } Ini.GetBool("Core.Encryption", "EncryptPak", out Settings.bEnablePakIndexEncryption); Settings.bEnablePakFullAssetEncryption = false; Settings.bEnablePakUAssetEncryption = false; Settings.bEnablePakIniEncryption = Settings.bEnablePakIndexEncryption; string EncryptionKeyString; Ini.GetString("Core.Encryption", "aes.key", out EncryptionKeyString); Settings.EncryptionKey = new EncryptionKey(); if (EncryptionKeyString.Length > 0) { if (EncryptionKeyString.Length < 32) { Log.WriteLine(LogEventType.Warning, "AES key parsed from encryption.ini is too short. It must be 32 bytes, so will be padded with 0s, giving sub-optimal security!"); } else if (EncryptionKeyString.Length > 32) { Log.WriteLine(LogEventType.Warning, "AES key parsed from encryption.ini is too long. It must be 32 bytes, so will be truncated!"); } Settings.EncryptionKey.Key = ParseAnsiStringToByteArray(EncryptionKeyString, 32); } } Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Crypto, InProjectDirectory, InTargetPlatform); string SectionName = "/Script/CryptoKeys.CryptoKeysSettings"; ConfigHierarchySection CryptoSection = Ini.FindSection(SectionName); // If we have new format crypto keys, read them in over the top of the legacy settings if (CryptoSection != null && CryptoSection.KeyNames.Count() > 0) { Ini.GetBool(SectionName, "bEnablePakSigning", out Settings.bEnablePakSigning); Ini.GetBool(SectionName, "bEncryptPakIniFiles", out Settings.bEnablePakIniEncryption); Ini.GetBool(SectionName, "bEncryptPakIndex", out Settings.bEnablePakIndexEncryption); Ini.GetBool(SectionName, "bEncryptUAssetFiles", out Settings.bEnablePakUAssetEncryption); Ini.GetBool(SectionName, "bEncryptAllAssetFiles", out Settings.bEnablePakFullAssetEncryption); // Parse encryption key string EncryptionKeyString; Ini.GetString(SectionName, "EncryptionKey", out EncryptionKeyString); if (!string.IsNullOrEmpty(EncryptionKeyString)) { Settings.EncryptionKey = new EncryptionKey(); Settings.EncryptionKey.Key = System.Convert.FromBase64String(EncryptionKeyString); } // Parse signing key string PrivateExponent, PublicExponent, Modulus; Ini.GetString(SectionName, "SigningPrivateExponent", out PrivateExponent); Ini.GetString(SectionName, "SigningModulus", out Modulus); Ini.GetString(SectionName, "SigningPublicExponent", out PublicExponent); if (!String.IsNullOrEmpty(PrivateExponent) && !String.IsNullOrEmpty(PublicExponent) && !String.IsNullOrEmpty(Modulus)) { Settings.SigningKey = new SigningKeyPair(); Settings.SigningKey.PublicKey.Exponent = System.Convert.FromBase64String(PublicExponent); Settings.SigningKey.PublicKey.Modulus = System.Convert.FromBase64String(Modulus); Settings.SigningKey.PrivateKey.Exponent = System.Convert.FromBase64String(PrivateExponent); Settings.SigningKey.PrivateKey.Modulus = Settings.SigningKey.PublicKey.Modulus; } } return(Settings); }