WCF 对称加密传输

来源:互联网 发布:上瘾网络剧百度云资源 编辑:程序博客网 时间:2024/06/04 20:03

大家使用WCF的时候,会不会觉得使用SSL通道传输太麻烦,使用明文传输又觉得不安全呢? 特别是当传递的消息中带有比较敏感,机密的身份信息的时候更是如此呢?本文实现一个可能大家非常需要的功能,对称加密传输,希望对大家有帮助。

  工作原理和压缩传输一致所以本文不做赘述,详细的实现机理会单开一篇详细去谈,本文重点看看实现代码和实现效果。要实现对称机密传输的功能,我们主要要实现的有如下几个类:CryptEncodingBindingElement,CryptEncoderFactory,CryptEncoder,DESCryption,前面三项都是WCF扩展所必须的,后面是工具类,主要是用于DES加解密和生成密钥和IV。

CryptEncodingBindingElement

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.ServiceModel.Channels;

namespace RobinLib
{
public class CryptEncodingBindingElement: MessageEncodingBindingElement

private XmlDictionaryReaderQuotas readerQuotas;
private MessageEncodingBindingElement innerMessage

EncodingBindingElement;
string key;
string iv; 
public MessageEncodingBindingElement InnerMessage

EncodingBindingElement
{
get
{
return innerMessageEncodingBindingElement;
}
}

public string Key
{
get
{
return key;
}
}
public string IV
{
get
{
return iv;
}
}

public CryptEncodingBindingElement(MessageEncodingBindingElement innerMessageEncodingBindingElement, string key,string iv)
{
this.readerQuotas = new XmlDictionaryReaderQuotas();
this.key = key;
this.iv = iv;
this.innerMessageEncodingBindingElement =

innerMessageEncodingBindingElement;
}

public override IChannelFactory<TChannel>

BuildChannelFactory<TChannel>(BindingContext context)
{
context.BindingParameters.Add(this);
return context.BuildInnerChannelFactory<TChannel>();
}
public override IChannelListener<TChannel>

BuildChannelListener<TChannel>(BindingContext context)
{
context.BindingParameters.Add(this);
return context.BuildInnerChannelListener<TChannel>();
}
public override bool CanBuildChannelFactory

<TChannel>(BindingContext context)
{
context.BindingParameters.Add(this);
return context.CanBuildInnerChannelFactory<TChannel>();
}
public override bool CanBuildChannelListener

<TChannel>(BindingContext context)
{
context.BindingParameters.Add(this);
return context.CanBuildInnerChannelListener<TChannel>();
}
public override MessageEncoderFactory CreateMessageEncoderFactory()
{
return new CryptEncoderFactory(innerMessageEncodingBindingElement,key,iv);
}
public override T GetProperty<T>(BindingContext context) 
{
if (typeof(T) == typeof(XmlDictionaryReaderQuotas))
{
return this.readerQuotas as T;
}
return base.GetProperty<T>(context);

}
public override MessageVersion MessageVersion
{
get
{
return innerMessageEncodingBindingElement.MessageVersion;
}
set
{
innerMessageEncodingBindingElement.MessageVersion = value;
}
}

public override BindingElement Clone()
{
return new CryptEncodingBindingElement(innerMessageEncodingBindingElement,key,iv);

}
}

CryptEncoderFactory

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;

namespace RobinLib
{
public class CryptEncoderFactory : MessageEncoderFactory
{
private MessageEncodingBindingElement innerMessageEncodingBindingElement;
CryptEncoder messageEncoder;
string key;
string iv; 
public CryptEncoderFactory(MessageEncodingBindingElement innerMessageEncodingBindingElement, string key,string iv)
{
this.innerMessageEncodingBindingElement =

innerMessageEncodingBindingElement;
this.key = key;
this.iv = iv;
messageEncoder = new CryptEncoder(this,key, iv);
}
public override MessageEncoder CreateSessionEncoder()
{
return base.CreateSessionEncoder();
}
public override MessageEncoder Encoder
{
get { return messageEncoder; }
}
public override MessageVersion MessageVersion
{
get { return innerMessageEncodingBindingElement.MessageVersion; }
}
public MessageEncodingBindingElement InnerMessageEncodingBindingElement
{
get
{
return innerMessageEncodingBindingElement;
}
}
}
}

CryptEncoder

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
using System.IO;

