private BsonValue ExplicitDecrypt(
            ClientEncryption clientEncryption,
            BsonBinaryData value,
            bool async)
        {
            BsonValue decryptedValue;

            if (async)
            {
                decryptedValue = clientEncryption
                                 .DecryptAsync(
                    value,
                    CancellationToken.None)
                                 .GetAwaiter()
                                 .GetResult();
            }
            else
            {
                decryptedValue = clientEncryption.Decrypt(
                    value,
                    CancellationToken.None);
            }

            return(decryptedValue);
        }
Example #2
0
        protected override bool OnClientMessage(byte[] data)
        {
            switch (phase)
            {
            case Phase.Seed:
                if (data.Length != 4)
                {
                    throw new SocketException("Invalid seed lenght.", this, data);
                }

                Seed = ByteConverter.LittleEndian.ToUInt32(data, 0);
                Trace.WriteLine(String.Format("Game seed sent by client: {0}", Seed.ToString("X")), "Communication");

                SendToServer(data);
                phase = Phase.EncryptionDetection;
                return(true);

            case Phase.EncryptionDetection:
                CommunicationManager.ClientEncryption = DetectEncryption(data);

                Trace.WriteLine(String.Format("Client is using {0} encryption.", CommunicationManager.ClientEncryption), "Communication");
                ClientEncryption = UOEncryption.Encryption.CreateServerGame(CommunicationManager.ClientEncryption, Seed);

                CommunicationManager.ServerEncryption = GetServerEncryption(CommunicationManager.ClientEncryption);

                Trace.WriteLine(String.Format("Server is using {0} encryption.", CommunicationManager.ServerEncryption), "Communication");
                ServerEncryption = UOEncryption.Encryption.CreateClientGame(CommunicationManager.ServerEncryption, Seed);

                byte[] decrypted = ClientEncryption.Decrypt(data);

                SendToServer(decrypted);
                Core.OnClientMessage(decrypted, CallbackResult.Sent);

                phase = fixCharList ? Phase.CharacterList : Phase.Normal;
                return(true);

            case Phase.CharListSelect:
                if (data[0] != 0x5D)
                {
                    throw new Exception("Invalid packet received from client. Did you selected properly character from list?");
                }

                Trace.WriteLine("Character from fake list selected.", "Communication");

                SendPendingData();
                pendingData = null;
                phase       = Phase.Normal;
                return(true);
            }

            return(base.OnClientMessage(data));
        }
        public void ClientSideExplicitEncryptionAndDecryptionTour()
        {
            RequireServer.Check().Supports(Feature.ClientSideEncryption);

            var localMasterKey = Convert.FromBase64String(LocalMasterKey);

            var kmsProviders = new Dictionary <string, IReadOnlyDictionary <string, object> >();
            var localKey     = new Dictionary <string, object>
            {
                { "key", localMasterKey }
            };

            kmsProviders.Add("local", localKey);

            var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
            var keyVaultClient    = new MongoClient("mongodb://localhost");
            var keyVaultDatabase  = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName);

            keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);

            // Create the ClientEncryption instance
            var clientEncryptionSettings = new ClientEncryptionOptions(
                keyVaultClient,
                keyVaultNamespace,
                kmsProviders);

            using (var clientEncryption = new ClientEncryption(clientEncryptionSettings))
            {
                var dataKeyId = clientEncryption.CreateDataKey(
                    "local",
                    new DataKeyOptions(),
                    CancellationToken.None);

                var originalString = "123456789";
                _output.WriteLine($"Original string {originalString}.");

                // Explicitly encrypt a field
                var encryptOptions = new EncryptOptions(
                    EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
                    keyId: dataKeyId);
                var encryptedFieldValue = clientEncryption.Encrypt(
                    originalString,
                    encryptOptions,
                    CancellationToken.None);
                _output.WriteLine($"Encrypted value {encryptedFieldValue}.");

                // Explicitly decrypt the field
                var decryptedValue = clientEncryption.Decrypt(encryptedFieldValue, CancellationToken.None);
                _output.WriteLine($"Decrypted value {decryptedValue}.");
            }
        }
Example #4
0
        protected override bool OnClientMessage(byte[] data)
        {
            switch (phase)
            {
            case Phase.Seed:
                if (data.Length != 4)
                {
                    throw new SocketException("Error while initializing LoginSocket. Invalid seed lenght.", this, data);
                }

                // Seed comes in little endian and encryption alghortm expects it in little endian, so i keep it as it is.
                Seed = ByteConverter.LittleEndian.ToUInt32(data, 0);
                CommunicationManager.LoginSeed = Seed;

                SendToServer(data);
                phase = Phase.Keys;
                return(true);

            case Phase.Keys:
                if (data.Length != 62)
                {
                    throw new SocketException("Error while initializing LoginSocket. Invalid login packet lenght.", this, data);
                }


                // Detect and create client encryption
                uint key1;
                uint key2;
                LoginEncryptionType clientEnc = GetClientEncryption(data, out key1, out key2);
                ClientEncryption = Encryption.CreateServerLogin(clientEnc, Seed, key1, key2);


                // Read and create server encryption
                uint serverKey1;
                uint serverKey2;
                LoginEncryptionType serverEnc;


                int v = Int32.Parse(Core.LaunchData.ServerEncryption);

                switch (v)
                {
                case 0:
                    serverKey1 = 0;
                    serverKey2 = 0;
                    serverEnc  = LoginEncryptionType.None;
                    Trace.WriteLine("Using no server encryption.", "Communication");
                    break;

                case 1:
                    serverKey1 = key1;
                    serverKey2 = key2;
                    serverEnc  = clientEnc;
                    Trace.WriteLine(String.Format("Server key1: {1} key2: {2}", Seed.ToString("X"), serverKey1.ToString("X"), serverKey2.ToString("X")), "Communication");
                    break;

                default:
                    try {
                        serverKey1 = UInt32.Parse(Core.LaunchData.ServerKey1, System.Globalization.NumberStyles.HexNumber);
                        serverKey2 = UInt32.Parse(Core.LaunchData.ServerKey2, System.Globalization.NumberStyles.HexNumber);
                        serverEnc  = LoginEncryptionType.New;
                    }
                    catch (Exception e) {
                        throw new Exception("Error parsing server login keys.", e);
                    }
                    Trace.WriteLine(String.Format("Server key1: {1} key2: {2}", Seed.ToString("X"), serverKey1.ToString("X"), serverKey2.ToString("X")), "Communication");
                    break;
                }

                ServerEncryption = Encryption.CreateClientLogin(serverEnc, Seed, serverKey1, serverKey2);

                byte[] decrypted = ClientEncryption.Decrypt(data);

                // Save used account and password. They will be used to detect game encryprion.
                CommunicationManager.Username = ByteConverter.BigEndian.ToAsciiString(decrypted, 1, 30);
                CommunicationManager.Password = ByteConverter.BigEndian.ToAsciiString(decrypted, 31, 30);

                SendToServer(decrypted);

                // Zero password for security reasons
                for (int i = 31; i < 61; i++)
                {
                    decrypted[i] = 0;
                }

                Core.OnClientMessage(decrypted, CallbackResult.Sent);

                phase = Phase.Normal;
                return(true);
            }

            return(base.OnClientMessage(data));
        }