Index: Rhino.ServiceBus.Tests/Rhino.ServiceBus.Tests.csproj
===================================================================
--- Rhino.ServiceBus.Tests/Rhino.ServiceBus.Tests.csproj	(revision 2085)
+++ Rhino.ServiceBus.Tests/Rhino.ServiceBus.Tests.csproj	(working copy)
@@ -49,7 +49,7 @@
     </Reference>
     <Reference Include="Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\..\build\net-3.5\debug\Rhino.Mocks.dll</HintPath>
+      <HintPath>..\..\SharedLibs\Rhino\Rhino.Mocks.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
@@ -57,6 +57,9 @@
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
     </Reference>
     <Reference Include="System.Messaging" />
+    <Reference Include="System.Runtime.Serialization">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
     <Reference Include="System.Transactions" />
     <Reference Include="System.Xml.Linq">
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -121,6 +124,7 @@
     <Compile Include="SagaTests.cs" />
     <Compile Include="TestExtensions.cs" />
     <Compile Include="Warnings\Warnings_would_be_generated.cs" />
+    <Compile Include="When_custom_element_serialization_is_used.cs" />
     <Compile Include="When_Security_Is_Not_Specified_In_Config.cs" />
     <Compile Include="When_Security_Is_Specified_In_Config.cs" />
     <Compile Include="SendAndReceiveMessages.cs" />
Index: Rhino.ServiceBus.Tests/When_custom_element_serialization_is_used.cs
===================================================================
--- Rhino.ServiceBus.Tests/When_custom_element_serialization_is_used.cs	(revision 0)
+++ Rhino.ServiceBus.Tests/When_custom_element_serialization_is_used.cs	(revision 0)
@@ -0,0 +1,86 @@
+using System;
+using System.Runtime.Serialization;
+using System.Xml;
+using System.Xml.Linq;
+using Castle.Windsor;
+using Castle.Windsor.Configuration.Interpreters;
+using Rhino.ServiceBus.Impl;
+using Xunit;
+using Rhino.ServiceBus.Internal;
+using System.IO;
+using Castle.MicroKernel.Registration;
+
+namespace Rhino.ServiceBus.Tests
+{
+	public class When_custom_element_serialization_is_used
+	{
+		private IWindsorContainer container;
+
+		public When_custom_element_serialization_is_used()
+		{
+			container = new WindsorContainer(new XmlInterpreter());
+			container.AddFacility("rhino.esb", new RhinoServiceBusFacility());
+			container.Register(
+				Component.For<ICustomElementSerializer>()
+				.ImplementedBy<DataContractMessageElementSerializer>()
+				);
+		}
+
+		[Fact]
+		public void Can_serialize_custom_element_with_non_custom_element()
+		{
+			var serializer = container.Resolve<IMessageSerializer>();
+			var message1 = new NoDataContract {Value = "test"};
+			var message2 = new DataContractMessage {Message = "test2"};
+			message2.ContractMessage = message2;
+			var memoryStream = new MemoryStream();
+			serializer.Serialize(new object[]{message1, message2}, memoryStream);
+			memoryStream.Position = 0;
+			var messages = serializer.Deserialize(memoryStream);
+			var dataContractMessage = messages[1] as DataContractMessage;
+			Assert.NotNull(dataContractMessage);
+			Assert.Same(dataContractMessage, dataContractMessage.ContractMessage);
+		}
+
+		public class NoDataContract
+		{
+			public string Value { get; set; }
+		}
+
+		[DataContract(IsReference = true)]
+		public class DataContractMessage
+		{
+			[DataMember]
+			public string Message { get; set; }
+
+			[DataMember]
+			public DataContractMessage ContractMessage { get; set; }
+		}
+
+		public class DataContractMessageElementSerializer : ICustomElementSerializer
+		{
+			public bool CanSerialize(Type type)
+			{
+				return type == typeof (DataContractMessage);
+			}
+
+			public XElement ToElement(object val, Func<Type, XNamespace> getNamespace)
+			{
+				var serializer = new DataContractSerializer(val.GetType());
+				using (var ms = new MemoryStream())
+				{
+					serializer.WriteObject(ms, val);
+					ms.Seek(0, SeekOrigin.Begin);
+					return XElement.Load(new XmlTextReader(ms));
+				}
+			}
+
+			public object FromElement(Type type, XElement element)
+			{
+				var serializer = new DataContractSerializer(type);
+				var childElement = element.FirstNode.NextNode;
+				return serializer.ReadObject(XmlReader.Create(new StringReader(childElement.ToString())));
+			}
+		}
+	}
+}
\ No newline at end of file
Index: Rhino.ServiceBus.Tests/When_Security_Is_Not_Specified_In_Config.cs
===================================================================
--- Rhino.ServiceBus.Tests/When_Security_Is_Not_Specified_In_Config.cs	(revision 2085)
+++ Rhino.ServiceBus.Tests/When_Security_Is_Not_Specified_In_Config.cs	(working copy)
@@ -1,4 +1,3 @@
-using System;
 using System.IO;
 using System.Runtime.Serialization;
 using Castle.Windsor;
