private async Task SendMessageAsync(Mocks.CloudBlobStorageProviderMock cloudStorage, Mocks.InboxHttpHandlerMock inboxMock, CryptoSettings senderCrypto, OwnEndpoint senderEndpoint, Endpoint receiverEndpoint) { Requires.NotNull(cloudStorage, "cloudStorage"); Requires.NotNull(senderCrypto, "senderCrypto"); Requires.NotNull(senderEndpoint, "senderEndpoint"); Requires.NotNull(receiverEndpoint, "receiverEndpoint"); var httpHandler = new Mocks.HttpMessageHandlerMock(); cloudStorage.AddHttpHandler(httpHandler); inboxMock.Register(httpHandler); var sentMessage = Valid.Message; var channel = new Channel() { HttpClient = new HttpClient(httpHandler), CloudBlobStorage = cloudStorage, CryptoServices = senderCrypto, Endpoint = senderEndpoint, Logger = this.logger, }; await channel.PostAsync(sentMessage, new[] { receiverEndpoint }, Valid.ExpirationUtc); }
private async Task ReceiveMessageAsync(Mocks.CloudBlobStorageProviderMock cloudStorage, Mocks.InboxHttpHandlerMock inboxMock, CryptoSettings receiverCrypto, OwnEndpoint receiverEndpoint) { Requires.NotNull(cloudStorage, "cloudStorage"); Requires.NotNull(receiverCrypto, "receiverCrypto"); Requires.NotNull(receiverEndpoint, "receiverEndpoint"); var httpHandler = new Mocks.HttpMessageHandlerMock(); cloudStorage.AddHttpHandler(httpHandler); inboxMock.Register(httpHandler); var channel = new Channel { HttpClient = new HttpClient(httpHandler), HttpClientLongPoll = new HttpClient(httpHandler), CloudBlobStorage = cloudStorage, CryptoServices = receiverCrypto, Endpoint = receiverEndpoint, Logger = this.logger, }; var messages = await channel.ReceiveAsync(); Assert.Equal(1, messages.Count); Assert.Equal(Valid.Message, messages[0].Payload); }
/// <summary> /// Gets the settings. /// </summary> /// <param name="version">The version.</param> /// <returns></returns> /// <exception cref="System.ArgumentOutOfRangeException">version</exception> public static CryptoSettings GetSettings(int version = CryptoVersion10) { CryptoSettings settings; switch (version) { case CryptoVersion10: settings = new CryptoSettings { Version = version, CryptoProvider = new Aes256CryptoProvider() }; break; default: settings = null; break; } if (settings == null) { throw new ArgumentOutOfRangeException(nameof(version)); } return(settings); }
public void CreateAddressBookEntry() { var ownContact = Valid.ReceivingEndpoint; CryptoSettings cryptoServices = new CryptoSettings(SecurityLevel.Minimum); var entry = ownContact.CreateAddressBookEntry(cryptoServices); Assert.NotEqual(0, entry.Signature?.Length); Assert.NotEqual(0, entry.SerializedEndpoint?.Length); }
public void FillFileSystemTest() { ConfigurationTest.Initialize(); Random r = new Random(1234); using (var io = ConfigurationTest.CreateMemoryIO()) { FileSystem fs = FileSystem.Create(io); byte[] data = new byte[1024 * 1024]; Directory d = fs.RootDirectory; File f = fs.CreateFile(d, "TEST"); int totalBytesWritten = 0; using (FileIO fio = new FileIO(fs, f)) { int bytesWritten = 0; do { r.NextBytes(data); bytesWritten = fio.WriteFile(data, f.Length); totalBytesWritten += bytesWritten; } while (bytesWritten != 0); } fs.Dispose(); CryptoSettings cryptoSettings = Configuration.CryptoSettings; Options options = Configuration.Options; Configuration.Reset(); Configuration.CryptoSettings = cryptoSettings; Configuration.Options = options; fs = FileSystem.Mount(io); r = new Random(1234); f = fs.GetContainedFiles(fs.RootDirectory)["TEST"]; Assert.AreEqual(f.Length, totalBytesWritten); int totalBytesRead = 0; byte[] compare = new byte[1024 * 1024]; using (FileIO fio = new FileIO(fs, f)) { int bytesRead = 0; do { r.NextBytes(data); bytesRead = fio.ReadFile(compare, totalBytesRead); totalBytesRead += bytesRead; for (int i = 0; i < bytesRead; i++) { Assert.AreEqual(compare[i], data[i]); } } while (bytesRead != 0); } Assert.AreEqual(totalBytesRead, totalBytesWritten); fs.Dispose(); } }
private async Task TestSendAndReceiveAsync( CryptoSettings senderCrypto, OwnEndpoint senderEndpoint, CryptoSettings receiverCrypto, OwnEndpoint receiverEndpoint) { var inboxMock = new Mocks.InboxHttpHandlerMock(new[] { receiverEndpoint.PublicEndpoint }); var cloudStorage = new Mocks.CloudBlobStorageProviderMock(); await this.SendMessageAsync(cloudStorage, inboxMock, senderCrypto, senderEndpoint, receiverEndpoint.PublicEndpoint); await this.ReceiveMessageAsync(cloudStorage, inboxMock, receiverCrypto, receiverEndpoint); }
public void ExtractEndpoint() { var ownContact = new OwnEndpoint(Valid.ReceivingEndpoint.SigningKey, Valid.ReceivingEndpoint.EncryptionKey); var cryptoServices = new CryptoSettings(SecurityLevel.Minimum); var entry = ownContact.CreateAddressBookEntry(cryptoServices); var endpoint = entry.ExtractEndpoint(); Assert.Equal(ownContact.PublicEndpoint, endpoint); }
public async Task CrossSecurityLevelAddressBookExchange() { var lowLevelCrypto = new CryptoSettings(SecurityLevel.Minimum); var lowLevelEndpoint = Valid.GenerateOwnEndpoint(lowLevelCrypto); var highLevelCrypto = new CryptoSettings(SecurityLevel.Minimum) { AsymmetricKeySize = 2048 }; var highLevelEndpoint = Valid.GenerateOwnEndpoint(highLevelCrypto); await this.TestSendAndReceiveAsync(lowLevelCrypto, lowLevelEndpoint, highLevelCrypto, highLevelEndpoint); await this.TestSendAndReceiveAsync(highLevelCrypto, highLevelEndpoint, lowLevelCrypto, lowLevelEndpoint); }
/// <summary> /// Encrypts and encodes the specified data. /// </summary> /// <param name="plainText">The plain text.</param> /// <returns></returns> public string EncryptAndEncode(string plainText) { if (string.IsNullOrEmpty(plainText)) { return(plainText); } CryptoSettings settings = CryptoSettings.GetSettings(); ICryptoProvider cryptoProvider = settings.CryptoProvider; byte[] iv = cryptoProvider.GenerateRandomIv(); byte[] cipherText = cryptoProvider.EncryptData(plainText, Initialise(), iv); return(EncodeCipherText(settings.Version, iv, cipherText)); }
internal static OwnEndpoint GenerateOwnEndpoint(CryptoSettings cryptoProvider = null) { cryptoProvider = cryptoProvider ?? new CryptoSettings(SecurityLevel.Minimum); var inboxFactory = new Mock<IEndpointInboxFactory>(); inboxFactory.Setup(f => f.CreateInboxAsync(CancellationToken.None)).Returns( Task.FromResult( new InboxCreationResponse { InboxOwnerCode = "some owner code", MessageReceivingEndpoint = MessageReceivingEndpoint.AbsoluteUri })); var endpointServices = new OwnEndpointServices { Channel = new Channel { CryptoServices = cryptoProvider }, EndpointInboxFactory = inboxFactory.Object, }; var ownContact = endpointServices.CreateAsync().Result; return ownContact; }
public void PostAndReceiveAsync() { Task.Run(async delegate { var sender = Valid.GenerateOwnEndpoint(); var receiver = Valid.GenerateOwnEndpoint(); var cloudStorage = new Mocks.CloudBlobStorageProviderMock(); var inboxMock = new Mocks.InboxHttpHandlerMock(new[] { receiver.PublicEndpoint }); var cryptoProvider = new CryptoSettings(SecurityLevel.Minimum); var sentMessage = Valid.Message; await this.SendMessageAsync(cloudStorage, inboxMock, cryptoProvider, sender, receiver.PublicEndpoint, sentMessage); var messages = await this.ReceiveMessageAsync(cloudStorage, inboxMock, new CryptoSettings(SecurityLevel.Minimum), receiver); Assert.Equal(1, messages.Count); var receivedMessage = messages.Single(); Assert.Equal(receivedMessage.Payload.ContentType, sentMessage.ContentType); Assert.Equal(receivedMessage.Payload.Content, sentMessage.Content); }).GetAwaiter().GetResult(); }
/// <summary> /// Decodes and decrypts the specified cipher text. /// </summary> /// <param name="encodedCipherText">The encoded cipher text.</param> /// <returns></returns> public string DecodeAndDecrypt(string encodedCipherText) { if (string.IsNullOrEmpty(encodedCipherText)) { return(encodedCipherText); } int version; byte[] iv; byte[] cipherText; if (!TryDecodeEncodedCipherText(encodedCipherText, out version, out iv, out cipherText)) { return(null); } CryptoSettings settings = CryptoSettings.GetSettings(version); ICryptoProvider cryptoProvider = settings.CryptoProvider; return(cryptoProvider.DecryptData(cipherText, Initialise(), iv)); }
public void FileDeleteTest() { ConfigurationTest.Initialize(); Random r = new Random(1234); using (var io = ConfigurationTest.CreateMemoryIO()) { FileSystem fs = FileSystem.Create(io); byte[] data = new byte[1024 * 1024]; r.NextBytes(data); Directory d = fs.RootDirectory; File f = fs.CreateFile(d, "TEST"); using (FileIO fio = new FileIO(fs, f)) { Assert.AreEqual(data.Length, fio.WriteFile(data, 0)); } fs.Dispose(); CryptoSettings cryptoSettings = Configuration.CryptoSettings; Options options = Configuration.Options; Configuration.Reset(); Configuration.CryptoSettings = cryptoSettings; Configuration.Options = options; fs = FileSystem.Mount(io); byte[] data2 = new byte[data.Length]; File f2 = fs.GetContainedFiles(fs.RootDirectory)["TEST"]; fs.RemoveFile(f2); Assert.AreEqual(0, (from s in fs.ClusterStates where (s & ClusterState.Used) != 0 && (s & ClusterState.System) == 0 select s).Count()); Assert.AreEqual(0, fs.GetContainedFiles(fs.RootDirectory).Count); fs.Dispose(); } }
internal static OwnEndpoint GenerateOwnEndpoint(CryptoSettings cryptoProvider = null) { cryptoProvider = cryptoProvider ?? new CryptoSettings(SecurityLevel.Minimum); var inboxFactory = new Mock <IEndpointInboxFactory>(); inboxFactory.Setup(f => f.CreateInboxAsync(CancellationToken.None)).Returns( Task.FromResult( new InboxCreationResponse { InboxOwnerCode = "some owner code", MessageReceivingEndpoint = MessageReceivingEndpoint.AbsoluteUri })); var endpointServices = new OwnEndpointServices { Channel = new Channel { CryptoServices = cryptoProvider }, EndpointInboxFactory = inboxFactory.Object, }; var ownContact = endpointServices.CreateAsync().Result; return(ownContact); }
/// <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); }
public AddressBookEntryTest() { this.desktopCryptoProvider = TestUtilities.CreateAuthenticCryptoProvider(); }
/// <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); }
public void FileIOTest() { ConfigurationTest.Initialize(); Random r = new Random(1234); using (var io = ConfigurationTest.CreateMemoryIO()) { FileSystem fs = FileSystem.Create(io); byte[] data = new byte[1024 * 1024]; r.NextBytes(data); Directory d = fs.RootDirectory; File f = fs.CreateFile(d, "TEST"); using (FileIO fio = new FileIO(fs, f)) { Assert.AreEqual(data.Length, fio.WriteFile(data, 0)); for (int j = 0; j < 100; j++) { switch (r.Next(3)) { case 0: { // Internal Overwrite int offset = r.Next(data.Length); int count = r.Next(data.Length - offset); if (count != 0) { byte[] newData = new byte[count]; r.NextBytes(newData); Assert.AreEqual(newData.Length, fio.WriteFile(newData, offset)); Buffer.BlockCopy(newData, 0, data, offset, count); Assert.AreEqual(data.Length, f.Length); } break; } case 1: { // Append int count = r.Next(2 * 1024 * 1024 - (int)f.Length); if (count != 0) { int offset = (int)f.Length; byte[] newData = new byte[count]; r.NextBytes(newData); Assert.AreEqual(newData.Length, fio.WriteFile(newData, offset)); byte[] dt = new byte[count + data.Length]; Buffer.BlockCopy(data, 0, dt, 0, offset); Buffer.BlockCopy(newData, 0, dt, offset, count); data = dt; Assert.AreEqual(data.Length, f.Length); } break; } case 2: { // Set Length int count = r.Next(2 * 1024 * 1024); fio.SetEndOfFile(count); byte[] newData = new byte[count]; Buffer.BlockCopy(data, 0, newData, 0, Math.Min(count, data.Length)); data = newData; Assert.AreEqual(data.Length, f.Length); break; } } } } int length = (int)f.Length; int clusters = length <= FileHeaderCluster.DataSize ? 1 : (length - FileHeaderCluster.DataSize + FileDataCluster.DataSize - 1) / FileDataCluster.DataSize + 1; Assert.AreEqual(clusters, (from s in fs.ClusterStates where (s & ClusterState.Used) != 0 && (s & ClusterState.System) == 0 select s).Count()); fs.Dispose(); CryptoSettings cryptoSettings = Configuration.CryptoSettings; Options options = Configuration.Options; Configuration.Reset(); Configuration.CryptoSettings = cryptoSettings; Configuration.Options = options; fs = FileSystem.Mount(io); byte[] data2 = new byte[data.Length]; File f2 = fs.GetContainedFiles(fs.RootDirectory)["TEST"]; Assert.AreEqual(f.Length, f2.Length); using (FileIO fio = new FileIO(fs, f2)) { Assert.AreEqual(data2.Length, fio.ReadFile(data2, 0)); Assert.AreEqual(0, fio.ReadFile(data2, data2.Length)); } Assert.IsTrue(data.SequenceEqual(data2)); length = (int)f2.Length; clusters = length <= FileHeaderCluster.DataSize ? 1 : (length - FileHeaderCluster.DataSize + FileDataCluster.DataSize - 1) / FileDataCluster.DataSize + 1; Assert.AreEqual(clusters, (from s in fs.ClusterStates where (s & ClusterState.Used) != 0 && (s & ClusterState.System) == 0 select s).Count()); using (FileIO fio = new FileIO(fs, f2)) { fio.SetEndOfFile(0); } Assert.AreEqual(0, f2.Length); Assert.AreEqual(0, (from s in fs.ClusterStates where (s & ClusterState.Used) != 0 && (s & ClusterState.System) == 0 select s).Count()); fs.Dispose(); Configuration.Reset(); Configuration.CryptoSettings = cryptoSettings; Configuration.Options = options; fs = FileSystem.Mount(io); File f3 = fs.GetContainedFiles(fs.RootDirectory)["TEST"]; Assert.AreEqual(0, f3.Length); Assert.AreEqual(0, (from s in fs.ClusterStates where (s & ClusterState.Used) != 0 && (s & ClusterState.System) == 0 select s).Count()); } }
private async Task<IReadOnlyCollection<Channel.PayloadReceipt>> ReceiveMessageAsync(Mocks.CloudBlobStorageProviderMock cloudBlobStorage, Mocks.InboxHttpHandlerMock inboxMock, CryptoSettings cryptoProvider, OwnEndpoint receiver, bool expectMessage = true) { Requires.NotNull(cloudBlobStorage, "cloudBlobStorage"); Requires.NotNull(receiver, "receiver"); var httpHandler = new Mocks.HttpMessageHandlerMock(); cloudBlobStorage.AddHttpHandler(httpHandler); inboxMock.Register(httpHandler); var channel = new Channel { HttpClient = new HttpClient(httpHandler), HttpClientLongPoll = new HttpClient(httpHandler), CloudBlobStorage = cloudBlobStorage, CryptoServices = cryptoProvider, Endpoint = receiver, Logger = this.logger, }; var progressMessage = new TaskCompletionSource<Payload>(); var progress = new Progress<Channel.PayloadReceipt>(m => progressMessage.SetResult(m.Payload)); var messages = await channel.ReceiveAsync(progress: progress); if (expectMessage) { Assert.Equal(1, messages.Count); await progressMessage.Task; Assert.Same(progressMessage.Task.Result, messages.Single().Payload); } else { Assert.Equal(0, messages.Count); } return messages; }
public void FileSystemCreateTest() { ConfigurationTest.Initialize(); Random r = new Random(1234); using (var io = ConfigurationTest.CreateMemoryIO()) { FileSystem fs = FileSystem.Create(io); fs.Flush(); ClusterState[] clusterStateArray = new ClusterState[Configuration.Geometry.DataClustersPerTrack * Configuration.Geometry.TrackCount]; for (int i = 0; i < clusterStateArray.Length; i++) { if ((fs.GetClusterState(i) & ClusterState.System) == 0) { ClusterState c = (ClusterState)r.Next(16); clusterStateArray[i] = c; fs.SetClusterState(i, c); } else { clusterStateArray[i] = fs.GetClusterState(i); } } int[] nextClusterArray = new int[Configuration.Geometry.DataClustersPerTrack * Configuration.Geometry.TrackCount]; for (int i = 0; i < nextClusterArray.Length; i++) { if ((fs.GetClusterState(i) & ClusterState.System) == 0) { int c = r.Next(); nextClusterArray[i] = c; fs.SetNextClusterAddress(i, c); } else { nextClusterArray[i] = fs.GetNextClusterAddress(i); } } int[] bytesUsedArray = new int[Configuration.Geometry.DataClustersPerTrack * Configuration.Geometry.TrackCount]; for (int i = 0; i < bytesUsedArray.Length; i++) { if ((fs.GetClusterState(i) & ClusterState.System) == 0) { int c = r.Next(); bytesUsedArray[i] = c; fs.SetBytesUsed(i, c); } else { bytesUsedArray[i] = fs.GetBytesUsed(i); } } DateTime[] verifyTimeArray = new DateTime[Configuration.Geometry.ClustersPerTrack * Configuration.Geometry.TrackCount]; for (int i = 0; i < verifyTimeArray.Length; i++) { if (i >= Configuration.Geometry.DataClustersPerTrack * Configuration.Geometry.TrackCount || (fs.GetClusterState(i) & ClusterState.System) == 0) { DateTime c = new DateTime(r.Next()); verifyTimeArray[i] = c; fs.SetVerifyTime(i, c); } else { verifyTimeArray[i] = fs.GetVerifyTime(i); } } fs.Dispose(); string volumeName = Configuration.VolumeName; Geometry geometry = Configuration.Geometry; CryptoSettings cryptoSettings = Configuration.CryptoSettings; Options options = Configuration.Options; Guid guid = Configuration.FileSystemID; Configuration.Reset(); Configuration.CryptoSettings = cryptoSettings; Configuration.Options = options; fs = FileSystem.Mount(io); Assert.AreEqual(volumeName, Configuration.VolumeName); Assert.AreEqual(geometry, Configuration.Geometry); Assert.AreEqual(guid, Configuration.FileSystemID); for (int i = 0; i < clusterStateArray.Length; i++) { Assert.AreEqual(clusterStateArray[i], fs.GetClusterState(i)); } for (int i = 0; i < nextClusterArray.Length; i++) { Assert.AreEqual(nextClusterArray[i], fs.GetNextClusterAddress(i)); } for (int i = 0; i < bytesUsedArray.Length; i++) { Assert.AreEqual(bytesUsedArray[i], fs.GetBytesUsed(i)); } for (int i = 0; i < verifyTimeArray.Length; i++) { Assert.AreEqual(verifyTimeArray[i], fs.GetVerifyTime(i)); } fs.Dispose(); } }
public ChannelTests(ITestOutputHelper logger) { this.logger = new Mocks.LoggerMock(logger); this.desktopCryptoProvider = TestUtilities.CreateAuthenticCryptoProvider(); }
public void FileSystemPopulate() { ConfigurationTest.Initialize(); Random r = new Random(1234); using (var io = ConfigurationTest.CreateMemoryIO()) { FileSystem fs = FileSystem.Create(io); fs.Flush(); SortedList <int, DirInfo> dirs = new SortedList <int, DirInfo>(); SortedList <int, FileInfo> files = new SortedList <int, FileInfo>(); Directory d = fs.RootDirectory; dirs.Add(fs.RootDirectory.ID, new DirInfo(d)); for (int i = 0; i < 1000; i++) { var parent = dirs.Values[r.Next(dirs.Count)]; d = fs.CreateDirectory(parent.Directory, $"dir{nextID}"); nextID++; DirInfo info = new DirInfo(d); dirs.Add(d.ID, info); dirs[d.ParentID].Subdirs.Add(d.ID); FileSystemAccessRule accessRule = new FileSystemAccessRule( WindowsIdentity.GetCurrent().User, FileSystemRights.FullControl, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow); fs.AddAccessRule(d, accessRule); info.AccessRules.Add(accessRule); FileSystemAuditRule auditRule = new FileSystemAuditRule( WindowsIdentity.GetCurrent().User, FileSystemRights.FullControl, InheritanceFlags.None, PropagationFlags.None, AuditFlags.Success); fs.AddAuditRule(d, auditRule); info.AuditRules.Add(auditRule); } for (int i = 0; i < 1000; i++) { var parent = dirs.Values[r.Next(dirs.Count)]; File f = fs.CreateFile(parent.Directory, $"file{nextID}"); nextID++; FileInfo info = new FileInfo(f); files.Add(f.ID, info); dirs[f.ParentID].Files.Add(f.ID); FileSystemAccessRule accessRule = new FileSystemAccessRule( WindowsIdentity.GetCurrent().User, FileSystemRights.FullControl, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow); fs.AddAccessRule(f, accessRule); info.AccessRules.Add(accessRule); FileSystemAuditRule auditRule = new FileSystemAuditRule( WindowsIdentity.GetCurrent().User, FileSystemRights.FullControl, InheritanceFlags.None, PropagationFlags.None, AuditFlags.Success); fs.AddAuditRule(f, auditRule); info.AuditRules.Add(auditRule); } checkDirectories(fs, fs.RootDirectory, dirs, files); fs.Dispose(); CryptoSettings cryptoSettings = Configuration.CryptoSettings; Options options = Configuration.Options; Configuration.Reset(); Configuration.CryptoSettings = cryptoSettings; Configuration.Options = options; fs = FileSystem.Mount(io); checkDirectories(fs, fs.RootDirectory, dirs, files); } }
/// <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); }
private async Task <IReadOnlyCollection <Channel.PayloadReceipt> > ReceiveMessageAsync(Mocks.CloudBlobStorageProviderMock cloudBlobStorage, Mocks.InboxHttpHandlerMock inboxMock, CryptoSettings cryptoProvider, OwnEndpoint receiver, bool expectMessage = true) { Requires.NotNull(cloudBlobStorage, "cloudBlobStorage"); Requires.NotNull(receiver, "receiver"); var httpHandler = new Mocks.HttpMessageHandlerMock(); cloudBlobStorage.AddHttpHandler(httpHandler); inboxMock.Register(httpHandler); var channel = new Channel { HttpClient = new HttpClient(httpHandler), HttpClientLongPoll = new HttpClient(httpHandler), CloudBlobStorage = cloudBlobStorage, CryptoServices = cryptoProvider, Endpoint = receiver, Logger = this.logger, }; var progressMessage = new TaskCompletionSource <Payload>(); var progress = new Progress <Channel.PayloadReceipt>(m => progressMessage.SetResult(m.Payload)); var messages = await channel.ReceiveAsync(progress : progress); if (expectMessage) { Assert.Equal(1, messages.Count); await progressMessage.Task; Assert.Same(progressMessage.Task.Result, messages.Single().Payload); } else { Assert.Equal(0, messages.Count); } return(messages); }