C# RSA加密解密 使用Openssl密鑰 XML格式密鑰和 openssl pem格式密鑰互轉, C#RSA獲取PEM格式密鑰


因為實際的需求,需要使用 RSA 的非對稱加密信息。所以有了這邊文章,簡單的說下什么是非對稱加密:

非對稱加密RSA

簡介: 
1. 對稱加密算法又稱現代加密算法。 
2. 非對稱加密是計算機通信安全的基石,保證了加密數據不會被破解。 
3. 非對稱加密算法需要兩個密鑰:公開密鑰(publickey) 和私有密(privatekey) 
4. 公開密鑰和私有密鑰是一對

如果用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密。 
如果用私有密鑰對數據進行加密,只有用對應的私有密鑰才能解密。

特點: 
算法強度復雜,安全性依賴於算法與密鑰。 
加密解密速度慢。

與對稱加密算法的對比: 
對稱加密只有一種密鑰,並且是非公開的,如果要解密就得讓對方知道密鑰。 
非對稱加密有兩種密鑰,其中一個是公開的。

RSA應用場景: 
由於RSA算法的加密解密速度要比對稱算法速度慢很多,在實際應用中,通常采取 
數據本身的加密和解密使用對稱加密算法(AES)。 
用RSA算法加密並傳輸對稱算法所需的密鑰。

這部分的內容可以參考下面的博客,我從這個博客里受益良多。

https://www.cnblogs.com/shoshana-kong/p/10934550.html

 

好了正式開始今天的內容

一般我們在C#里都是這么使用的,假如我們需要對密碼進行加密操作

			// 包含公鑰和私鑰的rsa對象
			RSACryptoServiceProvider RSA = new RSACryptoServiceProvider( );
			// 等待加密的密碼
			byte[] password = Encoding.UTF8.GetBytes( "123456" );
			// 對密碼進行加密
			byte[] encrypt = RSA.Encrypt( password, false );

			// 對密碼進行解密
			string password2 = Encoding.UTF8.GetString( RSA.Decrypt( encrypt, false ) );
			Console.WriteLine( password2 );

 

這就是用同一個的密鑰進行加密解密操作。但是通常時候,我們會把公鑰給客戶端,客戶端加密之后,把密碼發送給服務器,服務器實現解密,然后進行其他的操作。

 

			// 包含公鑰和私鑰的rsa對象
			RSACryptoServiceProvider RSA = new RSACryptoServiceProvider( );
			// 生成公鑰給客戶端使用,注意,就是XML格式的
			string publicKey = RSA.ToXmlString( false );
			Console.WriteLine( publicKey );

			// 客戶端進行加密操作
			RSACryptoServiceProvider RsaClient = new RSACryptoServiceProvider( );
			RsaClient.FromXmlString( publicKey );
			// 等待加密的密碼
			byte[] password = Encoding.UTF8.GetBytes( "123456" );
			// 對密碼進行加密
			byte[] encrypt = RsaClient.Encrypt( password, false );

			// 服務器端收到 encrypt 對密碼進行解密
			string password2 = Encoding.UTF8.GetString( RSA.Decrypt( encrypt, false ) );
			Console.WriteLine( password2 );

  運行之后看看

 

 

 

可以,沒有什么問題,接下來,我們看看標准的 OPENSSL 生成的密鑰的操作

官網:https://www.openssl.org/

下載地址:http://slproweb.com/download/Win64OpenSSL_Light-1_1_1L.msi

安裝好之后,我們就可以進行操作了

 

 

 

 

我先生成一個私鑰

openssl genrsa -out test.key 1024

 

 

 我們再生成一個公鑰

openssl rsa -in test.key -pubout -out test_pub.key

 

 

好了,我們公鑰私鑰都有了,這時候已經可以加密解密了。

我們創建一個文件 pwd.txt  存儲個密碼 123456

 

 文本文件編碼為UTF8

我們現在可以進行加密操作了

openssl rsautl -encrypt -in pwd.txt -inkey test_pub.key -pubin -out pwd.en

  執行之后就加密成功了

 

 