@@ -39,6 +38,27 @@
             }
         }
 
+		[Fact]
+		public void Will_throw_for_wire_encrypted_message()
+		{
+			var container = CreateContainer();
+			var serializer = container.Resolve<IMessageSerializer>();
+			var memoryStream = new MemoryStream();
+			try
+			{
+				serializer.Serialize(new[]
+                {
+                    new When_Security_Is_Specified_In_Config.SecretMessage() {Secret = 1234}
+                }, memoryStream);
+				Assert.True(false, "Expected exception");
+			}
+			catch (SerializationException e)
+			{
+				Assert.Equal("Cannot send IWireEncryptedMessage when <security> was not properly set up",
+					e.InnerException.Message);
+			}
+		}
+
         [Fact]
         public void Will_not_be_able_to_read_encypted_content()
         {
Index: Rhino.ServiceBus.Tests/When_Security_Is_Specified_In_Config.cs
===================================================================
--- Rhino.ServiceBus.Tests/When_Security_Is_Specified_In_Config.cs	(revision 2085)
+++ Rhino.ServiceBus.Tests/When_Security_Is_Specified_In_Config.cs	(working copy)
@@ -1,6 +1,5 @@
 using System.IO;
 using System.Security.Cryptography;
-using System.Text.RegularExpressions;
 using System.Xml.Linq;
 using Castle.Windsor;
 using Castle.Windsor.Configuration.Interpreters;
@@ -8,8 +7,8 @@
 using Rhino.ServiceBus.DataStructures;
 using Rhino.ServiceBus.Impl;
 using Rhino.ServiceBus.Internal;
+using Rhino.ServiceBus.Messages;
 using Xunit;
-using System.Linq;
 
 namespace Rhino.ServiceBus.Tests
 {
@@ -30,7 +29,15 @@
             Assert.IsType<WireEcryptedStringConvertor>(convertor);
         }
 
+		[Fact]
+		public void Will_register_wire_encrypted_message_convertor_on_container()
+		{
+			var container = CreateContainer();
+			var encryptionBehavior = container.Resolve<IElementSerializationBehavior>();
+			Assert.IsType<WireEncryptedMessageConvertor>(encryptionBehavior);
+		}
 
+
         public class ClassWithSecretField
         {
             public WireEcryptedString ShouldBeEncrypted
@@ -40,6 +47,11 @@
 
         }
 
+		public class SecretMessage : IWireEncryptedMessage
+		{
+			public int Secret { get; set; }
+		}
+
         public const string encryptedMessage =
                 @"<?xml version=""1.0"" encoding=""utf-8""?>
 <esb:messages xmlns:esb=""http://servicebus.hibernatingrhinos.com/2008/12/20/esb"" xmlns:tests.classwithsecretfield=""Rhino.ServiceBus.Tests.When_Security_Is_Specified_In_Config+ClassWithSecretField, Rhino.ServiceBus.Tests"" xmlns:datastructures.wireecryptedstring=""Rhino.ServiceBus.DataStructures.WireEcryptedString, Rhino.ServiceBus"" xmlns:string=""string"">
@@ -99,6 +111,59 @@
             Assert.Equal("abc", msg.ShouldBeEncrypted.Value);
         }
 
