C# 中使用 RSA加解密演算法

來源:互聯網
上載者:User

標籤:cifs   dig   pms   files   ng2   rsa加密   pboc   ifd   pow   

一、什麼是RSA

  RSA公開密鑰密碼體制。所謂的公開密鑰密碼體制就是使用不同的加密金鑰與解密密鑰,是一種“由已知加密金鑰推匯出解密密鑰在計算上是不可行的”密碼體制。   

  在公開密鑰密碼體制中,加密金鑰(即公開密鑰)PK是公開資訊,而解密密鑰(即秘密密鑰)SK是需要保密的。密碼編譯演算法E和解密演算法D也都是公開的。雖然密鑰SK是由公開密鑰PK決定的,但卻不能根據PK計算出SK。正是基於這種理論,1978年出現了著名的RSA演算法,它通常是先產生一對RSA 密鑰,其中之一是保密密鑰,由使用者儲存;另一個為公開密鑰,可對外公開,甚至可在網路伺服器中註冊。為提高保密強度,RSA密鑰至少為500位長,一般推薦使用1024位。這就使加密的計算量很大。為減少計算量,在傳送資訊時,常採用傳統加密方法 與公開祕密金鑰加密方法相結合的方式,即資訊採用改進的DES或IDEA對話祕密金鑰加密,然後使用RSA祕密金鑰加密對話密鑰和資訊摘要。對方收到資訊後,用不同的 密鑰解密並可核對資訊摘要。   

  RSA演算法是第一個能同時用於加密和數位簽章的演算法,也易於理解和操作。RSA是被研究得最廣泛的公開金鑰演算法,從提出到現在的三十多年裡,經曆了各種攻擊的考驗,逐漸為人們接受,普遍認為是目前最優秀的公開金鑰方案之一。

二、RSA演算法密鑰長度的選擇

1. 非對稱式加密演算法中1024 bit密鑰的強度相當於對稱式加密演算法80bit密鑰的強度。

2. 密鑰長度增長一倍,公開金鑰操作所需時間增加約4倍,私密金鑰操作所需時間增加約8倍,公私密金鑰產生時間約增長16倍。

3. 一次能加密的密文長度與密鑰長度成正比,加密後的密文長度跟密鑰長度相同(RSA加密內容的長度有限制,和密鑰長度有關,這是由它的演算法決定的)

  a、加密的明文長度不能超過RSA密鑰的長度減去11byte,比如密鑰長度是1024位的,1024位=1024bit=128byte,128-11=117byte,所以明文長度不能超過117byte,如果長度超過該值將會拋出異常。

  b、加密後密文的長度為密鑰的長度,如密鑰長度為1024bit(128Byte),最後產生的密文固定為 1024bit(128Byte)。

三、C#中的RSA加解密

   .NET Framework 類庫提供了System.Security 命名空間,System.Security 命名空間提供通用語言執行平台安全系統的基礎結構,包括許可權的基類,而該命名空間下提供了RSACryptoServiceProvider類來執行RSA演算法的不對稱式加密和解密。

1.金鑰組的產生:

a、根據RSACryptoServiceProvider直接產生

/// <summary>/// 產生密鑰/// </summary>public RSAKey GenerateRSAKey(){    RSAKey RSAKEY = new RSAKey();    RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();    RSAKEY.PrivateKey = RSA.ToXmlString(true);    //產生私密金鑰    RSAKEY.PublicKey = RSA.ToXmlString(false);    //產生公開金鑰    RSA.Clear();    return RSAKEY;}

b、通過Makecert認證建立工具產生安全性憑證

makecert -r -pe -n "CN=RSAKey" -b 03/31/2005 -e 12/31/2012 -sky exchange -ss my

可通過"Visual Studio命令提示行"執行以上命令產生認證。

查看產生的認證:

運行->輸入mmc開啟控制台->選擇檔案->添加/刪除嵌入式管理單元->在彈出框左側找到認證->選中認證添加->選擇我的使用者賬戶->完成確定

此時就可以在對應位置查看到我們剛剛建立的名為RSAKey的認證了,如:

最終我們可以將認證匯出為:

 

其中RSAKey.cer中含有加密用的公開金鑰,RSAKey.pfx中含有解密用的私密金鑰。

2.建立加解密RSA

