zoukankan      html  css  js  c++  java
  • 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:SSLpwd.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#解析密钥

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

     非常正确!!

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

      

  • 相关阅读:
    How can i use iptables on centos 7?
    Running Jenkins behind Nginx
    GPG入门教程
    HTML5 canvas标签-4 灰度直方图的实现
    [转载]手把手用C++解密Chrome80版本数据库
    Delphi
    7-zip Delphi API
    cef对本地web资源打包加密
    CEF3资源重定向、读取加密资源、读取zip资源
    axios设置withCredentials导致“跨域”的解决方案
  • 原文地址:https://www.cnblogs.com/dathlin/p/15227913.html
Copyright © 2011-2022 走看看