+		[Fact]
+		public void Will_encrypt_entire_message_for_wire_encrypted_message()
+		{
+			var container = CreateContainer();
+			var serializer = container.Resolve<IMessageSerializer>();
+			var memoryStream = new MemoryStream();
+			serializer.Serialize(new[]
+            {
+                new SecretMessage
+                {
+                    Secret = 1234,
+                }
+            }, memoryStream);
+
+			memoryStream.Position = 0;
+			var msg = new StreamReader(memoryStream).ReadToEnd();
+
+			var document = XDocument.Parse(msg);
+			var secretMessage = document
+				.Element(XName.Get("messages", "http://servicebus.hibernatingrhinos.com/2008/12/20/esb"))
+				.Element(XName.Get("SecretMessage", "Rhino.ServiceBus.Tests.When_Security_Is_Specified_In_Config+SecretMessage, Rhino.ServiceBus.Tests"));
+
+			var secret = secretMessage.Element(XName.Get("Secret", "int"));
+			Assert.Null(secret);
+
+			var valueElement = secretMessage.Element(XName.Get("Value", "string"));
+			Assert.NotNull(valueElement);
+
+			var iv = valueElement.Attribute("iv");
+			Assert.NotNull(iv);
+		}
+
+		[Fact]
+		public void Will_decrypt_message_for_wire_encrypted_message()
+		{
+			var container = CreateContainer();
+			var serializer = container.Resolve<IMessageSerializer>();
+			var memoryStream = new MemoryStream();
+			serializer.Serialize(new[]
+            {
+                new SecretMessage 
+                {
+					Secret = 1234,
+                }
+            }, memoryStream);
+
+			memoryStream.Position = 0;
+
+			var msg = (SecretMessage)serializer.Deserialize(memoryStream)[0];
+
+			Assert.Equal(1234, msg.Secret);
+		}
+
         [Fact]
         public void When_key_is_different_deserializing_key_will_fail()
         {
@@ -109,7 +174,7 @@
             var managed = new RijndaelManaged();
             managed.GenerateKey();
 
-            convertor.Key = managed.Key;
+            convertor.EncryptionService.Key = managed.Key;
 
             var memoryStream = new MemoryStream();
             var writer = new StreamWriter(memoryStream);
Index: Rhino.ServiceBus/Config/SecurityConfiguration.cs
===================================================================
--- Rhino.ServiceBus/Config/SecurityConfiguration.cs	(revision 2085)
+++ Rhino.ServiceBus/Config/SecurityConfiguration.cs	(working copy)
@@ -1,7 +1,6 @@
 using System;
 using System.Configuration;
 using Castle.Core.Configuration;
-using Castle.MicroKernel;
 using Castle.MicroKernel.Registration;
 using Rhino.ServiceBus.Convertors;
 using Rhino.ServiceBus.DataStructures;
@@ -24,6 +23,10 @@
                     Component.For<IValueConvertor<WireEcryptedString>>()
                         .ImplementedBy<ThrowingWireEcryptedStringConvertor>()
                     );
+				kernel.Register(
+					Component.For<IElementSerializationBehavior>()
+						.ImplementedBy<ThrowingWireEncryptedMessageConvertor>()
+					);
                 return;
             }
 
@@ -32,13 +35,28 @@
                 throw new ConfigurationErrorsException("<security> element must have a <key> element with content");
 
             var keyBuffer = Convert.FromBase64String(key.Value);
+
+        	kernel.Register(
+				Component.For<IEncryptionService>()
+					.ImplementedBy<RijndaelEncryptionService>()
+					.DependsOn(new
+					{
+						key = keyBuffer,
+					})
+					.Named("esb.security")
+				);
+
             kernel.Register(
                 Component.For<IValueConvertor<WireEcryptedString>>()
                     .ImplementedBy<WireEcryptedStringConvertor>()
-                    .DependsOn(
-                        Property.ForKey("key").Eq(keyBuffer)
-                    )
+					.ServiceOverrides(ServiceOverride.ForKey("encryptionService").Eq("esb.security"))
                 );