/// <summary>/// 建立加密RSA/// </summary>/// <param name="publicKey">公開金鑰</param>/// <returns></returns>private RSACryptoServiceProvider CreateEncryptRSA(string publicKey){    try    {        RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();        RSA.FromXmlString(publicKey);        return RSA;    }    catch (CryptographicException ex)    {        throw ex;    }}/// <summary>/// 建立解密RSA/// </summary>/// <param name="privateKey">私密金鑰</param>/// <returns></returns>private RSACryptoServiceProvider CreateDecryptRSA(string privateKey){    try    {        RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();        RSA.FromXmlString(privateKey);        return RSA;    }    catch (CryptographicException ex)    {        throw ex;    }}/// <summary>/// 根據安全性憑證建立加密RSA/// </summary>/// <param name="certfile">公開金鑰檔案</param>/// <returns></returns>private RSACryptoServiceProvider X509CertCreateEncryptRSA(string certfile){    try    {        X509Certificate2 x509Cert = new X509Certificate2(certfile);        RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)x509Cert.PublicKey.Key;        return RSA;    }    catch (CryptographicException ex)    {        throw ex;    }}/// <summary>/// 根據私密金鑰檔案建立解密RSA/// </summary>/// <param name="keyfile">私密金鑰檔案</param>/// <param name="password">訪問含私密金鑰檔案的密碼</param>/// <returns></returns>private RSACryptoServiceProvider X509CertCreateDecryptRSA(string keyfile, string password){    try    {        X509Certificate2 x509Cert = new X509Certificate2(keyfile, password);        RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)x509Cert.PrivateKey;        return RSA;    }    catch (CryptographicException ex)    {        throw ex;    }}

其中所提及的私密金鑰檔案和公開金鑰檔案就是根據Makecert認證建立工具產生安全性憑證,而X509CertCreateDecryptRSA方法中的參數password是我們匯出私密金鑰檔案所設定的訪問密碼,如果沒有改密碼即使有私密金鑰認證也沒辦法解密。

3.RSA加解密

/// <summary>/// 加密/// </summary>/// <param name="dataToEncrypt">待加密資料</param>/// <param name="publicKey">公開金鑰</param>/// <returns></returns>public string Encrypt(string dataToEncrypt, string publicKey){    Encoding encoder = Encoding.UTF8;    byte[] _dataToEncrypt = encoder.GetBytes(dataToEncrypt);    return this.Encrypt(_dataToEncrypt, publicKey);}/// <summary>/// 加密/// </summary>/// <param name="dataToEncrypt">待加密資料</param>/// <param name="publicKey">公開金鑰</param>/// <returns></returns>public string Encrypt(byte[] dataToEncrypt, string publicKey){    using (RSACryptoServiceProvider RSA = this.CreateEncryptRSA(publicKey))    {        byte[] encryptedData = RSA.Encrypt(dataToEncrypt, false);        return this.BytesToHexString(encryptedData);    }}/// <summary>/// 根據安全性憑證加密/// </summary>/// <param name="dataToEncrypt"></param>/// <param name="certfile"></param>/// <returns></returns>public string X509CertEncrypt(string dataToEncrypt, string certfile){    Encoding encoder = Encoding.UTF8;    byte[] _dataToEncrypt = encoder.GetBytes(dataToEncrypt);    return this.X509CertEncrypt(_dataToEncrypt, certfile);}/// <summary>/// 根據安全性憑證加密/// </summary>/// <param name="dataToEncrypt">待加密資料</param>/// <param name="certfile">安全性憑證</param>/// <returns></returns>public string X509CertEncrypt(byte[] dataToEncrypt, string certfile){    if (!File.Exists(certfile))    {        throw new ArgumentNullException(certfile, "加密認證未找到");    }    using (RSACryptoServiceProvider RSA = this.X509CertCreateEncryptRSA(certfile))    {        byte[] encryptedData = RSA.Encrypt(dataToEncrypt, false);        return this.BytesToHexString(encryptedData);    }}/// <summary>/// 解密/// </summary>/// <param name="encryptedData">待解密資料</param>/// <param name="privateKey">私密金鑰</param>/// <returns></returns>public string Decrypt(string encryptedData, string privateKey){    using (RSACryptoServiceProvider RSA = this.CreateDecryptRSA(privateKey))    {        Encoding encoder = Encoding.UTF8;        byte[] _encryptedData = HexStringToBytes(encryptedData);        byte[] decryptedData = RSA.Decrypt(_encryptedData, false);        return encoder.GetString(decryptedData);    }}/// <summary>/// 解密/// </summary>/// <param name="encryptedData">待解密資料</param>/// <param name="keyfile">私密金鑰檔案</param>/// <param name="password">訪問私密金鑰檔案密碼</param>/// <returns></returns>public string X509CertDecrypt(string encryptedData, string keyfile, string password){    if (!File.Exists(keyfile))    {        throw new ArgumentNullException(keyfile, "解密認證未找到");    }    using (RSACryptoServiceProvider RSA = this.X509CertCreateDecryptRSA(keyfile, password))    {        Encoding encoder = Encoding.UTF8;        byte[] _encryptedData = HexStringToBytes(encryptedData);        byte[] decryptedData = RSA.Decrypt(_encryptedData, false);        return encoder.GetString(decryptedData);    }}

最後整理了一個簡單的Demo:

Demo下載:RSACrypto.rar

 

參考資料:

http://dustin.iteye.com/blog/763931

http://baike.baidu.com/view/539299.htm

http://www.cnblogs.com/yjmyzz/archive/2008/08/20/1272098.html

C# 中使用 RSA加解密演算法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.