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#里都是这么使用的,假如我们需要对密码进行加密操作
1 2 3 4 5 6 7 8 9 10 | // 包含公钥和私钥的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 ); |
这就是用同一个的密钥进行加密解密操作。但是通常时候,我们会把公钥给客户端,客户端加密之后,把密码发送给服务器,服务器实现解密,然后进行其他的操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 包含公钥和私钥的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
安装好之后,我们就可以进行操作了
我先生成一个私钥
1 | openssl genrsa - out test.key 1024 |
我们再生成一个公钥
1 | openssl rsa - in test.key -pubout - out test_pub.key |
好了,我们公钥私钥都有了,这时候已经可以加密解密了。
我们创建一个文件 pwd.txt 存储个密码 123456
文本文件编码为UTF8
我们现在可以进行加密操作了
1 | 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了,现在继续操作
1 2 | using System.Security.Cryptography; using HslCommunication.Core.Security; |
只要using这两个就可以了,如果需要扩展方法,最好再using一个
1 | using HslCommunication; |
代码里应该怎么写呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 把私钥拷贝过来,就可以对数据进行解析了。 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对象呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // 把公钥数据拷贝过来,就可以加密了 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的公钥私钥数据呢?
1 2 3 4 5 6 7 8 9 10 11 | // 生成一个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文件路径下
重新加密解密看看
1 | openssl rsautl -encrypt - in pwd.txt -inkey test_pub.key -pubin - out pwd.en |
解密
1 | openssl rsautl -decrypt - in pwd.en -inkey test.key - out pwd1.txt |
可以看到非常的准确,再尝试下,C#解析密钥
还是之前的代码,但是私钥换了
非常正确!!
经过测试,符合要求,感谢使用。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构