private bool StartEncrypt() { CryptoHandler crypto = new CryptoHandler(); List <byte> encryptionRequest = new List <byte>(); string serverID = ""; if (protocol.protocolVersion < MCVersion.MC172Version) { serverID = "lilium-pre"; } encryptionRequest.AddRange(getString(serverID)); encryptionRequest.AddRange(getArray(crypto.getPublic())); byte[] token = new byte[4]; var rng = new System.Security.Cryptography.RNGCryptoServiceProvider(); rng.GetBytes(token); encryptionRequest.AddRange(getArray(token)); SendPacket(0x01, encryptionRequest); List <byte> encryptResponse = new List <byte>(readDataRAW(readNextVarIntRAW())); if (readNextVarInt(encryptResponse) == 0x01) { List <byte> dec = new List <byte>(); dec.AddRange(crypto.Decrypt(readNextByteArray(encryptResponse))); dec.RemoveRange(0, dec.Count - 16); byte[] key_dec = dec.ToArray(); byte[] token_dec = token; EncStream = CryptoHandler.getAesStream(Client.GetStream(), key_dec); this.encrypted = true; return(true); } return(false); }
/// <summary> /// Read a specified clipboard data, encrypt and save it into a file. /// </summary> /// <param name="clipboardReader">The <see cref="ClipboardReader"/> used to read the data.</param> /// <param name="identifier">The data identifier.</param> /// <param name="clipboardDataPath">The full path to the clipboard data folder.</param> private void WriteClipboardDataToFile(ClipboardReader clipboardReader, DataIdentifier identifier, string clipboardDataPath) { Requires.NotNull(clipboardReader, nameof(clipboardReader)); Requires.NotNull(identifier, nameof(identifier)); Requires.NotNullOrWhiteSpace(clipboardDataPath, nameof(clipboardDataPath)); var dataFilePath = Path.Combine(clipboardDataPath, $"{identifier.Identifier}.dat"); if (File.Exists(dataFilePath)) { Logger.Instance.Fatal(new FileLoadException($"The file {dataFilePath} already exists.")); } var dataPassword = SecurityHelper.ToSecureString(SecurityHelper.EncryptString(SecurityHelper.ToSecureString(identifier.Identifier.ToString()))); Requires.NotNull(dataPassword, nameof(dataPassword)); clipboardReader.BeginRead(identifier.FormatName); Requires.IsTrue(clipboardReader.IsReadable); Requires.IsTrue(clipboardReader.CanReadNextBlock()); using (var fileStream = File.OpenWrite(dataFilePath)) using (var aesStream = new AesStream(fileStream, dataPassword, SecurityHelper.GetSaltKeys(dataPassword).GetBytes(16))) { aesStream.AutoDisposeBaseStream = false; while (clipboardReader.CanReadNextBlock()) { var buffer = clipboardReader.ReadNextBlock(); aesStream.Write(buffer, 0, buffer.Length); } aesStream.Position = 0; } clipboardReader.EndRead(); }
public void Save(Stream stream) { EndianReader writer = new EndianReader(stream, Endianness.BigEndian); Bk.Save(stream); writer.PadToMultiple(0x40); TMD.Save(stream); writer.PadToMultiple(0x40); if (RawData != null) { RawData.Position = 0; Util.StreamCopy(stream, RawData); } else if (Content != null) { byte[] iv = new byte[0x10]; BigEndianConverter.GetBytes(Content.Index).CopyTo(iv, 0); AesStream astream = new AesStream(stream, Key, iv); Data.Position = 0; Util.StreamCopy(astream, Data); astream.Close(); } writer.PadToMultiple(0x40); }
/// <summary> /// Upload the specified data file to the cloud storage service. /// </summary> /// <param name="clipboardDataPath">The full path to the clipboard data folder.</param> /// <param name="cloudFolder">The <see cref="CloudFolder"/> that contains informations about the application folder.</param> /// <param name="cloudDataPassword">The supposed password that we will use to encrypt the data before uploading it to the cloud.</param> /// <param name="dataIdentifier">The data identifier used to determines which file will be uploaded.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> private async Task UploadDataFileAsync(string clipboardDataPath, CloudFolder cloudFolder, SecureString cloudDataPassword, DataIdentifier dataIdentifier) { var dataService = ServiceLocator.GetService <DataService>(); var fileName = $"{dataIdentifier.Identifier}.dat"; var cloudDataFilePath = Path.Combine(cloudFolder.FullPath, fileName); var localDataFilePath = Path.Combine(clipboardDataPath, fileName); var temporaryLocalDataFilePath = Path.Combine(clipboardDataPath, $"{fileName}.temp"); var localDataPassword = SecurityHelper.ToSecureString(SecurityHelper.EncryptString(SecurityHelper.ToSecureString(dataIdentifier.Identifier.ToString()))); Requires.NotNull(localDataPassword, nameof(localDataPassword)); if (!File.Exists(localDataFilePath)) { Logger.Instance.Warning($"Data file {dataIdentifier.Identifier} not found locally, it has probably been removed while synchronizing."); return; } using (var fileStream = File.OpenRead(localDataFilePath)) using (var temporaryLocalFileStream = File.Open(temporaryLocalDataFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite)) using (var localAesStream = new AesStream(fileStream, localDataPassword, SecurityHelper.GetSaltKeys(localDataPassword).GetBytes(16))) using (var cloudAesStream = new AesStream(temporaryLocalFileStream, cloudDataPassword, SecurityHelper.GetSaltKeys(cloudDataPassword).GetBytes(16))) { dataService.CopyData(localAesStream, cloudAesStream); await CurrentCloudStorageProvider.UploadFileAsync(temporaryLocalFileStream, cloudDataFilePath); } if (File.Exists(temporaryLocalDataFilePath)) { File.Delete(temporaryLocalDataFilePath); } }
private async Task <MemoryStream> ReadFileFromServerAsync(string filePath) { var cloudStorageProviderMock = GetCloudStorageProviderMock(); if (File.Exists(filePath)) { var password = await GetCloudDataPasswordAsync(); var result = new MemoryStream(); using (var temporaryLocalFileStream = new MemoryStream()) { await cloudStorageProviderMock.DownloadFileAsync(filePath, temporaryLocalFileStream); temporaryLocalFileStream.Position = 0; using (var cloudAesStream = new AesStream(temporaryLocalFileStream, password, SecurityHelper.GetSaltKeys(password).GetBytes(16))) { CopyStream(cloudAesStream, result); } } return(result); } return(null); }
/// <summary> /// Write a specified clipboard data from an encrypted file. /// </summary> /// <param name="clipboardWriter">The <see cref="ClipboardWriter"/> used to write the data.</param> /// <param name="identifier">The data identifier.</param> /// <param name="clipboardDataPath">The full path to the clipboard data folder.</param> private void ReadFileToClipboardData(ClipboardWriter clipboardWriter, DataIdentifier identifier, string clipboardDataPath) { Requires.NotNull(clipboardWriter, nameof(clipboardWriter)); Requires.NotNull(identifier, nameof(identifier)); Requires.NotNullOrWhiteSpace(clipboardDataPath, nameof(clipboardDataPath)); var dataFilePath = Path.Combine(clipboardDataPath, $"{identifier.Identifier}.dat"); if (!File.Exists(dataFilePath)) { return; } var dataPassword = SecurityHelper.ToSecureString(SecurityHelper.EncryptString(SecurityHelper.ToSecureString( identifier.Identifier.ToString( )))); Requires.NotNull(dataPassword, nameof(dataPassword)); var fileStream = File.OpenRead(dataFilePath); var aesStream = new AesStream(fileStream, dataPassword, SecurityHelper.GetSaltKeys(dataPassword).GetBytes(16)); clipboardWriter.AddData(identifier.FormatName, aesStream, fileStream); }
public void Encrypt_Decrypt_Stream() { using (var media = new MemoryStream()) using (var crypto = new AesStream("abc", media)) { var input0 = new byte[8192]; var input1 = new byte[8192]; var input2 = new byte[8192]; var output0 = new byte[8192]; var output1 = new byte[8192]; var output2 = new byte[8192]; input0.Fill(100, 0, 8192); input1.Fill(101, 0, 8192); input2.Fill(102, 0, 8192); // write 0, 2, 1 but in order 0, 1, 2 crypto.Position = 0 * 8192; crypto.Write(input0, 0, 8192); crypto.Position = 2 * 8192; crypto.Write(input2, 0, 8192); crypto.Position = 1 * 8192; crypto.Write(input1, 0, 8192); // read encrypted data media.Position = 0; media.Read(output0, 0, 8192); media.Read(output1, 0, 8192); media.Read(output2, 0, 8192); Assert.IsFalse(output0.All(x => x == 100)); Assert.IsFalse(output1.All(x => x == 101)); Assert.IsFalse(output2.All(x => x == 102)); // read decrypted data crypto.Position = 0 * 8192; crypto.Read(output0, 0, 8192); crypto.Position = 2 * 8192; crypto.Read(output2, 0, 8192); crypto.Position = 1 * 8192; crypto.Read(output1, 0, 8192); Assert.IsTrue(output0.All(x => x == 100)); Assert.IsTrue(output1.All(x => x == 101)); Assert.IsTrue(output2.All(x => x == 102)); } }
public bool SwitchToEncrypted(string serverID, byte[] Serverkey, byte[] token) { if (ServerData.OnlineMode) { var crypto = CryptoHandler.DecodeRSAPublicKey(Serverkey); byte[] secretKey = CryptoHandler.GenerateAESPrivateKey(); byte[] key_enc = crypto.Encrypt(secretKey, false); byte[] token_enc = crypto.Encrypt(token, false); //Console.WriteLine(key_enc.Length + " " + token_enc.Length); SendPacket(0x01, concatBytes(getArray(key_enc), getArray(token_enc))); this.s = CryptoHandler.getAesStream(c.GetStream(), secretKey); encrypted = true; int packetID = -1; List <byte> packetData = new List <byte>(); while (true) { readNextPacket(ref packetID, packetData); if (packetID == 0x00) { handler.OnConnectionLost(Conn.DisconnectReason.LoginRejected, readNextString(packetData)); return(false); } else if (packetID == 0x02)//Logined { Debug.Log("Login Success"); login_phase = false; handler.OnLogin(packetData); StartUpdating(); return(true); } else { if (packetID == 0x03 && login_phase) { if (protocolversion >= MCVersion.MC18Version) { compression_treshold = readNextVarInt(packetData); } } handler.receivePacket(packetID, packetData); } } } else { handler.OnConnectionLost(Conn.DisconnectReason.LoginRejected, ServerData.MsgEncryptReject); } return(false); }
public void AesStreamRead() { var cryptedData = new byte[] { 238, 75, 117, 248, 55 }; var password = SecurityHelper.ToSecureString("MyPassword"); using (var baseStream = new MemoryStream(cryptedData)) using (var aesStream = new AesStream(baseStream, password, SecurityHelper.GetSaltKeys(password).GetBytes(16))) { var data = new byte[aesStream.Length]; aesStream.Read(data, 0, data.Length); Assert.IsTrue(data.ToArray().SequenceEqual(new byte[] { 72, 101, 108, 108, 111 })); Assert.AreEqual(Encoding.ASCII.GetString(data), "Hello"); } }
public void TestAesStream() { var baseStream = new MemoryStream(); var key = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; var encryptStream = new AesStream(baseStream, key); var plaintext = Encoding.UTF8.GetBytes("Hello, world!"); encryptStream.Write(plaintext, 0, plaintext.Length); baseStream.Seek(0, SeekOrigin.Begin); var decryptStream = new AesStream(baseStream, key); byte[] buffer = new byte[plaintext.Length]; decryptStream.Read(buffer, 0, buffer.Length); Assert.AreEqual("Hello, world!", Encoding.UTF8.GetString(buffer)); }
public async Task TestEncryption(byte[] testData) { var random = new Random(); var sharedKey = new byte[32]; random.NextBytes(sharedKey); await using var memoryStream = new MemoryStream(); await using var stream = new AesStream(memoryStream, sharedKey); await stream.WriteAsync(testData); memoryStream.Position = 0; var incomingRandomData = new byte[testDataLength]; await stream.ReadAsync(incomingRandomData, 0, incomingRandomData.Length); Assert.Equal(testData, incomingRandomData); }
private async Task <List <CloudDataEntry> > GetDataEntriesFromServerAsync() { var cloudStorageProviderMock = GetCloudStorageProviderMock(); if (Directory.Exists(cloudStorageProviderMock.TemporaryFolder)) { using (var memoryStream = new MemoryStream()) { await cloudStorageProviderMock.DownloadFileAsync(cloudStorageProviderMock.TemporaryFolder + @"\.clipboard", memoryStream); var cloudDataPassword = await GetCloudDataPasswordAsync(); using (var aesStream = new AesStream(memoryStream, cloudDataPassword, SecurityHelper.GetSaltKeys(cloudDataPassword).GetBytes(16))) { var data = new byte[aesStream.Length]; aesStream.Read(data, 0, data.Length); return(JsonConvert.DeserializeObject <List <CloudDataEntry> >(Encoding.UTF8.GetString(data))); } } } return(null); }
/// <summary> /// Force to synchronize that data with the cloud. /// </summary> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> internal async Task SynchronizeAsync() { if (IsSynchronizing) { return; } Logger.Instance.Information("Synchronization with the cloud started."); IsSynchronizing = true; if (CurrentCloudStorageProvider == null) { Logger.Instance.Warning("The user is not logged to any cloud storage provider. The synchronization stopped."); IsSynchronizing = false; return; } if (!CoreHelper.IsUnitTesting() && !SystemInfoHelper.CheckForInternetConnection()) { Logger.Instance.Warning("There is no internet connection. The synchronization stopped."); IsSynchronizing = false; return; } SynchronizationStarted?.Invoke(this, new EventArgs()); try { if (!await CurrentCloudStorageProvider.TryAuthenticateAsync()) { Logger.Instance.Warning("The user is not authenticated correctly. Consider unlink the app and connect again. The synchronization stopped."); IsSynchronizing = false; SynchronizationEnded?.Invoke(this, new EventArgs()); return; } var userId = SecurityHelper.ToSecureString(await CurrentCloudStorageProvider.GetUserIdAsync()); if (string.IsNullOrWhiteSpace(SecurityHelper.ToUnsecureString(userId))) { Logger.Instance.Warning("The user's id from the cloud storage provider has not been found. The synchronization stopped."); IsSynchronizing = false; SynchronizationEnded?.Invoke(this, new EventArgs()); SynchronizationFailed?.Invoke(this, new EventArgs()); return; } Logger.Instance.Information("Freezing the data before synchronize."); var dataService = ServiceLocator.GetService <DataService>(); var cloudDataEntryFromServer = new List <CloudDataEntry>(); var cloudAppFolder = await CurrentCloudStorageProvider.GetAppFolderAsync(); var cloudDataEntryFilePath = Path.Combine(cloudAppFolder.FullPath, Consts.DataEntryFileName); var cloudDataPassword = SecurityHelper.ToSecureString(SecurityHelper.EncryptString(userId, SecurityHelper.ToSecureString(await CurrentCloudStorageProvider.GetUserNameAsync()))); var localFrozenDataEntries = DataHelper.FromByteArray <AsyncObservableCollection <DataEntry> >(DataHelper.ToByteArray(dataService.DataEntries)); var localFrozenCache = DataHelper.FromByteArray <List <DataEntryCache> >(DataHelper.ToByteArray(dataService.Cache)); // Download data from server. if (cloudAppFolder.Files.Any(file => file.FullPath == cloudDataEntryFilePath)) { Logger.Instance.Information("Downloading the data entry file from the server."); try { using (var memoryStream = new MemoryStream()) { await CurrentCloudStorageProvider.DownloadFileAsync(cloudDataEntryFilePath, memoryStream); memoryStream.Position = 0; using (var aesStream = new AesStream(memoryStream, cloudDataPassword, SecurityHelper.GetSaltKeys(cloudDataPassword).GetBytes(16))) { var data = new byte[aesStream.Length]; aesStream.Read(data, 0, data.Length); cloudDataEntryFromServer = JsonConvert.DeserializeObject <List <CloudDataEntry> >(Encoding.UTF8.GetString(data)); } } } catch (Exception exception) { Logger.Instance.Warning($"Unable to download or read the data file entry from the cloud for the following reason : {exception.Message}"); IsSynchronizing = false; SynchronizationEnded?.Invoke(this, new EventArgs()); SynchronizationFailed?.Invoke(this, new EventArgs()); return; } } else { Logger.Instance.Information("There is no data entry file on the server yet."); } // Synchronize locally the data. The result must corresponds to what we will have locally and on the server at the end of the synchronization process. var cloudDataEntryToServer = dataService.DifferenceLocalAndCloudDataEntries(cloudDataEntryFromServer); // Download the needed data from the server to the local machine. Logger.Instance.Information("Downloading the needed data from the server to the local machine."); var dataToDownload = cloudDataEntryFromServer.Cast <DataEntryBase>().Except(localFrozenDataEntries, (item1, item2) => item1.Identifier == item2.Identifier).ToList(); var taskList = new List <Task>(); foreach (var cloudDataEntry in dataToDownload) { if (dataToDownload.Any(data => localFrozenCache.Any(item => data.Identifier == item.Identifier && item.Status == DataEntryStatus.Deleted))) { continue; } foreach (var dataEntryDataIdentifier in cloudDataEntry.DataIdentifiers) { var task = DownloadDataFileAsync(dataService.ClipboardDataPath, cloudAppFolder, cloudDataPassword, dataEntryDataIdentifier); taskList.Add(task); } } await Task.WhenAll(taskList); // Delete the needed data from the server Logger.Instance.Information("Deleting the needed data from the server."); taskList = new List <Task>(); foreach (var dataServiceDataEntry in localFrozenDataEntries.Where(item => !item.CanSynchronize)) { foreach (var dataEntryDataIdentifier in dataServiceDataEntry.DataIdentifiers) { var task = DeleteFileAsync(cloudAppFolder, dataEntryDataIdentifier); taskList.Add(task); } } await Task.WhenAll(taskList); taskList = new List <Task>(); foreach (var cacheEntry in localFrozenCache.Where(item => item.Status == DataEntryStatus.Deleted)) { var dataEntry = cloudDataEntryFromServer.SingleOrDefault(item => item.Identifier == cacheEntry.Identifier); if (dataEntry != null) { foreach (var dataEntryDataIdentifier in dataEntry.DataIdentifiers) { var task = DeleteFileAsync(cloudAppFolder, dataEntryDataIdentifier); taskList.Add(task); } } } await Task.WhenAll(taskList); await dataService.MakeCacheSynchronized(cloudDataEntryToServer, true, localFrozenCache); localFrozenDataEntries = DataHelper.FromByteArray <AsyncObservableCollection <DataEntry> >(DataHelper.ToByteArray(dataService.DataEntries)); localFrozenCache = DataHelper.FromByteArray <List <DataEntryCache> >(DataHelper.ToByteArray(dataService.Cache)); // Upload the needed data from the server to the local machine Logger.Instance.Information("Uploading the needed data from the server to the local machine."); var dataToUpload = localFrozenDataEntries.Cast <DataEntryBase>().Except(cloudDataEntryFromServer, (item1, item2) => item1.Identifier == item2.Identifier); taskList = new List <Task>(); foreach (var dataEntry in dataToUpload) { var localDataEntry = localFrozenDataEntries.Single(item => item.Identifier == dataEntry.Identifier); if (!localDataEntry.CanSynchronize || localDataEntry.Thumbnail.Type == ThumbnailDataType.Files) { continue; } foreach (var dataEntryDataIdentifier in dataEntry.DataIdentifiers) { var task = UploadDataFileAsync(dataService.ClipboardDataPath, cloudAppFolder, cloudDataPassword, dataEntryDataIdentifier); taskList.Add(task); } } await Task.WhenAll(taskList); // Upload the new data to the server. Logger.Instance.Information("Uploading the data entry file to the server."); using (var memoryStream = new MemoryStream()) using (var aesStream = new AesStream(memoryStream, cloudDataPassword, SecurityHelper.GetSaltKeys(cloudDataPassword).GetBytes(16))) { var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(cloudDataEntryToServer)); aesStream.Write(data, 0, data.Length); aesStream.Position = 0; await CurrentCloudStorageProvider.UploadFileAsync(memoryStream, cloudDataEntryFilePath); } await dataService.MakeCacheSynchronized(cloudDataEntryToServer, false, localFrozenCache); } catch (Exception exception) { Logger.Instance.Warning($"Unable to synchronize for the following reason : {exception.Message}. {exception.InnerException?.Message}"); SynchronizationFailed?.Invoke(this, new EventArgs()); } _synchronizeTimer.Stop(); _synchronizeTimer.Start(); IsSynchronizing = false; SynchronizationEnded?.Invoke(this, new EventArgs()); }
/// <summary> /// Gets the next packet from the server /// </summary> /// <returns></returns> public PacketData ReadNextPacket() { int packetId; byte[] payload; lock (_streamReadLock) { int length = VarInt.ReadNext(ReadBytes); List <byte> buffer = new List <byte>(); // check if data is compressed if (_compressionThreshold >= 0) { int dataLength = VarInt.ReadNext(ReadBytes); length -= VarInt.GetBytes(dataLength).Length; // remove size of data length from rest of packet length if (dataLength != 0) { byte[] compressedBuffer = ReadBytes(length); buffer.AddRange(ZlibStream.UncompressBuffer(compressedBuffer)); } else { buffer.AddRange(ReadBytes(length)); } } else { buffer.AddRange(ReadBytes(length)); } packetId = VarInt.ReadNext(buffer); payload = buffer.ToArray(); } // handles some stuff during login phase if (State == ProtocolState.LOGIN) { // handle compression packet if (packetId == (int)ClientboundIDs.LogIn_SetCompression) { _compressionThreshold = VarInt.ReadNext(new List <byte>(payload)); return(ReadNextPacket()); } // handle protocol encryption packet if (packetId == (int)ClientboundIDs.LogIn_EncryptionRequest) { var encRequestPkt = new EncryptionRequestPacket() { Payload = payload }; var aesSecret = CryptoHandler.GenerateSharedSecret(); var authHash = CryptoHandler.SHAHash(Encoding.ASCII.GetBytes(encRequestPkt.ServerID).Concat(aesSecret, encRequestPkt.PublicKey)); Debug.Log($"Sending hash to Mojang servers: {authHash}"); // check session with mojang if (!MojangAPI.JoinServer(authHash)) { throw new UnityException("Invalid session. (Try restarting game or relogging into Minecraft account)"); } // use pub key to encrypt shared secret using (var rsaProvider = CryptoHandler.DecodeRSAPublicKey(encRequestPkt.PublicKey)) { byte[] encSecret = rsaProvider.Encrypt(aesSecret, false); byte[] encToken = rsaProvider.Encrypt(encRequestPkt.VerifyToken, false); // respond to server with private key var responsePkt = new EncryptionResponsePacket() { SharedSecret = encSecret, VerifyToken = encToken }; WritePacket(responsePkt); // enable aes encryption _aesStream = new AesStream(Client.GetStream(), aesSecret); _encrypted = true; // read the next packet return(ReadNextPacket()); } } } return(new PacketData { ID = packetId, Payload = payload }); }