I've to encrypt WCF messages manually with two way encryption for some reasons and I can not use default built-in security mechanisms of WCF.
Without encryption, everything works fine, but after encryption, I see some illegal characters in my WCF XML message.
If I remove those illegal characters with regular expressions, everything works fine again, even with encryption.
Question:
What's wrong with my encryption?
Encryption:
public override ArraySegment<Byte> WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
{
Int32 messageLength;
Byte[] messageBytes;
using (MemoryStream unEncryptedXmlStream = new MemoryStream())
{
using (XmlWriter writer = XmlWriter.Create(unEncryptedXmlStream))
{
message.WriteMessage(writer);
}
using (Rijndael crypObj = Rijndael.Create())
{
crypObj.IV = UTF8Encoding.Default.GetBytes("1234567890123456");
crypObj.Key = UTF8Encoding.Default.GetBytes("1234567890123456");
using (MemoryStream encryptedStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(encryptedStream, crypObj.CreateEncryptor(), CryptoStreamMode.Write))
{
unEncryptedXmlStream.Position = 0;
cryptoStream.Write(unEncryptedXmlStream.ToArray(), 0, (Int32)unEncryptedXmlStream.Length);
cryptoStream.FlushFinalBlock();
messageBytes = encryptedStream.ToArray();
messageLength = (Int32)encryptedStream.Position;
}
}
}
}
Int32 totalLength = messageLength + messageOffset;
Byte[] totalBytes = bufferManager.TakeBuffer(totalLength);
Array.Copy(messageBytes, 0, totalBytes, messageOffset, messageLength);
ArraySegment<Byte> byteArray = new ArraySegment<Byte>(totalBytes, messageOffset, messageLength);
return byteArray;
}
Decryption:
public override Message ReadMessage(Stream stream, Int32 maxSizeOfHeaders, String contentType)
{
Stream encryptedXmlStream = stream;
XElement reader = null;
encryptedXmlStream.Position = 0;
using (Rijndael crypObj = Rijndael.Create())
{
crypObj.IV = UTF8Encoding.Default.GetBytes("1234567890123456");
crypObj.Key = UTF8Encoding.Default.GetBytes("1234567890123456");
using (CryptoStream cryptoStream = new CryptoStream(encryptedXmlStream, crypObj.CreateDecryptor(), CryptoStreamMode.Read))
{
Byte[] buffer = new Byte[(Int32)encryptedXmlStream.Length];
cryptoStream.Read(buffer, 0, (Int32)encryptedXmlStream.Length);
//reader = XElement.Parse(Encoding.UTF8.GetString(buffer)); // exception
reader = XElement.Parse(CleanInvalidXmlChars(Encoding.UTF8.GetString(buffer))); // everything works fine again, even with encryption & decryption
}
}
String action = reader.Descendants()
.First(element => element.Name.LocalName == "Action").Value;
return Message.CreateMessage(MessageVersion, action, reader.Descendants()
.First(element => element.Name.LocalName == "Body").Elements().Single().CreateReader());
}
Remove illegal characters:
private static String CleanInvalidXmlChars(String input)
{
String pattern = @"[^\x09\x0A\x0D\x20-\xD7FF\xE000-\xFFFD\x10000-x10FFFF]";
return Regex.Replace(input, pattern, "");
}
Easy to debug and test console application:
https://drive.google.com/file/d/0B8_dFKbcEQ47b2VnSG0zcTZiRlk/edit?usp=sharing
To download press Ctrl+S
Thanks in advance