因為實際的需求,需要使用 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 生成的密鑰的操作
下載地址: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#解析密鑰
還是之前的代碼,但是私鑰換了
非常正確!!
經過測試,符合要求,感謝使用。