private void HandleEncryption(EncryptionRequestPacket packet) { var random = RandomNumberGenerator.Create(); _sharedSecret = new byte[16]; random.GetBytes(_sharedSecret); if (packet.ServerId != "") { throw new NotImplementedException("Online mode is not implemented"); } var parser = new AsnKeyParser(packet.PublicKey); var key = parser.ParseRSAPublicKey(); // Encrypt shared secret and verification token var crypto = new RSACryptoServiceProvider(); crypto.ImportParameters(key); WritePacket(new EncryptionResponsePacket { SharedSecret = crypto.Encrypt(_sharedSecret, false), VerifyToken = crypto.Encrypt(packet.VerifyToken, false), }); _baseStream = new AesStream(_networkStream, _sharedSecret); _writer = new MinecraftStreamWriter(_baseStream); _reader = new MinecraftStreamReader(_baseStream); }
/// <summary> /// Compose and send an encryption request packet to the server /// </summary> private void SendEncryptionRequest() { // Create the encryption request packet EncryptionRequestPacket packet = new EncryptionRequestPacket(); // Add the game packet handlers AddGamePacketHandler(0x00, new SessionPacketHandler(SpecialPacketReceiveHandler)); // Add the special packet handlers AddSpecialPacketHandler(0x02, new SessionPacketHandler(HandleEncryptionResponse)); AddSpecialPacketHandler(0x05, new SessionPacketHandler(HandleSynchronizeRequest)); AddSpecialPacketHandler(0x07, new SessionPacketHandler(HandleDisconnect)); // Log the connection message m_sessionLogger(String.Format("Connecting to {0}:{1}", m_sessionSettings.ServerAddress, m_sessionSettings.ServerPort)); // Set the client encryption key value packet.EncryptionKey = m_sessionSocket.ClientEncryptKey; // Send the packet to the server TransmitPacket(packet); }
private void HandleEncryptionRequest(EncryptionRequestPacket packet) { var generator = new CipherKeyGenerator(); generator.Init(new KeyGenerationParameters(new SecureRandom(), 16 * 8)); var sharedKey = generator.GenerateKey(); var pkcs = new PKCS1Signer(packet.PublicKey); var signedSecret = pkcs.SignData(sharedKey); var signedVerify = pkcs.SignData(packet.VerificationToken); SendPacketDirect(new EncryptionResponsePacket { SharedSecret = signedSecret, VerificationToken = signedVerify }); Stream.InitializeEncryption(sharedKey); State |= JoinState.JoinedGame; }
/// <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 }); }