+
+        	kernel.Register(
+				Component.For<IElementSerializationBehavior>()
+					.ImplementedBy<WireEncryptedMessageConvertor>()
+					.ServiceOverrides(ServiceOverride.ForKey("encryptionService").Eq("esb.security"))
+        		);
         }
     }
 }
\ No newline at end of file
Index: Rhino.ServiceBus/Convertors/ThrowingWireEncryptedMessageConvertor.cs
===================================================================
--- Rhino.ServiceBus/Convertors/ThrowingWireEncryptedMessageConvertor.cs	(revision 0)
+++ Rhino.ServiceBus/Convertors/ThrowingWireEncryptedMessageConvertor.cs	(revision 0)
@@ -0,0 +1,30 @@
+using System;
+using System.Security;
+using System.Xml.Linq;
+using Rhino.ServiceBus.Internal;
+using Rhino.ServiceBus.Messages;
+
+namespace Rhino.ServiceBus.Convertors
+{
+	public class ThrowingWireEncryptedMessageConvertor : IElementSerializationBehavior
+	{
+		private readonly Type wireEncryptedMessageType = typeof (IWireEncryptedMessage);
+
+		public bool ShouldApplyBehavior(Type type)
+		{
+			return wireEncryptedMessageType.IsAssignableFrom(type);
+		}
+
+		public XElement ApplyElementBehavior(XElement element)
+		{
+			throw new SecurityException(
+				"Cannot send IWireEncryptedMessage when <security> was not properly set up");
+		}
+
+		public XElement RemoveElementBehavior(XElement element)
+		{
+			throw new SecurityException(
+				"Cannot accept IWireEncryptedMessage when <security> was not properly set up");
+		}
+	}
+}
\ No newline at end of file
Index: Rhino.ServiceBus/Convertors/WireEcryptedStringConvertor.cs
===================================================================
--- Rhino.ServiceBus/Convertors/WireEcryptedStringConvertor.cs	(revision 2085)
+++ Rhino.ServiceBus/Convertors/WireEcryptedStringConvertor.cs	(working copy)
@@ -1,6 +1,4 @@
 using System;
-using System.IO;
-using System.Security.Cryptography;
 using System.Xml.Linq;
 using Rhino.ServiceBus.DataStructures;
 using Rhino.ServiceBus.Internal;
@@ -9,37 +7,19 @@
 {
     public class WireEcryptedStringConvertor : IValueConvertor<WireEcryptedString>
     {
-        public byte[] Key{ get; set;}
+    	public IEncryptionService EncryptionService { get; set;}
 
-        public WireEcryptedStringConvertor(byte[] key)
+        public WireEcryptedStringConvertor(IEncryptionService encryptionService)
         {
-            Key = key;
+        	EncryptionService = encryptionService;
         }
 
         public XElement ToElement(WireEcryptedString val, Func<Type, XNamespace> getNamespace)
         {
-            using (var rijndael = new RijndaelManaged())
-            {
-                rijndael.Key = Key;
-                rijndael.Mode = CipherMode.CBC;
-                rijndael.GenerateIV();
-
-                using (var encryptor = rijndael.CreateEncryptor())
-                using (var memoryStream = new MemoryStream())
-                using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
-                using (var writer = new StreamWriter(cryptoStream))
-                {
-                    writer.Write(val);
-                    writer.Flush();
-                    cryptoStream.Flush();
-                    cryptoStream.FlushFinalBlock();
-
-                    return new XElement(getNamespace(typeof (string)) + "Value",
-                                        new XAttribute("iv", Convert.ToBase64String(rijndael.IV)),
-                                        Convert.ToBase64String(memoryStream.ToArray())
-                        );
-                }
-            }
+        	var encryptedValue = EncryptionService.Encrypt(val);
+			return new XElement(getNamespace(typeof(string)) + "Value",
+				new XAttribute("iv", encryptedValue.Base64Iv),
+				encryptedValue.EncryptedBase64Value);
         }
 
         public WireEcryptedString FromElement(XElement element)
@@ -50,24 +30,15 @@
             
             var attribute = value.Attribute("iv");
             if(attribute==null)
-                throw new ArgumentException("element must contain a <value> element with iv attribue");
+                throw new ArgumentException("element must contain a <value> element with iv attribute");
 
-            var base64String = Convert.FromBase64String(element.Value);
+        	var encryptedValue = new EncryptedValue
+        	{
+				EncryptedBase64Value = element.Value,
+				Base64Iv = attribute.Value,
+        	};
 
-            using (var rijndael = new RijndaelManaged())
-            {
-                rijndael.Key = Key;
-                rijndael.IV = Convert.FromBase64String(attribute.Value);
-                rijndael.Mode = CipherMode.CBC;
-
-                using (var decryptor = rijndael.CreateDecryptor())
-                using (var memoryStream = new MemoryStream(base64String))
-                using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
-                using (var reader = new StreamReader(cryptoStream))
-                {
-                    return reader.ReadToEnd();
-                }
-            }
+        	return EncryptionService.Decrypt(encryptedValue);
         }
     }
 }
