使用RSA算法实现对数据的加解密

在我们现实当中经常会存在需要对某些数据进行加密保护 然后进行解密的操作,比方,我们需要对某些XML配置信息里面的某些数据进行加密,以防止任何人打开该XML配置信息都能正常的看到该配置信息里面的内容,从而被人家篡改程序,甚至致使系统崩溃.下面我就谈下现在比较常用的RSA算法以及如何在Visual C#中如何实现.
 
1.首先介绍下什么是RSA算法,让大家对RSA算法有个简要的理解.
   RSA算法非常简单,概述如下:
  找两素数p和q
   取n=p*q  如:n=3*7=21
   取t=(p-1)*(q-1) 如:t = 2*6 = 12
   取任何一个数e,要求满足e 
  取d*e%t==1  如:d=7,e=7,则7*7/12刚好等于1满足要求
  这样最终得到三个数: n d e,即 n=21,d=7,e=7
  设消息为数M 
  设c=(M**d)%n就得到了加密后的消息c
  设m=(c**e)%n则 m == M,从而完成对c的解密。
  注:**表示次方,上面两式中的d和e可以互换。
 
  在对称加密中:
  n d两个数构成公钥,可以告诉别人;
  n e两个数构成私钥,e自己保留,不让任何人知道。
  给别人发送的信息使用e加密,只要别人能用d解开就证明信息是由你发送的,构成了签名机制。
  别人给你发送信息时使用d加密,这样只有拥有e的你能够对其解密。
  rsa的安全性在于对于一个大数n,没有有效的方法能够将其分解从而在已知n d的情况无法获得e;同样在已知n e的情况下无法求得d。
 
2.上面就是对RSA算法的一个简要概括,该描述在很多书本上都有介绍,这里也就不做过多解释了,下面我们看下在.net 里面如何实现该算法.

   在.net 里面,有一个叫RSACryptoServiceProvider的类,在MSDN中,我们可以了解到该类使用加密服务提供程序 (CSP) 提供的rsa算法的实现,执行不对称加密和解密,从继承关系上我们了解到该类继承自RSA类.通过该类,我们可以导出加密解密所需要的XML信息,并且能够根据我们提供的XML信息进行加密解密计算,下面是对该类的一些具体操作,主要包括如何导出密钥,如何用形成的密钥进行加密和解密,完成我们一般的操作.


对字符串进行加解密:

using UnityEngine;
using System;
using System.IO;
using System.Collections;
using System.Text;
using System.Security.Cryptography;

public class RSACSPSample : MonoBehaviour {

	// Use this for initialization
	void Start () {
		Decrypt ();
	}
	
	// Update is called once per frame
	void Update () {
	
	}

	void Decrypt()
	{
		try
		{
			//Create a UnicodeEncoder to convert between byte array and string.
			ASCIIEncoding ByteConverter = new ASCIIEncoding();

			string dataString = "Data to Encrypt";

			//Create byte arrays to hold original, encrypted, and decrypted data.
			byte[] dataToEncrypt = ByteConverter.GetBytes(dataString);
			byte[] encryptedData;
			byte[] decryptedData;

			//Create a new instance of the RSACryptoServiceProvider class 
			// and automatically create a new key-pair.
			RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();

			//Display the origianl data to the console.
			Debug.LogFormat("Original Data: {0}", dataString);

			//Encrypt the byte array and specify no OAEP padding.  
			//OAEP padding is only available on Microsoft Windows XP or
			//later.  
			encryptedData = RSAalg.Encrypt(dataToEncrypt, false);

			//Display the encrypted data to the console. 
			Debug.LogFormat("Encrypted Data: {0}", ByteConverter.GetString(encryptedData));

			//Pass the data to ENCRYPT and boolean flag specifying 
			//no OAEP padding.
			decryptedData = RSAalg.Decrypt(encryptedData, false);

			//Display the decrypted plaintext to the console. 
			Debug.LogFormat("Decrypted plaintext: {0}", ByteConverter.GetString(decryptedData));
		}

		catch(CryptographicException e)
		{
			//Catch this exception in case the encryption did
			//not succeed.
			Debug.LogFormat(e.Message);
		}
	}
}

将数据流链接到加密转换的流CryptoStream类:

using UnityEngine;
using System;
using System.IO;
using System.Collections;
using System.Security.Cryptography;

public class RijndaelExample : MonoBehaviour {

	// Use this for initialization
	void Start () {
		EncryptAndDecrypt ();
	}
	
	// Update is called once per frame
	void Update () {
	
	}

	void EncryptAndDecrypt()         // 加密、解密
	{
		try
		{
			string original = "Here is some data to encrypt !";

			// Create a new instance of the Rijndael
			// class.  This generates a new key and initialization 
			// vector (IV).
			using (Rijndael myRijndael = Rijndael.Create())
			{
				// Encrypt the string to an array of bytes.
				byte[] encrypted = EncryptStringToBytes(original, myRijndael.Key, myRijndael.IV);

				// Decrypt the bytes to a string.
				string roundtrip = DecryptStringFromBytes(encrypted, myRijndael.Key, myRijndael.IV);

				//Display the original data and the decrypted data.
				Debug.LogFormat("Original:   {0}", original);
				Debug.LogFormat("Round Trip: {0}", roundtrip);
			}
		}
		catch (Exception e)
		{
			Debug.LogFormat("Error: {0}", e.Message);
		}
	}