namespace RobinLib
{
public class CryptEncoder : MessageEncoder
{
CryptEncoderFactory factory;
MessageEncoder innserEncoder;
string key;
string iv;
public CryptEncoder(CryptEncoderFactory encoderFactory,string key,string iv)
{
factory = encoderFactory;
this.key = key;
this.iv = iv;
innserEncoder =

factory.InnerMessageEncodingBindingElement.CreateMessageEncoderFactory().Encoder;
}
public override string ContentType
{
get { return innserEncoder.ContentType; }
}
public override string MediaType
{
get { return innserEncoder.MediaType; }
}
public override MessageVersion MessageVersion
{
get { return innserEncoder.MessageVersion; }
}
public override bool IsContentTypeSupported(string contentType)
{
return innserEncoder.IsContentTypeSupported(contentType);
}
public override T GetProperty<T>()
{
return innserEncoder.GetProperty<T>();
}
public override Message ReadMessage(ArraySegment<byte>

buffer, BufferManager bufferManager, string contentType)
{
ArraySegment<byte> bytes = new DESCryption(key,iv).Decrypt(buffer);
int totalLength = bytes.Count;
byte[] totalBytes = bufferManager.TakeBuffer(totalLength);
Array.Copy(bytes.Array, 0, totalBytes, 0, bytes.Count);
ArraySegment<byte> byteArray = new ArraySegment<byte>(totalBytes, 0, bytes.Count);
bufferManager.ReturnBuffer(byteArray.Array); 
Message msg = innserEncoder.ReadMessage(byteArray, bufferManager, contentType);
return msg;

}
public override Message ReadMessage(System.IO.Stream stream,

int maxSizeOfHeaders, string contentType)
{
//读取消息的时候,二进制流为加密的,需要解压
Stream ms = new DESCryption(key,iv).Decrypt(stream); 
Message msg = innserEncoder.ReadMessage(ms, maxSizeOfHeaders, contentType);
return msg;
}
public override ArraySegment<byte>

WriteMessage(Message message, int maxMessageSize,

BufferManager bufferManager, int messageOffset)

ArraySegment<byte> bytes =

innserEncoder.WriteMessage(message, maxMessageSize, bufferManager);
ArraySegment<byte> buffer = new DESCryption(key,iv).Encrypt(bytes);
int totalLength = buffer.Count + messageOffset;
byte[] totalBytes = bufferManager.TakeBuffer(totalLength);
Array.Copy(buffer.Array, 0, totalBytes, messageOffset, buffer.Count);
ArraySegment<byte> byteArray =

new ArraySegment<byte>(totalBytes, messageOffset, buffer.Count);
Console.WriteLine(",原来字节流大小:"+bytes.Count+",压缩后字节流大小:"+byteArray.Count);
return byteArray;
}
public override void WriteMessage(Message message, System.IO.Stream stream)
{
System.IO.MemoryStream ms = new System.IO.MemoryStream();
innserEncoder.WriteMessage(message, ms);
stream = new DESCryption(key,iv).Encrypt(ms);
}
}
}

DESCryption

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace RobinLib
{
public class DESCryption : IDisposable
{
DESCryptoServiceProvider des;
Encoding encoding = new UnicodeEncoding();
public DESCryption()
{

}
public DESCryption(string key, string iv)
{
des = new DESCryptoServiceProvider();
des.Key = Convert.FromBase64String(key);
des.IV = Convert.FromBase64String(iv);
}
public void Dispose()
{
des.Clear();
}
public void GenerateKey(out string key, out string iv)
{
key = "";
iv = "";
using (DESCryptoServiceProvider des_o = new DESCryptoServiceProvider())
{
des_o.GenerateIV();
des_o.GenerateKey();
iv = Convert.ToBase64String(des_o.IV);
key = Convert.ToBase64String(des_o.Key);
}
}
#region ========加密========
/// <summary> 
/// 加密数据 
/// </summary> 
/// <param name="Text"></param> 
/// <param name="sKey"></param> 
/// <returns></returns> 
public string Encrypt(string Text)
{
MemoryStream ms = new MemoryStream();
CryptoStream cs =

new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
StreamWriter sw = new StreamWriter(cs);
sw.Write(Text);
sw.Close();
cs.Close();
byte[] buffer = ms.ToArray();
ms.Close();
return Convert.ToBase64String(buffer);
}

public ArraySegment<byte> Encrypt(ArraySegment<byte> buffers)

MemoryStream ms = new MemoryStream();
CryptoStream cs =

new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(buffers.Array, 0, buffers.Count); 
cs.Close();
byte[] buffer = ms.ToArray();
ms.Close(); 
ArraySegment<byte> bytes = new ArraySegment<byte>(buffer); 
return bytes;
}

public Stream Encrypt(Stream stream)
{
MemoryStream ms = new MemoryStream(); 
CryptoStream cs =

new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
cs.Write(buffer, 0, buffer.Length);
cs.Close(); 
return ms;
}

#endregion

#region ========解密========
/// <summary> 
/// 解密数据 
/// </summary> 
/// <param name="Text"></param> 
/// <param name="sKey"></param> 
/// <returns></returns> 
public string Decrypt(string Text)
{
byte[] inputByteArray = Convert.FromBase64String(Text);
System.IO.MemoryStream ms =

new System.IO.MemoryStream(inputByteArray);
CryptoStream cs =

new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read);
StreamReader sr = new StreamReader(cs);
string val = sr.ReadLine();
cs.Close();
ms.Close();
des.Clear();
return val;
}
public ArraySegment<byte>