好了,加密成功了,現在我們來看下這個密鑰信息,先看私鑰

 

 公鑰

 

 

 emmmm,好像和我們在C#看到的密鑰不一樣啊,我想在C#里,也使用這個公鑰私鑰,怎么辦????

 

 

在經過我幾天的研究之后,給大家提供了一個庫,來快速方便的解決這個問題

就是大名鼎鼎的 HslCommunication

至於如何安裝,可以參考下面的文章:

如果需要教程:Nuget安裝教程:http://www.cnblogs.com/dathlin/p/7705014.html

組件的api地址:http://api.hslcommunication.cn

 

有個demo程序的源代碼:

https://github.com/dathlin/HslCommunication

在demo里提供了測試的界面

 

 

好了,想必您已經安裝了HslCommunication了,現在繼續操作

using System.Security.Cryptography;
using HslCommunication.Core.Security;

  

只要using這兩個就可以了,如果需要擴展方法,最好再using一個

using HslCommunication;

  

代碼里應該怎么寫呢?

			// 把私鑰拷貝過來,就可以對數據進行解析了。
			RSACryptoServiceProvider rsa = RSAHelper.CreateRsaProviderFromPrivateKey( @"-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCedjrK/6w7gMapQsN/vyvvohbeLfdEZ/hk3AP6QeKa0D7S8cCa
dOhbM279wXPwwH7S9zLMpEl6BPYk2V0uZzjyMgAQl5dTZZj4esgoJJ9fpHFJlo0/
mSRzv848/s+UmNniYZN7n8764HMZr5C5J67Ky0QOVHPBUMrvrxmXpFJ7zQIDAQAB
AoGAebqnVZRtEdTOR+6S0krgjJi+6nTzM6iPJ6PgploAox8Ac/nlFIJkkNMFG4iF
8Vde1d+yNYSrMUIoeIxGScRf+HBngpjSD2Zmdv1yOT2BaULxv+O4HIG5KUt9X+WW
FrwB0KYNnSR5ggwFIuUSY9kEdEghvE7mAbTCImwCQVHhD50CQQDTJLEwWz+nlldI
Z4fVr2mPPJYW+MVe2Zj4f8wMQUct3c/Ys6a3XG9yO+qGUjMrZQD0jXLoTNeJSSW9
3XqAU97LAkEAwCBilv5yY/ZTyNV5WqzTiglrUhm7R6RZWAUIjeztCwT1Hn3UQbW1
aK1aXIoV6sEAsmbfmQekmvgSvLrJnCtkxwJBAKaxZSIkKBEK5EXJVrghEFmBH41r
QYcsi1REsLdMIgHYCGuxCYHhfCrXmsQIyVUNHL/1nC5B3DgKg71tyXTewhkCQA+J
ju+PHEkhPp1bRjkjCOh84oT9N7wPeno3zf1MT884U2pn2qaFv2n7uvcI48TcXuYO
k76Yc6NktH82y98pUzkCQDd5JRD2McDLPkAIJERk7lSgkxyt0a8lpD8o/kKYBLtO
am6KPGMGIhEOpgsRXMJYCk7v9gFoPWhcxX4RsMlhsk8=
-----END RSA PRIVATE KEY-----" );
			Console.WriteLine( Encoding.UTF8.GetString( rsa.Decrypt( File.ReadAllBytes( @"E:\SSL\pwd.en" ), false ) ) );

  運行一下,看看結果

 

 

 

 

 

如何創建公鑰的RSA對象呢?

			// 把公鑰數據拷貝過來,就可以加密了
			RSACryptoServiceProvider rsaPublic = RSAHelper.CreateRsaProviderFromPublicKey( @"-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCedjrK/6w7gMapQsN/vyvvohbe
LfdEZ/hk3AP6QeKa0D7S8cCadOhbM279wXPwwH7S9zLMpEl6BPYk2V0uZzjyMgAQ
l5dTZZj4esgoJJ9fpHFJlo0/mSRzv848/s+UmNniYZN7n8764HMZr5C5J67Ky0QO
VHPBUMrvrxmXpFJ7zQIDAQAB
-----END PUBLIC KEY-----" );
			// 我隨便加密個數據
			string pwd = "在座的都是帥哥美女";
			byte[] encrypt = rsaPublic.Encrypt( Encoding.UTF8.GetBytes( pwd ), false );

			// 對上面的加密數據進行解析
			// 把私鑰拷貝過來,就可以對數據進行解析了。
			RSACryptoServiceProvider rsa = RSAHelper.CreateRsaProviderFromPrivateKey( @"-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCedjrK/6w7gMapQsN/vyvvohbeLfdEZ/hk3AP6QeKa0D7S8cCa
dOhbM279wXPwwH7S9zLMpEl6BPYk2V0uZzjyMgAQl5dTZZj4esgoJJ9fpHFJlo0/
mSRzv848/s+UmNniYZN7n8764HMZr5C5J67Ky0QOVHPBUMrvrxmXpFJ7zQIDAQAB
AoGAebqnVZRtEdTOR+6S0krgjJi+6nTzM6iPJ6PgploAox8Ac/nlFIJkkNMFG4iF
8Vde1d+yNYSrMUIoeIxGScRf+HBngpjSD2Zmdv1yOT2BaULxv+O4HIG5KUt9X+WW
FrwB0KYNnSR5ggwFIuUSY9kEdEghvE7mAbTCImwCQVHhD50CQQDTJLEwWz+nlldI
Z4fVr2mPPJYW+MVe2Zj4f8wMQUct3c/Ys6a3XG9yO+qGUjMrZQD0jXLoTNeJSSW9
3XqAU97LAkEAwCBilv5yY/ZTyNV5WqzTiglrUhm7R6RZWAUIjeztCwT1Hn3UQbW1
aK1aXIoV6sEAsmbfmQekmvgSvLrJnCtkxwJBAKaxZSIkKBEK5EXJVrghEFmBH41r
QYcsi1REsLdMIgHYCGuxCYHhfCrXmsQIyVUNHL/1nC5B3DgKg71tyXTewhkCQA+J
ju+PHEkhPp1bRjkjCOh84oT9N7wPeno3zf1MT884U2pn2qaFv2n7uvcI48TcXuYO
k76Yc6NktH82y98pUzkCQDd5JRD2McDLPkAIJERk7lSgkxyt0a8lpD8o/kKYBLtO
am6KPGMGIhEOpgsRXMJYCk7v9gFoPWhcxX4RsMlhsk8=
-----END RSA PRIVATE KEY-----" );
			Console.WriteLine( Encoding.UTF8.GetString( rsa.Decrypt( encrypt, false ) ) );

  在運行下

 

 

這樣通過openssl或是其他的程序生成的公鑰私鑰,都可以給C#使用了。

還有個細節是

當C#生成一個RSA對象之后,就默認創建了公鑰私鑰了。雖然C#提供了導出XML格式的公鑰私鑰,但是這不是我們想要的,或是提供給別人,就蒙圈了

那么如何導出PEM的公鑰私鑰數據呢?

			// 生成一個rsa算法的私鑰和公鑰
			RSACryptoServiceProvider rsa = new RSACryptoServiceProvider( 1024 );
			// 下面兩種方法都可以導出私鑰的
			// byte[] privateKey = RSAHelper.GetPrivateKeyFromRSA( rsa );
			byte[] privateKey = rsa.GetPEMPrivateKey( );
			Console.WriteLine( Convert.ToBase64String( privateKey ) );
			// 導出公鑰
			// byte[] publicKey = RSAHelper.GetPublicKeyFromRSA( rsa );
			byte[] publicKey = rsa.GetPEMPublicKey( );
			Console.WriteLine( "==============================以下是公鑰" );
			Console.WriteLine( Convert.ToBase64String( publicKey ) );

  

 運行一下看看

 

 

這個密鑰生成到底對不對呢?

我們把密鑰拷貝到SSL文件路徑下

 

 重新加密解密看看

openssl rsautl -encrypt -in pwd.txt -inkey test_pub.key -pubin -out pwd.en

  解密

openssl rsautl -decrypt -in pwd.en -inkey test.key -out pwd1.txt

 

 可以看到非常的准確,再嘗試下,C#解析密鑰

 

 

 還是之前的代碼,但是私鑰換了

 

 非常正確!!

經過測試,符合要求,感謝使用。

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM