在我们现实当中经常会存在需要对某些数据进行加密保护 然后进行解密的操作,比方,我们需要对某些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 里面如何实现该算法.
将数据流链接到加密转换的流CryptoStream类:
任何从 Stream 导出的对象都可以传入
stream 参数。任何实现 ICryptoTransform(例如 HashAlgorithm)的对象都可以传入transform 参数。
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
程序集: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)
CryptoStreamMode mode)
参数:
stream-- 对其执行加密转换的流。
transform-- 要对流执行的加密转换。
mode--CryptoStreamMode 值之一。
3.CryptoStream.Write 方法
--------------------------------------
将一个字节序列写入当前 CryptoStream,并将流中的当前位置提升写入的字节数。
public override void Write (byte[ ] buffer,
int offset,
int count)
参数
buffer: 字节数组。此方法将 count 个字节从 buffer 复制到当前流。
offset:buffer 中的字节偏移量,从此偏移量开始将字节复制到当前流。
count:要写入当前流的字节数。
--------------------------------------
将一个字节序列写入当前 CryptoStream,并将流中的当前位置提升写入的字节数。
public override void Write (byte[ ] buffer,
参数
buffer: 字节数组。此方法将 count 个字节从 buffer 复制到当前流。
offset:buffer 中的字节偏移量,从此偏移量开始将字节复制到当前流。
count:要写入当前流的字节数。
4.CryptoStream.FlushFinalBlock 方法
----------------------------------------------------
用缓冲区的当前状态更新基础数据源或储存库,随后清除缓冲区。
public void 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());
}
如: