/// <summary> /// Serialize the Message to output stream /// </summary> /// <param name="message"></param> /// <param name="TargetStream"></param> /// <returns>The size of the serialzed message</returns> internal int EncryptMessage(Connection conn, IMessage message, MemoryStream TargetStream) { PayloadWriter pw = new PayloadWriter(TargetStream); int PayloadPos = pw.Position; Serializer.Serialize(TargetStream, message); //return (int)TargetStream.Length; #region Security //compress data if (CompressionAlgorithm.QuickLZ == (conn.CompressionAlgorithm & CompressionAlgorithm.QuickLZ)) { UnsafeQuickLZ quickLz = new UnsafeQuickLZ(); byte[] compressed = quickLz.compress(TargetStream.GetBuffer(), (uint)Connection.HEADER_SIZE, (uint)TargetStream.Length - Connection.HEADER_SIZE); if (compressed != null && compressed.Length + Connection.HEADER_SIZE < TargetStream.Length) //only apply compression if it's smaller then the original data { TargetStream.Position = Connection.HEADER_SIZE; TargetStream.Write(compressed, 0, compressed.Length); if (TargetStream.Length != compressed.Length + Connection.HEADER_SIZE) { TargetStream.SetLength(compressed.Length + Connection.HEADER_SIZE); } } } //encrypt all the data if (EncAlgorithm.HwAES == (conn.EncryptionAlgorithm & EncAlgorithm.HwAES)) { lock (conn.EncAES) { //no need to re-size the stream here, AES will encrypt at the same size or bigger then the stream, so data will be overwritten byte[] encrypted = conn.EncAES.Encrypt(TargetStream.GetBuffer(), Connection.HEADER_SIZE, (int)TargetStream.Length - Connection.HEADER_SIZE); TargetStream.Position = Connection.HEADER_SIZE; TargetStream.Write(encrypted, 0, encrypted.Length); } } if (EncAlgorithm.WopEx == (conn.EncryptionAlgorithm & EncAlgorithm.WopEx)) { lock (conn.PayloadEncryption) { conn.PayloadEncryption.Encrypt(TargetStream.GetBuffer(), Connection.HEADER_SIZE, (int)TargetStream.Length - Connection.HEADER_SIZE); } } #endregion return(pw.Length - PayloadPos); }
private UnsafeQuickLZ quickLz; //change to safe or unsafe public QuickLzProtection() : base() { this.quickLz = new UnsafeQuickLZ(); }
/// <summary> /// Save the changes and apply Header Information /// </summary> public void Commit(Connection conn) { bool UseFragments = PayloadFrames.Count > 1; int FullLength = 0; byte FragmentId = (byte)(UseFragments ? 1 : 0); //count all the payload, this is the original size for (int i = 0; i < PayloadFrames.Count; i++) { FullLength += (int)PayloadFrames[i].Length - Connection.HEADER_SIZE; } #region Encryption & Compression //compress all the data for (int i = 0; i < PayloadFrames.Count; i++) { MemoryStream stream = PayloadFrames[i]; if (CompressionAlgorithm.QuickLZ == (conn.CompressionAlgorithm & CompressionAlgorithm.QuickLZ)) { UnsafeQuickLZ quickLz = new UnsafeQuickLZ(); byte[] compressed = quickLz.compress(stream.GetBuffer(), (uint)Connection.HEADER_SIZE, (uint)stream.Length - Connection.HEADER_SIZE); if (compressed != null && compressed.Length + Connection.HEADER_SIZE < stream.Length) //only apply compression if it's smaller then the original data { stream.Position = Connection.HEADER_SIZE; stream.Write(compressed, 0, compressed.Length); if (stream.Length != compressed.Length + Connection.HEADER_SIZE) { stream.SetLength(compressed.Length + Connection.HEADER_SIZE); } } } } //encrypt all the data for (int i = 0; i < PayloadFrames.Count; i++) { MemoryStream stream = PayloadFrames[i]; if (EncAlgorithm.HwAES == (conn.EncryptionAlgorithm & EncAlgorithm.HwAES)) { lock (conn.EncAES) { //no need to re-size the stream here, AES will encrypt at the same size or bigger then the stream, so data will be overwritten byte[] encrypted = conn.EncAES.Encrypt(stream.GetBuffer(), Connection.HEADER_SIZE, (int)stream.Length - Connection.HEADER_SIZE); stream.Position = Connection.HEADER_SIZE; stream.Write(encrypted, 0, encrypted.Length); } } if (EncAlgorithm.WopEx == (conn.EncryptionAlgorithm & EncAlgorithm.WopEx)) { lock (conn.PayloadEncryption) { conn.PayloadEncryption.Encrypt(stream.GetBuffer(), Connection.HEADER_SIZE, (int)stream.Length - Connection.HEADER_SIZE); } } } #endregion for (int i = 0; i < PayloadFrames.Count; i++) { PayloadWriter pw = new PayloadWriter(PayloadFrames[i]); pw.Position = 0; //if (pw.Length - Connection.HEADER_SIZE > ushort.MaxValue) // throw new OverflowException(); //should never happen if Write(...) is handled correctly ushort PayloadLength = (ushort)(pw.Length - Connection.HEADER_SIZE); byte CurPacketId = 0; int FeatureId = feature != null?feature.GetFeatureId() : -1; ushort ConnectionId = OpSocket != null ? OpSocket.ConnectionId : (ushort)0; if (i + 1 >= PayloadFrames.Count && UseFragments) { FragmentId += 128; } byte checksum = 0; checksum += (byte)PayloadLength; checksum += FragmentId; checksum += CurPacketId; checksum += (byte)ConnectionId; checksum += (byte)HeaderId; checksum += (byte)FullLength; checksum += (byte)FeatureId; pw.WriteUShort(PayloadLength); //length pw.WriteByte(CurPacketId); //cur packet id pw.WriteUShort(ConnectionId); //Connection Id pw.WriteUShort(HeaderId); //Header Id pw.WriteByte(FragmentId); pw.WriteByte(checksum); pw.WriteThreeByteInteger(FullLength); //the full packet size, mainly used for Fragmentation pw.WriteInteger(FeatureId); if (UseFragments) { FragmentId++; } } }