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#解析密钥

 

 

 还是之前的代码,但是私钥换了

 

 非常正确!!

经过测试,符合要求,感谢使用。

 

  

 

posted @ 2021-09-04 21:41  dathlin  阅读(3801)  评论(0编辑  收藏  举报