我出于某些原因使用双向加密手动加密WCF消息,我不能使用WCF的默认内置安全机制。
没有加密,一切正常,但加密后,我在WCF XML消息中看到一些非法字符。
如果我使用正则表达式删除这些非法字符,即使使用加密,一切也能正常工作。
问题:
我的加密有什么问题?
加密:
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;
}
解密:
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());
}
删除非法字符:
private static String CleanInvalidXmlChars(String input)
{
String pattern = @"[^\x09\x0A\x0D\x20-\xD7FF\xE000-\xFFFD\x10000-x10FFFF]";
return Regex.Replace(input, pattern, "");
}
易于调试和测试控制台应用程序:
https://drive.google.com/file/d/0B8_dFKbcEQ47b2VnSG0zcTZiRlk/edit?usp=sharing
要下载,请按Ctrl + S
提前致谢
答案 0 :(得分:1)
撇开您的安全方法,核心问题是您无法在XML文档中拥有所需的所有字符。要解决此问题,您应该在写入XML(example)之前在Base64中对加密文本进行编码。不要使用任何正则表达式,因为这会更改密码文本,这意味着您将无法对其进行解密。
发件人
string
- &gt; byte[]
)byte[]
- &gt; string
)接收机
string
)string
- &gt; byte[]
)byte[]
- &gt; string
)