\ No newline at end of file
Index: Rhino.ServiceBus/Convertors/WireEncryptedMessageConvertor.cs
===================================================================
--- Rhino.ServiceBus/Convertors/WireEncryptedMessageConvertor.cs	(revision 0)
+++ Rhino.ServiceBus/Convertors/WireEncryptedMessageConvertor.cs	(revision 0)
@@ -0,0 +1,54 @@
+using System;
+using System.Xml.Linq;
+using Rhino.ServiceBus.Internal;
+using Rhino.ServiceBus.Messages;
+using Rhino.ServiceBus.DataStructures;
+
+namespace Rhino.ServiceBus.Convertors
+{
+	public class WireEncryptedMessageConvertor : IElementSerializationBehavior
+	{
+		private readonly Type wireEncryptedMessageType = typeof (IWireEncryptedMessage);
+		public IEncryptionService EncryptionService { get; set; }
+
+		public WireEncryptedMessageConvertor(IEncryptionService encryptionService)
+		{
+			EncryptionService = encryptionService;
+		}
+
+		public bool ShouldApplyBehavior(Type type)
+		{
+			return wireEncryptedMessageType.IsAssignableFrom(type);
+		}
+
+		public XElement ApplyElementBehavior(XElement element)
+		{
+			var encryptedValue = EncryptionService.Encrypt(element.ToString());
+			var replacement = new XElement(element.Name,
+				new XElement(XName.Get("Value", "string"),
+				new XAttribute("iv", encryptedValue.Base64Iv),
+				encryptedValue.EncryptedBase64Value
+				));
+			return replacement;
+		}
+
+		public XElement RemoveElementBehavior(XElement element)
+		{
+			var value = element.Element(XName.Get("Value", "string"));
+			if (value == null)
+				throw new ArgumentException("element must contain <value> element");
+
+			var attribute = value.Attribute("iv");
+			if (attribute == null)
+				throw new ArgumentException("element must contain a <value> element with iv attribute");
+
+			var encryptedValue = new EncryptedValue
+			{
+                Base64Iv = attribute.Value,
+				EncryptedBase64Value = element.Value,
+			};
+			var unencryptedValue = EncryptionService.Decrypt(encryptedValue);
+			return XElement.Parse(unencryptedValue);
+		}
+	}
+}
\ No newline at end of file
Index: Rhino.ServiceBus/DataStructures/EncryptedValue.cs
===================================================================
--- Rhino.ServiceBus/DataStructures/EncryptedValue.cs	(revision 0)
+++ Rhino.ServiceBus/DataStructures/EncryptedValue.cs	(revision 0)
@@ -0,0 +1,8 @@
+namespace Rhino.ServiceBus.DataStructures
+{
+	public class EncryptedValue
+	{
+		public string EncryptedBase64Value { get; set; }
+		public string Base64Iv { get; set; }
+	}
+}
\ No newline at end of file
Index: Rhino.ServiceBus/Impl/RijndaelEncryptionService.cs
===================================================================
--- Rhino.ServiceBus/Impl/RijndaelEncryptionService.cs	(revision 0)
+++ Rhino.ServiceBus/Impl/RijndaelEncryptionService.cs	(revision 0)
@@ -0,0 +1,63 @@
+using System;
+using System.IO;
+using System.Security.Cryptography;
+using Rhino.ServiceBus.DataStructures;
+using Rhino.ServiceBus.Internal;
+
+namespace Rhino.ServiceBus.Impl
+{
+	public class RijndaelEncryptionService : IEncryptionService
+	{
+		public byte[] Key { get; set;}
+
+		public RijndaelEncryptionService(byte[] key)
+		{
+			Key = key;
+		}
+
+		public EncryptedValue Encrypt(string value)
+		{
+			using (var rijndael = new RijndaelManaged())
+			{
+				rijndael.Key = Key;
+				rijndael.Mode = CipherMode.CBC;
+				rijndael.GenerateIV();
+
+				using (var encryptor = rijndael.CreateEncryptor())
+				using (var memoryStream = new MemoryStream())
+				using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
+				using (var writer = new StreamWriter(cryptoStream))
+				{
+					writer.Write(value);
+					writer.Flush();
+					cryptoStream.Flush();
+					cryptoStream.FlushFinalBlock();
+					return new EncryptedValue
+					{
+                        EncryptedBase64Value = Convert.ToBase64String(memoryStream.ToArray()),
+						Base64Iv = Convert.ToBase64String(rijndael.IV)
+					};
+				}
+			}
+		}
+
+		public string Decrypt(EncryptedValue encryptedValue)
+		{
+			var encrypted = Convert.FromBase64String(encryptedValue.EncryptedBase64Value);
+			using (var rijndael = new RijndaelManaged())
+			{
+				rijndael.Key = Key;
+				rijndael.IV = Convert.FromBase64String(encryptedValue.Base64Iv);
+				rijndael.Mode = CipherMode.CBC;
+
+				using (var decryptor = rijndael.CreateDecryptor())
+				using (var memoryStream = new MemoryStream(encrypted))
+				using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
+				using (var reader = new StreamReader(cryptoStream))
+				{
+					return reader.ReadToEnd();
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
Index: Rhino.ServiceBus/Internal/ICustomElementSerializer.cs
===================================================================
--- Rhino.ServiceBus/Internal/ICustomElementSerializer.cs	(revision 0)
+++ Rhino.ServiceBus/Internal/ICustomElementSerializer.cs	(revision 0)
@@ -0,0 +1,12 @@
+using System;
+using System.Xml.Linq;
+
+namespace Rhino.ServiceBus.Internal
+{
+	public interface ICustomElementSerializer
+	{
+		bool CanSerialize(Type type);
+		XElement ToElement(object val, Func<Type, XNamespace> getNamespace);
+		object FromElement(Type type, XElement element);
+	}
+}
\ No newline at end of file
Index: Rhino.ServiceBus/Internal/IElementSerializationBehavior.cs
===================================================================
--- Rhino.ServiceBus/Internal/IElementSerializationBehavior.cs	(revision 0)
+++ Rhino.ServiceBus/Internal/IElementSerializationBehavior.cs	(revision 0)
@@ -0,0 +1,12 @@
+using System;
+using System.Xml.Linq;
+
+namespace Rhino.ServiceBus.Internal
+{
+	public interface IElementSerializationBehavior
+	{
+		bool ShouldApplyBehavior(Type type);
+		XElement ApplyElementBehavior(XElement element);
+		XElement RemoveElementBehavior(XElement element);
+	}
+}
\ No newline at end of file
Index: Rhino.ServiceBus/Internal/IEncryptionService.cs
===================================================================
--- Rhino.ServiceBus/Internal/IEncryptionService.cs	(revision 0)
+++ Rhino.ServiceBus/Internal/IEncryptionService.cs	(revision 0)
@@ -0,0 +1,10 @@
+using Rhino.ServiceBus.DataStructures;
+namespace Rhino.ServiceBus.Internal
+{
+	public interface IEncryptionService
+	{
+		byte[] Key { get; set; }
+		EncryptedValue Encrypt(string value);
+		string Decrypt(EncryptedValue encryptedValue);
+	}
+}
\ No newline at end of file
Index: Rhino.ServiceBus/Messages/IWireEncryptedMessage.cs
===================================================================
--- Rhino.ServiceBus/Messages/IWireEncryptedMessage.cs	(revision 0)
+++ Rhino.ServiceBus/Messages/IWireEncryptedMessage.cs	(revision 0)
@@ -0,0 +1,6 @@
+namespace Rhino.ServiceBus.Messages
+{
+	public interface IWireEncryptedMessage
+	{
+	}
+}
\ No newline at end of file
Index: Rhino.ServiceBus/Rhino.ServiceBus.csproj
===================================================================
--- Rhino.ServiceBus/Rhino.ServiceBus.csproj	(revision 2085)
+++ Rhino.ServiceBus/Rhino.ServiceBus.csproj	(working copy)
@@ -168,14 +168,22 @@
     <Compile Include="Actions\IDeploymentAction.cs" />
     <Compile Include="Actions\IEnvironmentValidationAction.cs" />
     <Compile Include="Config\LoadBalancerConfiguration.cs" />
+    <Compile Include="Convertors\ThrowingWireEncryptedMessageConvertor.cs" />
+    <Compile Include="Convertors\WireEncryptedMessageConvertor.cs" />
+    <Compile Include="DataStructures\EncryptedValue.cs" />
     <Compile Include="DataStructures\Timeout.cs" />
     <Compile Include="Exceptions\InvalidDeploymentException.cs" />
     <Compile Include="Exceptions\LoadBalancerException.cs" />
     <Compile Include="Hosting\IApplicationHost.cs" />
     <Compile Include="Impl\AbstractRhinoServiceBusFacility.cs" />
+    <Compile Include="Impl\RijndaelEncryptionService.cs" />
+    <Compile Include="Internal\ICustomElementSerializer.cs" />
+    <Compile Include="Internal\IElementSerializationBehavior.cs" />
+    <Compile Include="Internal\IEncryptionService.cs" />
     <Compile Include="LoadBalancer\LoadBalancerFacility.cs" />
     <Compile Include="LoadBalancer\MsmqSecondaryLoadBalancer.cs" />
     <Compile Include="Messages\Heartbeat.cs" />
+    <Compile Include="Messages\IWireEncryptedMessage.cs" />
     <Compile Include="Messages\NewEndpointPersisted.cs" />
     <Compile Include="Messages\NewWorkerPersisted.cs" />
     <Compile Include="Messages\QueryForAllKnownWorkersAndEndpoints.cs" />
Index: Rhino.ServiceBus/Serializers/XmlMessageSerializer.cs
===================================================================
--- Rhino.ServiceBus/Serializers/XmlMessageSerializer.cs	(revision 2085)
+++ Rhino.ServiceBus/Serializers/XmlMessageSerializer.cs	(working copy)
@@ -4,7 +4,6 @@
 using System.Globalization;
 using System.IO;
 using System.Runtime.Serialization;
-using System.Security;
 using System.Text;
 using System.Xml;
 using System.Xml.Linq;
@@ -73,17 +72,28 @@
 
         private void WriteObject(string name, object value, XContainer parent, IDictionary<string, XNamespace> namespaces)
         {
-            if(HaveCustomSerializer(value.GetType()))
+            if(HaveCustomValueConvertor(value.GetType()))
             {
                 var valueConvertorType = reflection.GetGenericTypeOf(typeof (IValueConvertor<>), value);
                 var convertor = kernel.Resolve(valueConvertorType);
 
                 var elementName = GetXmlNamespace(namespaces, value.GetType()) + name;
 
-                var covertedValue = reflection.InvokeToElement(convertor, value, v => GetXmlNamespace(namespaces, v));
+                var convertedValue = reflection.InvokeToElement(convertor, value, v => GetXmlNamespace(namespaces, v));
 
-                parent.Add(new XElement(elementName, covertedValue));
+            	convertedValue = ApplyMessageSerializationBehaviorIfNecessary(value.GetType(), convertedValue);
+
+                parent.Add(new XElement(elementName, convertedValue));
             }
+			else if(HaveCustomSerializer(value.GetType()))
+			{
+				var customSerializer = kernel.ResolveAll<ICustomElementSerializer>().First(s => s.CanSerialize(value.GetType()));
+				var elementName = GetXmlNamespace(namespaces, value.GetType()) + name;
+				var element = customSerializer.ToElement(value, v => GetXmlNamespace(namespaces, v));
+				var customElement = new XElement(elementName, element);
+				customElement = ApplyMessageSerializationBehaviorIfNecessary(value.GetType(), customElement);
+				parent.Add(customElement);
+			}
             else if (ShouldPutAsString(value))
             {
                 var elementName = GetXmlNamespace(namespaces, value.GetType()) + name;
@@ -113,7 +123,6 @@
             else
             {
                 XElement content = GetContentWithNamespace(value, namespaces, name);
-                parent.Add(content);
                 foreach (var property in reflection.GetProperties(value))
                 {
                     var propVal = reflection.Get(value, property);
@@ -121,9 +130,31 @@
                         continue;
                     WriteObject(property, propVal, content, namespaces);
                 }
+            	content = ApplyMessageSerializationBehaviorIfNecessary(value.GetType(), content);
+				parent.Add(content);
             }
         }
 
+		private XElement ApplyMessageSerializationBehaviorIfNecessary(Type messageType, XElement element)
+		{
+			foreach (var afterSerializedBehavior in kernel.ResolveAll<IElementSerializationBehavior>())
+			{
+				if (afterSerializedBehavior.ShouldApplyBehavior(messageType))
+					return afterSerializedBehavior.ApplyElementBehavior(element);
+			}
+			return element;
+		}
+
+		private XElement ApplyMessageDeserializationBehaviorIfNecessary(Type messageType, XElement element)
+		{
+			foreach (var afterSerializedBehavior in kernel.ResolveAll<IElementSerializationBehavior>())
+			{
+				if (afterSerializedBehavior.ShouldApplyBehavior(messageType))
+					return afterSerializedBehavior.RemoveElementBehavior(element);
+			}
+			return element;
+		}
+
         private XNamespace GetXmlNamespace(IDictionary<string, XNamespace> namespaces, Type type)
         {
             var ns = reflection.GetNamespaceForXml(type);
@@ -135,7 +166,13 @@
             return xmlNs;
         }
 
-        private bool HaveCustomSerializer(Type type)
+		private bool HaveCustomSerializer(Type type)
+		{
+			return kernel.ResolveAll<ICustomElementSerializer>()
+				.Any(s => s.CanSerialize(type));
+		}
+
+        private bool HaveCustomValueConvertor(Type type)
         {
             bool? hasConvertor = null;
             typeHasConvertorCache.Read(
@@ -280,12 +317,19 @@
             if (type == null)
                 throw new ArgumentNullException("type");
 
-            if(HaveCustomSerializer(type))
+        	element = ApplyMessageDeserializationBehaviorIfNecessary(type, element);
+
+            if(HaveCustomValueConvertor(type))
             {
                 var convertorType = reflection.GetGenericTypeOf(typeof(IValueConvertor<>),type);
                 var convertor = kernel.Resolve(convertorType);
                 return reflection.InvokeFromElement(convertor, element);
             }
+			if(HaveCustomSerializer(type))
+			{
+				var customSerializer = kernel.ResolveAll<ICustomElementSerializer>().First(s => s.CanSerialize(type));
+				return customSerializer.FromElement(type, element);
+			}
 			if(type == typeof(byte[]))
 			{
 				return Convert.FromBase64String(element.Value);
