二话不说,先上一个图:
如上图所示
第一步:左边是服务器端,右边是客户端,先通过RSA算法生成两组公私钥,分别给服务器和客户端.
第二步:然后服务器端与客户端分别交互各自的公钥,各自保管好自己的私钥不要泄露.
第三步:每次要与服务端交互数据时,都先通过公钥加密,每次接收到数据之后先通过私钥解密.以保证数据的安全性.
来一段RSA生成公钥及私钥,加密及解密的公共类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace WebAPI.Tools
{
/// <summary>
/// RSA 非对称加解密算法
/// </summary>
public class RSAHelper
{
private int MAXENCRYPTSIZE = 117;
private int MAXDECRYPTSIZE = 128;
public string priKeyXml
{
get;
private set;
}
public string pubKeyXml
{
get;
private set;
}
private RSAHelper(string privateKey, string publicKey)
{
this.priKeyXml = privateKey;
this.pubKeyXml = publicKey;
}
public static RSAHelper Load(string privateKey = "", string publicKey = "")
{
if (string.IsNullOrEmpty(privateKey) && string.IsNullOrEmpty(publicKey))
{
//无key时生成新密钥
return Instance;
}
return new RSAHelper(privateKey, publicKey);
}
/// <summary>
/// 随机生成公私钥并返回对象
/// </summary>
public static RSAHelper Instance
{
get
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider(1024);
var publicKeyXml = provider.ToXmlString(false);
//publickey:<RSAKeyValue><Modulus>w9u2HfdbNZrmAUmXPbNmrhfy861qX4mzcCn69Ksl03Nz+Fq9gINZeN/vrfcWBzMyYxb2/J2TnGtpCLc0ls6gOTKDPbnQHwHr3oCzfvxNwvT2uoKQUBl4xMFw0TmvufMbheq6q3FCXUkVkAUC1cbQ/S9DqNp/veYcAavRDXtFdD0=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
var privateKeyXml = provider.ToXmlString(true);
//privatekey:<RSAKeyValue><Modulus>w9u2HfdbNZrmAUmXPbNmrhfy861qX4mzcCn69Ksl03Nz+Fq9gINZeN/vrfcWBzMyYxb2/J2TnGtpCLc0ls6gOTKDPbnQHwHr3oCzfvxNwvT2uoKQUBl4xMFw0TmvufMbheq6q3FCXUkVkAUC1cbQ/S9DqNp/veYcAavRDXtFdD0=</Modulus><Exponent>AQAB</Exponent><P>6tzaLZmY+hLLAifunWwcdUSfqTUvKOO5bJ8M1Zt34en40tfBaH9zml9gP8cmXaWyfpiZgHlPS9xlkLngudAiJw==</P><Q>1Xw2E1ufXsCM2JZahB6PH9pCgfD4XPjrqxF9xOWVvfbPmVBZByBIHYRs8ifbjIPvSKuaCfVFVStoIcOYrT9I+w==</Q><DP>mS4iPsuHMtM/BND2mEYC6ZkwaTP+5jRgo6+4tzkHH5lyaFHAG1/FDlJWfEJvi3SezmLI+zojtd6xf4s8PvS40Q==</DP><DQ>I91kMEhaM87hWpmXx05i+RTvy2iyMNxYqzqbCHMRfwJxye3npvzTYLIYo23ywl5/2pOJo1ajOTW7nsB/a8uP9Q==</DQ><InverseQ>EtYQvvBViXf7A5bgh+H4xLlBezD0yziBigoP/xcg1mcuI9Kb9rtPq64hQsajDYeNmm0Ibkxz9ihHr8+uWtdi5w==</InverseQ><D>HSivw2RZKvDlv1lSb/gumEqufALcbF7W3SMS3qxAVGvC3z27Ks/jWTCVwWOg3u+LV99KZC+dk1MWbxq/dJhMmBSiHOT6Sg7wvNMmX58zHl7Bhs702henzbr7CkiWrUcy3pVigr4olT9FlkjQkeEu9VfVW4TRGUDUkixTeh9MMC0=</D></RSAKeyValue>
return new RSAHelper(privateKeyXml, publicKeyXml);
}
}
/// <summary>
/// RSA公钥加密
/// </summary>
/// <param name="content"></param>
/// <param name="publicKeyXml">公钥xml串</param>
/// <returns></returns>
public string Encrypt(string content)
{
//string publickey = @"<RSAKeyValue><Modulus>w9u2HfdbNZrmAUmXPbNmrhfy861qX4mzcCn69Ksl03Nz+Fq9gINZeN/vrfcWBzMyYxb2/J2TnGtpCLc0ls6gOTKDPbnQHwHr3oCzfvxNwvT2uoKQUBl4xMFw0TmvufMbheq6q3FCXUkVkAUC1cbQ/S9DqNp/veYcAavRDXtFdD0=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.FromXmlString(pubKeyXml);
cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);
return Convert.ToBase64String(cipherbytes);
//return cipherbytes;
}
/// <summary>
/// RSA私钥解密
/// </summary>
/// <param name="encryptData">经过Base64编码的密文</param>
/// <param name="privateKeyXml">私钥xml串</param>
/// <returns>RSA解密后的数据</returns>
public string Decrypt(string encryptData)
{
string decryptData = "";
try
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(priKeyXml);
byte[] bEncrypt = Convert.FromBase64String(encryptData);
int length = bEncrypt.Length;
int offset = 0;
string cache;
int i = 0;
while (length - offset > 0)
{
if (length - offset > MAXDECRYPTSIZE)
{
var aa = GetSplit(bEncrypt, offset, MAXDECRYPTSIZE);
cache = Encoding.UTF8.GetString(provider.Decrypt(aa, false));
}
else
{
var aa = GetSplit(bEncrypt, offset, length - offset);
cache = Encoding.UTF8.GetString(provider.Decrypt(aa, false));
}
decryptData += cache;
i++;
offset = i * MAXDECRYPTSIZE;
}
}
catch (Exception e)
{
throw e;
}
return decryptData;
}
/// <summary>
/// RSA解密
/// </summary>
/// <param name="privatekey"></param>
/// <param name="content"></param>
/// <returns></returns>
public string RSADecrypt(string content)
{
//privatekey = @"<RSAKeyValue><Modulus>5m9m14XH3oqLJ8bNGw9e4rGpXpcktv9MSkHSVFVMjHbfv+SJ5v0ubqQxa5YjLN4vc49z7SVju8s0X4gZ6AzZTn06jzWOgyPRV54Q4I0DCYadWW4Ze3e+BOtwgVU1Og3qHKn8vygoj40J6U85Z/PTJu3hN1m75Zr195ju7g9v4Hk=</Modulus><Exponent>AQAB</Exponent><P>/hf2dnK7rNfl3lbqghWcpFdu778hUpIEBixCDL5WiBtpkZdpSw90aERmHJYaW2RGvGRi6zSftLh00KHsPcNUMw==</P><Q>6Cn/jOLrPapDTEp1Fkq+uz++1Do0eeX7HYqi9rY29CqShzCeI7LEYOoSwYuAJ3xA/DuCdQENPSoJ9KFbO4Wsow==</Q><DP>ga1rHIJro8e/yhxjrKYo/nqc5ICQGhrpMNlPkD9n3CjZVPOISkWF7FzUHEzDANeJfkZhcZa21z24aG3rKo5Qnw==</DP><DQ>MNGsCB8rYlMsRZ2ek2pyQwO7h/sZT8y5ilO9wu08Dwnot/7UMiOEQfDWstY3w5XQQHnvC9WFyCfP4h4QBissyw==</DQ><InverseQ>EG02S7SADhH1EVT9DD0Z62Y0uY7gIYvxX/uq+IzKSCwB8M2G7Qv9xgZQaQlLpCaeKbux3Y59hHM+KpamGL19Kg==</InverseQ><D>vmaYHEbPAgOJvaEXQl+t8DQKFT1fudEysTy31LTyXjGu6XiltXXHUuZaa2IPyHgBz0Nd7znwsW/S44iql0Fen1kzKioEL3svANui63O3o5xdDeExVM6zOf1wUUh/oldovPweChyoAdMtUzgvCbJk1sYDJf++Nr0FeNW1RB1XG30=</D></RSAKeyValue>";
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.FromXmlString(priKeyXml);
cipherbytes = rsa.Decrypt(Convert.FromBase64String(content), false);
return Encoding.UTF8.GetString(cipherbytes);
}
/// <summary>
/// 截取字节数组部分字节
/// </summary>
/// <param name="input"></param>
/// <param name="offset">起始偏移位</param>
/// <param name="length">截取长度</param>
/// <returns></returns>
private byte[] GetSplit(byte[] input, int offset, int length)
{
byte[] output = new byte[length];
for (int i = offset; i < offset + length; i++)
{
output[i - offset] = input[i];
}
return output;
}
}
}
通过WebAPI中调用生成公钥及私钥的方法:
/// <summary>
/// 通过Post获取公钥和私钥
/// </summary>
/// <returns>返回两对RSA公钥和私钥</returns>
public UserRSAFile Post(string username)
{
UserRSAFile rsaFile = new UserRSAFile();
rsaFile.username = username;
//生成客户端的公钥和私钥
RSAHelper rhelp = RSAHelper.Load();
TestEncDesMod mod = new TestEncDesMod();
mod.PrivateKeyForServer = false;
mod.PublicKey = rhelp.pubKeyXml;
mod.PrivateKey = rhelp.priKeyXml;
rsaFile.ClientRSA = mod;
//生成服务器端的公钥和私钥
rhelp = RSAHelper.Load();
mod = new TestEncDesMod();
mod.PrivateKeyForServer = false;
mod.PublicKey = rhelp.pubKeyXml;
mod.PrivateKey = rhelp.priKeyXml;
rsaFile.ServerRSA = mod;
return rsaFile;
}