	static byte[] EncryptStringToBytes(string plainText, byte[] key, byte[] IV)         // 将字符串加密成字节
	{
		// Check arguments.
		if (plainText == null || plainText.Length <= 0)
		{
			throw new ArgumentNullException ("plainText");
		}
		if (key==null || key.Length<=0)
		{
			throw new ArgumentNullException ("Key");
		}
		if (IV==null || IV.Length<=0)
		{
			throw new ArgumentNullException ("IV");
		}
		byte[] encrypted;
		// Create an Rijndael object
		// with the specified key and IV.
		using (Rijndael rijAlg = Rijndael.Create ()) 
		{
			rijAlg.Key = key;
			rijAlg.IV = IV;

			// Create an encryptor to perform the stream transform.
			ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);

			// create the stream used for encryption
			using (MemoryStream msEncrypt = new MemoryStream ())
			{
				using (CryptoStream csEncrypt = new CryptoStream (msEncrypt, encryptor, CryptoStreamMode.Write))
				{
					using (StreamWriter swEncrypt = new StreamWriter (csEncrypt))
					{
						// Write all data to the stream
						swEncrypt.Write(plainText);
					}
					encrypted = msEncrypt.ToArray ();
				}
			}
			// Return the encrypted bytes from the memory stream.
			return encrypted;
		}
	}

	static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)     // 将字节解密成字符串
	{
		// Check arguments.
		if (cipherText == null || cipherText.Length <= 0)
			throw new ArgumentNullException("cipherText");
		if (Key == null || Key.Length <= 0)
			throw new ArgumentNullException("Key");
		if (IV == null || IV.Length <= 0)
			throw new ArgumentNullException("IV");

		// Declare the string used to hold
		// the decrypted text.
		string plaintext = null;

		// Create an Rijndael object
		// with the specified key and IV.
		using (Rijndael rijAlg = Rijndael.Create())
		{
			rijAlg.Key = Key;
			rijAlg.IV = IV;

			// Create a decryptor to perform the stream transform.
			ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);

			// Create the streams used for decryption.
			using (MemoryStream msDecrypt = new MemoryStream(cipherText))
			{
				using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
				{
					using (StreamReader srDecrypt = new StreamReader(csDecrypt))
					{

						// Read the decrypted bytes from the decrypting stream
						// and place them in a string.
						plaintext = srDecrypt.ReadToEnd();
					}
				}
			}

		}
		return plaintext;

	}

}


将数据流链接到加密转换的流 CryptoStream类


1.命名空间:System.Security.Cryptography
程序集:mscorlib(在 mscorlib.dll 中)

----------------------------------------------------
继承层次结构
-System.Object
----- System.MarshalByRefObject
--------- System.IO.Stream
-------------System.Security.Cryptography.CryptoStream
2.-------------------------------
        公共语言运行库使用面向流的设计进行加密。该设计的核心是 CryptoStream。实现 CryptoStream 的任何加密对象可以和实现 Stream 的任
何对象链接起来,因此一个对象的流式处理输出可以馈送到另一个对象的输入。不需要分别存储中间结果(第一个对象的输出)。
        通过调用 Close 方法完成 CryptoStream 对象的使用后,始终应该显式关闭该对象。这会刷新流并使所有剩余的数据块都被 CryptoStream
对象处理。但是,如果在调用 Close 方法前发生了异常,CryptoStream 对象可能会关闭。为确保 Close 方法始终被调用,请在 try/catch 语句的
finally 块中放置 Close 方法调用。
用目标数据流、要使用的转换和流的模式初始化 CryptoStream 类的新实例。
public  CryptoStream (Stream  stream,ICryptoTransform  transform,
CryptoStreamMode  mode)
参数:
stream-- 对其执行加密转换的流。
transform-- 要对流执行的加密转换。
mode--CryptoStreamMode 值之一。
 任何从 Stream 导出的对象都可以传入  stream 参数。任何实现 ICryptoTransform(例如 HashAlgorithm)的对象都可以传入transform 参数。
3.CryptoStream.Write 方法 
--------------------------------------
将一个字节序列写入当前 CryptoStream,并将流中的当前位置提升写入的字节数。
public override void Write (byte[ ] buffer, int offset, int count)
参数
buffer: 字节数组。此方法将 count 个字节从 buffer 复制到当前流。
offset:buffer 中的字节偏移量,从此偏移量开始将字节复制到当前流。
count:要写入当前流的字节数。
4.CryptoStream.FlushFinalBlock 方法 
----------------------------------------------------
用缓冲区的当前状态更新基础数据源或储存库,随后清除缓冲区。
public void FlushFinalBlock ()
5.--------------------------------
如:
   private string DecryptString(string Value)
  {
        ICryptoTransform transform1=this.mCSP.CreateDecrytor(this.mCSP.Key,this.mCSP.IV);
       byte [ ] buffer1=Convert.FromBase64String(Value);
       MemoryStream stream1=new MemoryStream();
       CryptoStream  stream2=new CryptoStream(stream1,transform1,CrytoStreamMode.Write);
      stream2.Write(buffer1,0,buffer1.Length);
      stream2.FlushFinalBlock();
      stream2.Close();
      return Encoding.UTF8.GetString(stream1.ToArray());
  }

你可能感兴趣的:(文件操作)