Decrypt(ArraySegment<byte> buffers)
{
MemoryStream ms = new MemoryStream();
ms.Write(buffers.Array, 0, buffers.Count);
ms.Seek(0, SeekOrigin.Begin);
CryptoStream cs =

new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read);
byte[] buffer = RetrieveBytesFromStream(cs, 1024);
ms.Close();
ArraySegment<byte> bytes = new ArraySegment<byte>(buffer);
return bytes;
}
public Stream Decrypt(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
MemoryStream ms = new MemoryStream();
Stream compressStream = new CryptoStream(stream, des.CreateDecryptor(), CryptoStreamMode.Read);
byte[] newByteArray = RetrieveBytesFromStream(compressStream, 1);
compressStream.Close();
return new MemoryStream(newByteArray);
}
public static byte[] RetrieveBytesFromStream(Stream stream, int bytesblock)
{

List<byte> lst = new List<byte>();
byte[] data = new byte[1024];
int totalCount = 0;
while (true)
{
int bytesRead = stream.Read(data, 0, data.Length);
if (bytesRead == 0)
{
break;
}
byte[] buffers = new byte[bytesRead];
Array.Copy(data, buffers, bytesRead);
lst.AddRange(buffers);
totalCount += bytesRead;
}
return lst.ToArray();
}
#endregion

#region IDisposable 成员

void IDisposable.Dispose()
{
if (des != null)
{
des.Clear();
}
}

#endregion
}
}

宿主

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Robin_Wcf_CustomMessageEncoder_SvcLib;
using System.ServiceModel.Channels;
using RobinLib;

namespace Robin_Wcf_CustomMessageEncoder_Host
{
class Program
{
static void Main(string[] args)
{
//服务地址
Uri baseAddress = new Uri("http://127.0.0.1:8081/Robin_Wcf_Formatter");
ServiceHost host = new ServiceHost(typeof(Service1), new Uri[] { baseAddress });
//服务绑定
ICollection<BindingElement> bindingElements = new List<BindingElement>();
HttpTransportBindingElement httpBindingElement = new HttpTransportBindingElement();
string key = "JggkieIw7JM=";
string iv = "XdTkT85fZ0U=";
CryptEncodingBindingElement textBindingElement = new CryptEncodingBindingElement(new BinaryMessageEncodingBindingElement(), key,iv);
bindingElements.Add(textBindingElement);
bindingElements.Add(httpBindingElement);
CustomBinding bind = new CustomBinding(bindingElements); 
host.AddServiceEndpoint(typeof(IService1), bind, "");
if (host.Description.Behaviors.Find

<System.ServiceModel.Description.ServiceMetadataBehavior>() == null)
{
System.ServiceModel.Description.ServiceMetadataBehavior svcMetaBehavior =

new System.ServiceModel.Description.ServiceMetadataBehavior();
svcMetaBehavior.HttpGetEnabled = true;
svcMetaBehavior.HttpGetUrl = new Uri("http://127.0.0.1:8001/Mex");
host.Description.Behaviors.Add(svcMetaBehavior);
}
host.Opened += new EventHandler(delegate(object obj, EventArgs e)
{
Console.WriteLine("服务已经启动!");
}); 
host.Open();
Console.Read();
}
}
}

客户端

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RobinLib;
using System.ServiceModel.Channels;
using Robin_Wcf_CustomMessageEncoder_ClientApp.ServiceReference1;

namespace Robin_Wcf_CustomMessageEncoder_ClientApp
{
class Program
{
static void Main(string[] args)
{
System.Threading.Thread.Sleep(5300);
ICollection<BindingElement> bindingElements =

new List<BindingElement>();
HttpTransportBindingElement httpBindingElement =

new HttpTransportBindingElement();
string key = "JggkieIw7JM=";
string iv = "XdTkT85fZ0U=";
CryptEncodingBindingElement textBindingElement =

new CryptEncodingBindingElement

(new BinaryMessageEncodingBindingElement(), key, iv);
bindingElements.Add(textBindingElement);
bindingElements.Add(httpBindingElement); 
CustomBinding bind = new CustomBinding(bindingElements); 
ServiceReference1.IService1 svc =

new ServiceReference1.Service1Client(bind,

new System.ServiceModel.EndpointAddress

("http://127.0.0.1:8081/Robin_Wcf_Formatter"));
string pres = svc.GetData(10);
Console.WriteLine(pres);
CompositeType ct = svc.GetDataUsingDataContract(new CompositeType());
System.IO.MemoryStream ms = new System.IO.MemoryStream();
for (int i = 0; i < 1000000; i++)
{
byte[] buffer = BitConverter.GetBytes(i);
ms.Write(buffer, 0, buffer.Length);
}
System.IO.Stream stream = svc.GetStream(ms);
Console.Read();
}
}
}

运行效果图:

 

生成key和iv的方法为:

public void GenerateKey(out string key, out string iv)
{
key = "";
iv = "";
using (DESCryptoServiceProvider des_o = new DESCryptoServiceProvider())
{
des_o.GenerateIV();
des_o.GenerateKey();
iv = Convert.ToBase64String(des_o.IV);
key = Convert.ToBase64String(des_o.Key);
}
}

原创粉丝点击