消息加密的工作原理
消息應用程序發送方對消息進行加密後發送到目標計算機的消息隊列中,然後由目標計算機上的應用程序接收消息隊列中的消息進行解密。消息加密旨在防止在傳輸過程中有人未經授權查看消息。
使用消息加密會降低性能,不過這沒有使用消息驗證時性能下降得那麼多。將加密的消息發送到多個不同的計算機時,由加密引起的性能下降非常明顯。但是,將多條消息發送到同一目標計算機上時,只有發送第一條消息所花費的時間明顯比平常發送的時間長。
要了解消息吞吐量降低的原因,那麼了解消息隊列使用的加密機制就很重要。
在源計算機上,消息隊列執行下列操作:
創建密鑰。
使用密鑰加密消息正文。
使用目標計算機的公鑰加密此密鑰。
將加密的密鑰附加到加密的消息中。
在目標計算機上,消息隊列執行下列操作:
使用其私鑰(在密鑰對中)解密密鑰。
使用密鑰解密消息正文。
密鑰可用於加密和解密兩個方面,因此它們被稱為是對稱的。公鑰只能用於加密,而私鑰只能用於解密。
由於非對稱密鑰加密比對稱的密鑰加密需要更高的開銷。因此采用類似SSL加密機制,使用非對稱加密算法加密對成加密使用的密鑰,用對稱加密算法加密需要發送的消息;解密的時候先使用非對稱解密算法解密對稱加密時使用的密鑰,然後用的得到密鑰來解密消息。
技術實現
創建x509證書
X509證書用於非對稱加密
證書的來源可以通過安裝證書服務獲取也可以通過命令生成
生成證書的命令如下
makecert -r -pe -n "CN=x509Signature" -b 01/01/2005 -e 01/01/2010 -sky Exchange -ss my -sr localMachine
獲取證書的方法
static X509Certificate2 GetCertificate()
{
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2 cert = null;
X509Certificate2Collection certCollection = store.Certificates;
foreach (X509Certificate2 x509 in certCollection)
{
if (x509.Thumbprint.Equals(thumbPrint.ToUpper()))
{
cert = x509;
break;
}
}
if (cert == null)
{
store.Close();
throw new ArgumentNullException(string.Format("The X.509 certificate (ThumbPrint: {0} ) could not be found. ", thumbPrint), "error");
}
store.Close();
return cert;
}
使用證書實現非對稱加密/解密的代碼如下
//非對稱加密密鑰
static byte[] RSAEncrypt(byte[] enkey, X509Certificate2 Certificate)
{
RSACryptoServiceProvider RSA = Certificate.PublicKey.Key as RSACryptoServiceProvider;
return RSA.Encrypt(enkey, false);
}
//非對成解密密鑰
static byte[] RSADecrypt(byte[] context, X509Certificate2 Certificate)
{
RSACryptoServiceProvider RSA = Certificate.PrivateKey as RSACryptoServiceProvider;
return RSA.Decrypt(context, false);
}
使用證書的公鑰加密,使用證書的私鑰解密
加解密方法
使用對稱加密算法進行消息的加密和解密,代碼如下:
//對稱加密消息內容
static byte[] Encrypt(SymmetricAlgorithm RC2, string bodystring)
{
MemoryStream ms = new MemoryStream();
CryptoStream encStream = new CryptoStream(ms, RC2.CreateEncryptor(), CryptoStreamMode.Write);
StreamWriter sw = new StreamWriter(encStream);
sw.WriteLine(bodystring);
sw.Close();
encStream.Close();
byte[] buffer = ms.ToArray();
ms.Close();
return buffer;
}
//對稱解密消息內容
static string Decrypt(byte[] CypherText, SymmetricAlgorithm RC2)
{
MemoryStream ms = new MemoryStream(CypherText);
Crypto
Stream encStream = new CryptoStream(ms, RC2.CreateDecryptor(), CryptoStreamMode.Read);
StreamReader sr = new StreamReader(encStream);
string val = sr.ReadLine();
sr.Close();
encStream.Close();
ms.Close();
return val;
}
發送加密消息
static void Send()
{
MessageQueue mq = new MessageQueue(DestinationQueue);
//mq.EncryptionRequired = EncryptionRequired.Body;
//mq.FormatName = new BinaryMessageFormatter();
Message message = new Message();
//采用二進制序列化
message.Formatter = new BinaryMessageFormatter();// new XMLMessageFormatter(new Type[] { typeof(string) });
//獲取x509證書
X509Certificate2 certificate = GetCertificate();
//使用x509證書非對稱加密對稱加密密鑰
RC2CryptoServiceProvider RC2 = new RC2CryptoServiceProvider();
byte[] key=RSAEncrypt(RC2.Key, certificate);
byte[] iv = RSAEncrypt(RC2.IV, certificate);
byte[] extarry= new byte[256];
key.CopyTo(extarry, 0);
iv.CopyTo(extarry, 128);
//保存使用非對稱加密後的對稱加密密鑰
message.Extension = extarry;
//message.DestinationSymmetricKey = RSAEncrypt(RC2.Key, certificate);
//設定使用非對稱加密的證書
//message.DigitalSignature = certificate.RawData;
message.SenderCertificate = certificate.RawData;
message.UseEncryption = false;
//message.AcknowledgeType = AcknowledgeTypes.PositiveReceive | AcknowledgeTypes.PositiveArrival;
//message.AdministrationQueue = new MessageQueue(@"thinkpad-t400\private$\myAdministrationQueue");
//message.UseJournalQueue = true;
message.UseDeadLetterQueue = true;
//設定對消息體對稱加密算法
message.EncryptionAlgorithm = EncryptionAlgorithm.Rc2;
//message.ConnectorType = new Guid("1E9A03C5-A9B5-4BF6-B0CB-CCB313275285");
message.Label = Guid.NewGuid().ToString();
//生成同步加密key
//MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
//SHA256CryptoServiceProvider hsa = new SHA256CryptoServiceProvider();
//byte[] keyArray = hsa.ComputeHash(System.Text.Encoding.ASCII.GetBytes(DestinationSymmetricKey));
//message.HashAlgorithm = System.Messaging.HashAlgorithm.Sha;
// RC2.Key = keyArray;
//使用RC2算法進行加密
byte[] enarry = Encrypt(RC2, BodyString);
string base64 = Convert.ToBase64String(enarry);
message.Body = enarry;
//message.SecurityContext = new SecurityContext();
Console.WriteLine("send encrypt message \r\n" + BodyString);
mq.Send(message, MessageQueueTransactionType.Single);
}
接收加密的消息
static void Receive()
{
MessageQueue mq = new MessageQueue(DestinationQueue);
//設定讀取消息中證書,擴展屬性中加密過的解密密鑰
mq.MessageReadPropertyFilter.DestinationSymmetri
Stream encStream = new CryptoStream(ms, RC2.CreateDecryptor(), CryptoStreamMode.Read);
StreamReader sr = new StreamReader(encStream);
string val = sr.ReadLine();
sr.Close();
encStream.Close();
ms.Close();
return val;
}
發送加密消息
static void Send()
{
MessageQueue mq = new MessageQueue(DestinationQueue);
//mq.EncryptionRequired = EncryptionRequired.Body;
//mq.FormatName = new BinaryMessageFormatter();
Message message = new Message();
//采用二進制序列化
message.Formatter = new BinaryMessageFormatter();// new XMLMessageFormatter(new Type[] { typeof(string) });
//獲取x509證書
X509Certificate2 certificate = GetCertificate();
//使用x509證書非對稱加密對稱加密密鑰
RC2CryptoServiceProvider RC2 = new RC2CryptoServiceProvider();
byte[] key=RSAEncrypt(RC2.Key, certificate);
byte[] iv = RSAEncrypt(RC2.IV, certificate);
byte[] extarry= new byte[256];
key.CopyTo(extarry, 0);
iv.CopyTo(extarry, 128);
//保存使用非對稱加密後的對稱加密密鑰
message.Extension = extarry;
//message.DestinationSymmetricKey = RSAEncrypt(RC2.Key, certificate);
//設定使用非對稱加密的證書
//message.DigitalSignature = certificate.RawData;
message.SenderCertificate = certificate.RawData;
message.UseEncryption = false;
//message.AcknowledgeType = AcknowledgeTypes.PositiveReceive | AcknowledgeTypes.PositiveArrival;
//message.AdministrationQueue = new MessageQueue(@"thinkpad-t400\private$\myAdministrationQueue");
//message.UseJournalQueue = true;
message.UseDeadLetterQueue = true;
//設定對消息體對稱加密算法
message.EncryptionAlgorithm = EncryptionAlgorithm.Rc2;
//message.ConnectorType = new Guid("1E9A03C5-A9B5-4BF6-B0CB-CCB313275285");
message.Label = Guid.NewGuid().ToString();
//生成同步加密key
//MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
//SHA256CryptoServiceProvider hsa = new SHA256CryptoServiceProvider();
//byte[] keyArray = hsa.ComputeHash(System.Text.Encoding.ASCII.GetBytes(DestinationSymmetricKey));
//message.HashAlgorithm = System.Messaging.HashAlgorithm.Sha;
// RC2.Key = keyArray;
//使用RC2算法進行加密
byte[] enarry = Encrypt(RC2, BodyString);
string base64 = Convert.ToBase64String(enarry);
message.Body = enarry;
//message.SecurityContext = new SecurityContext();
Console.WriteLine("send encrypt message \r\n" + BodyString);
mq.Send(message, MessageQueueTransactionType.Single);
}
接收加密的消息
static void Receive()
{
MessageQueue mq = new MessageQueue(DestinationQueue);
//設定讀取消息中證書,擴展屬性中加密過的解密密鑰
mq.MessageReadPropertyFilter.DestinationSymmetri
Stream encStream = new CryptoStream(ms, RC2.CreateDecryptor(), CryptoStreamMode.Read);
StreamReader sr = new StreamReader(encStream);
string val = sr.ReadLine();
sr.Close();
encStream.Close();
ms.Close();
return val;
}
發送加密消息
static void Send()
{
MessageQueue mq = new MessageQueue(DestinationQueue);
//mq.EncryptionRequired = EncryptionRequired.Body;
//mq.FormatName = new BinaryMessageFormatter();
Message message = new Message();
//采用二進制序列化
message.Formatter = new BinaryMessageFormatter();// new XMLMessageFormatter(new Type[] { typeof(string) });
//獲取x509證書
X509Certificate2 certificate = GetCertificate();
//使用x509證書非對稱加密對稱加密密鑰
RC2CryptoServiceProvider RC2 = new RC2CryptoServiceProvider();
byte[] key=RSAEncrypt(RC2.Key, certificate);
byte[] iv = RSAEncrypt(RC2.IV, certificate);
byte[] extarry= new byte[256];
key.CopyTo(extarry, 0);
iv.CopyTo(extarry, 128);
//保存使用非對稱加密後的對稱加密密鑰
message.Extension = extarry;
//message.DestinationSymmetricKey = RSAEncrypt(RC2.Key, certificate);
//設定使用非對稱加密的證書
//message.DigitalSignature = certificate.RawData;
message.SenderCertificate = certificate.RawData;
message.UseEncryption = false;
//message.AcknowledgeType = AcknowledgeTypes.PositiveReceive | AcknowledgeTypes.PositiveArrival;
//message.AdministrationQueue = new MessageQueue(@"thinkpad-t400\private$\myAdministrationQueue");
//message.UseJournalQueue = true;
message.UseDeadLetterQueue = true;
//設定對消息體對稱加密算法
message.EncryptionAlgorithm = EncryptionAlgorithm.Rc2;
//message.ConnectorType = new Guid("1E9A03C5-A9B5-4BF6-B0CB-CCB313275285");
message.Label = Guid.NewGuid().ToString();
//生成同步加密key
//MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
//SHA256CryptoServiceProvider hsa = new SHA256CryptoServiceProvider();
//byte[] keyArray = hsa.ComputeHash(System.Text.Encoding.ASCII.GetBytes(DestinationSymmetricKey));
//message.HashAlgorithm = System.Messaging.HashAlgorithm.Sha;
// RC2.Key = keyArray;
//使用RC2算法進行加密
byte[] enarry = Encrypt(RC2, BodyString);
string base64 = Convert.ToBase64String(enarry);
message.Body = enarry;
//message.SecurityContext = new SecurityContext();
Console.WriteLine("send encrypt message \r\n" + BodyString);
mq.Send(message, MessageQueueTransactionType.Single);
}
接收加密的消息
static void Receive()
{
MessageQueue mq = new MessageQueue(DestinationQueue);
//設定讀取消息中證書,擴展屬性中加密過的解密密鑰
mq.MessageReadPropertyFilter.DestinationSymmetri
cKey = true;
mq.MessageReadPropertyFilter.Extension = true;
mq.MessageReadPropertyFilter.SenderCertificate = true;
mq.MessageReadPropertyFilter.DigitalSignature = true;
Message message=mq.Receive(MessageQueueTransactionType.Single);
message.Formatter = new BinaryMessageFormatter();
//獲取證書
byte[] cert = message.SenderCertificate;
X509Certificate2 x509 = new X509Certificate2(cert);
x509 = GetCertificateBySubject(x509.Subject);
Console.WriteLine(x509.Thumbprint.ToString());
byte[] key = new byte[128];
byte[] iv = new byte[128];
for(int i=0;i<message.Extension.Length;i++)
{
if(i<128)
key[i] = message.Extension[i];
else
iv[i - 128] = message.Extension[i];
}
//還原對稱加密密鑰
key = RSADecrypt(key, x509);
iv = RSADecrypt(iv, x509);
//解密消息
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.Key = key;
rc2.IV = iv;
byte[] body = message.Body as byte[];
string bodystring= Decrypt(body, rc2);
Console.WriteLine("receive message " + bodystring);
}
實施步驟
消息接收方步驟
消息接收方申請x509證書
導出公鑰給消息發送發送放
消息發送方步驟
消息發送方隨機生成對稱加密的密鑰,使用該密鑰進行對消息對稱加密。
使用消息發送提供的證書對對稱密鑰進行非對成加密。
發送加密消息
接收方收到消息
讀取消息中的證書信息
讀取消息中的加密的密鑰信息
使用申請的x509證書對加密密鑰進行解密得到密鑰
使用對稱密鑰對加密消息進行解密得到明文
結束