简体   繁体   中英

Illegal Hex Chars in XML after encryption & decryption

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

Leaving aside your approach to security, the core problem is that you cannot have all the chars you want in XML document. To fix this, you should encode the encrypted text in Base64 before writing to the XML ( example ). Do not use any regex, as this changes the cypher text, which means you will not be able to decrypt it.

Sender

  • Encrypt message ( string -> byte[] )
  • Base64 encode ( byte[] -> string )
  • Write to xml

Receiver

  • Read from xml ( string )
  • Decode from Base64 ( string -> byte[] )
  • Decrypt ( byte[] -> string )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM