zoukankan      html  css  js  c++  java
  • 实现MSMQ消息加密的安全实践

    实现MSMQ消息加密的安全实践

    消息加密的工作原理

    消息应用程序发送方对消息进行加密后发送到目标计算机的消息队列中,然后由目标计算机上的应用程序接收消息队列中的消息进行解密。消息加密旨在防止在传输过程中有人未经授权查看消息。

    使用消息加密会降低性能,不过这没有使用消息验证时性能下降得那么多。将加密的消息发送到多个不同的计算机时,由加密引起的性能下降非常明显。但是,将多条消息发送到同一目标计算机上时,只有发送第一条消息所花费的时间明显比平常发送的时间长。

    要了解消息吞吐量降低的原因,那么了解消息队列使用的加密机制就很重要。

    在源计算机上,消息队列执行下列操作:

    1. 创建密钥。
    2. 使用密钥加密消息正文。
    3. 使用目标计算机的公钥加密此密钥。
    4. 将加密的密钥附加到加密的消息中。
    5.  

    在目标计算机上,消息队列执行下列操作:

    1. 使用其私钥(在密钥对中)解密密钥。
    2. 使用密钥解密消息正文。
    3. 密钥可用于加密和解密两个方面,因此它们被称为是对称的。公钥只能用于加密,而私钥只能用于解密。

    由于非对称密钥加密比对称的密钥加密需要更高的开销。因此采用类似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);

    CryptoStream 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.DestinationSymmetricKey = 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);

    }

    实施步骤

    消息接收方步骤

    1. 消息接收方申请x509证书
    2. 导出公钥给消息发送发送放

    消息发送方步骤

    1. 消息发送方随机生成对称加密的密钥,使用该密钥进行对消息对称加密。
    2. 使用消息发送提供的证书对对称密钥进行非对成加密。
    3. 发送加密消息
    1. 接收方收到消息
    2. 读取消息中的证书信息
    3. 读取消息中的加密的密钥信息
    4. 使用申请的x509证书对加密密钥进行解密得到密钥
    5. 使用对称密钥对加密消息进行解密得到明文

    结束

  • 相关阅读:
    DS4700磁盘阵列的控制器微码升级操作记录(收录百度文库)
    Android 解决布局无法对齐的情况
    android 模仿大众点评团购卷列表多余3条时折叠,点击时显示剩余全部的功能
    android 解决ScrollView中的子布局不能够填充整个ScrollView的情况。
    Android在代码中设置控件的drawableLeft,drawableRight,drawableTop,drawableBottom。
    android RadioGroup中设置selector后出现多个别选中的RadioButton的解决办法
    Android 动态的给Button、TextView、ImageView等控件设置了background后,再设置padding属性时该属性不起作用
    Android Universal Image Loader java.io.FileNotFoundException: http:/xxx/lxx/xxxx.jpg
    Android2.3系统 自定义的PopupWindow在实例化时报空指针异常
    android精品开源项目整理
  • 原文地址:https://www.cnblogs.com/luluping/p/1467248.html
Copyright © 2011-2022 走看看