最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c# RSA非對(duì)稱加解密及XML&PEM格式互換方案

 更新時(shí)間:2020年12月31日 09:14:27   作者:夢(mèng)在旅途  
這篇文章主要介紹了c# RSA非對(duì)稱加解密及XML&PEM格式互換方案,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下

最近因考慮接口安全問題,有實(shí)現(xiàn)給WEB API實(shí)現(xiàn)統(tǒng)一的參數(shù)鑒權(quán)功能,以防止請(qǐng)求參數(shù)被篡改或重復(fù)執(zhí)行,參數(shù)鑒權(quán)方法基本與常見的鑒權(quán)思路相同,采用(timestamp+sign),而我為了防止timestamp被更改,sign算法(timestamp+相關(guān)參數(shù)排序、格式化后拼接再M(fèi)D5)也因?yàn)樵谇岸耸遣话踩?,故?duì)timestamp采取使用非對(duì)稱加解密,以盡可能的保證生成的sign不易被破解或替換;

RSA加解密(即:非對(duì)稱加解密)

生成公鑰、私鑰對(duì)方法(C#),生成出來后默認(rèn)都是XML格式:

    public static Tuple<string, string> GeneratePublicAndPrivateKeyPair()
    {
      using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
      {
        string publicKey = rsa.ToXmlString(false); // 公鑰
        string privateKey = rsa.ToXmlString(true); // 私鑰

        return Tuple.Create(publicKey, privateKey);
      }
    }

使用公鑰加密:(支持分段加密,普通單次加密可能會(huì)因?yàn)閮?nèi)容過長(zhǎng)而報(bào)錯(cuò))

public static string RSAEncrypt(string publicKey, string rawInput)
    {
      if (string.IsNullOrEmpty(rawInput))
      {
        return string.Empty;
      }

      if (string.IsNullOrWhiteSpace(publicKey))
      {
        throw new ArgumentException("Invalid Public Key");
      }

      using (var rsaProvider = new RSACryptoServiceProvider())
      {
        var inputBytes = Encoding.UTF8.GetBytes(rawInput);//有含義的字符串轉(zhuǎn)化為字節(jié)流
        rsaProvider.FromXmlString(publicKey);//載入公鑰
        int bufferSize = (rsaProvider.KeySize / 8) - 11;//單塊最大長(zhǎng)度
        var buffer = new byte[bufferSize];
        using (MemoryStream inputStream = new MemoryStream(inputBytes),
           outputStream = new MemoryStream())
        {
          while (true)
          { //分段加密
            int readSize = inputStream.Read(buffer, 0, bufferSize);
            if (readSize <= 0)
            {
              break;
            }

            var temp = new byte[readSize];
            Array.Copy(buffer, 0, temp, 0, readSize);
            var encryptedBytes = rsaProvider.Encrypt(temp, false);
            outputStream.Write(encryptedBytes, 0, encryptedBytes.Length);
          }
          return Convert.ToBase64String(outputStream.ToArray());//轉(zhuǎn)化為字節(jié)流方便傳輸
        }
      }
    }

使用私鑰解密:(支持分段解密,普通單次解密可能會(huì)因?yàn)槊芪倪^長(zhǎng)而報(bào)錯(cuò))

 public static string RSADecrypt(string privateKey,string encryptedInput)
    {
      if (string.IsNullOrEmpty(encryptedInput))
      {
        return string.Empty;
      }

      if (string.IsNullOrWhiteSpace(privateKey))
      {
        throw new ArgumentException("Invalid Private Key");
      }

      using (var rsaProvider = new RSACryptoServiceProvider())
      {
        var inputBytes = Convert.FromBase64String(encryptedInput);
        rsaProvider.FromXmlString(privateKey);
        int bufferSize = rsaProvider.KeySize / 8;
        var buffer = new byte[bufferSize];
        using (MemoryStream inputStream = new MemoryStream(inputBytes),
           outputStream = new MemoryStream())
        {
          while (true)
          {
            int readSize = inputStream.Read(buffer, 0, bufferSize);
            if (readSize <= 0)
            {
              break;
            }

            var temp = new byte[readSize];
            Array.Copy(buffer, 0, temp, 0, readSize);
            var rawBytes = rsaProvider.Decrypt(temp, false);
            outputStream.Write(rawBytes, 0, rawBytes.Length);
          }
          return Encoding.UTF8.GetString(outputStream.ToArray());
        }
      }
    }

如果都是C#項(xiàng)目可能如上兩個(gè)方法就可以了,但如果需要與WEB前端、JAVA等其它編程語言協(xié)同交互處理時(shí)(比如:WEB前端用公鑰加密,后端C#私鑰解密),則可能因?yàn)楣€與私鑰的格式不相同而導(dǎo)致無法正常的進(jìn)行對(duì)接【前端、JAVA 等語言使用的是PEM格式的,而C#使用的是XML格式】,網(wǎng)上查XML轉(zhuǎn)PEM格式方案時(shí),都是復(fù)制自:https://www.cnblogs.com/micenote/p/7862989.html 這篇文章,但其實(shí)這篇文章也只是寫了私鑰XML轉(zhuǎn)PEM格式,并沒有說明公鑰XML如何轉(zhuǎn)PEM格式,而且只寫了支持從文件中獲取內(nèi)容再轉(zhuǎn)換,方案不全,但是給了我思路,我經(jīng)過各種驗(yàn)證,最終實(shí)現(xiàn)了比較友好的PEM與XML格式的相互轉(zhuǎn)換方式,且經(jīng)過單元測(cè)試驗(yàn)證通過,在此分享給大家。

如下是完整的XML與PEM格式轉(zhuǎn)換器類代碼;(注意需引入BouncyCastle nuget包)

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Zuowj.Common
{
  /// <summary>
  /// RSA公鑰、私鑰對(duì)格式(XML與PEM)轉(zhuǎn)換器
  /// author:zuowenjun
  /// date:2020-12-29
  /// </summary>
  public static class RsaKeysFormatConverter
  {
    /// <summary>
    /// XML公鑰轉(zhuǎn)成Pem公鑰
    /// </summary>
    /// <param name="xmlPublicKey"></param>
    /// <returns></returns>
    public static string XmlPublicKeyToPem(string xmlPublicKey)
    {
      RSAParameters rsaParam;
      using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
      {
        rsa.FromXmlString(xmlPublicKey);
        rsaParam = rsa.ExportParameters(false);
      }
      RsaKeyParameters param = new RsaKeyParameters(false, new BigInteger(1, rsaParam.Modulus), new BigInteger(1, rsaParam.Exponent));

      string pemPublicKeyStr = null;
      using (var ms = new MemoryStream())
      {
        using (var sw = new StreamWriter(ms))
        {
          var pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(sw);
          pemWriter.WriteObject(param);
          sw.Flush();

          byte[] buffer = new byte[ms.Length];
          ms.Position = 0;
          ms.Read(buffer, 0, (int)ms.Length);
          pemPublicKeyStr = Encoding.UTF8.GetString(buffer);
        }
      }

      return pemPublicKeyStr;
    }

    /// <summary>
    /// Pem公鑰轉(zhuǎn)成XML公鑰
    /// </summary>
    /// <param name="pemPublicKeyStr"></param>
    /// <returns></returns>
    public static string PemPublicKeyToXml(string pemPublicKeyStr)
    {
      RsaKeyParameters pemPublicKey;
      using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(pemPublicKeyStr)))
      {
        using (var sr = new StreamReader(ms))
        {
          var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sr);
          pemPublicKey = (RsaKeyParameters)pemReader.ReadObject();
        }
      }

      var p = new RSAParameters
      {
        Modulus = pemPublicKey.Modulus.ToByteArrayUnsigned(),
        Exponent = pemPublicKey.Exponent.ToByteArrayUnsigned()
      };

      string xmlPublicKeyStr;
      using (var rsa = new RSACryptoServiceProvider())
      {
        rsa.ImportParameters(p);
        xmlPublicKeyStr = rsa.ToXmlString(false);
      }

      return xmlPublicKeyStr;
    }

    /// <summary>
    /// XML私鑰轉(zhuǎn)成PEM私鑰
    /// </summary>
    /// <param name="xmlPrivateKey"></param>
    /// <returns></returns>
    public static string XmlPrivateKeyToPem(string xmlPrivateKey)
    {
      RSAParameters rsaParam;
      using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
      {
        rsa.FromXmlString(xmlPrivateKey);
        rsaParam = rsa.ExportParameters(true);
      }

      var param = new RsaPrivateCrtKeyParameters(
        new BigInteger(1, rsaParam.Modulus), new BigInteger(1, rsaParam.Exponent), new BigInteger(1, rsaParam.D),
        new BigInteger(1, rsaParam.P), new BigInteger(1, rsaParam.Q), new BigInteger(1, rsaParam.DP), new BigInteger(1, rsaParam.DQ),
        new BigInteger(1, rsaParam.InverseQ));

      string pemPrivateKeyStr = null;
      using (var ms = new MemoryStream())
      {
        using (var sw = new StreamWriter(ms))
        {
          var pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(sw);
          pemWriter.WriteObject(param);
          sw.Flush();

          byte[] buffer = new byte[ms.Length];
          ms.Position = 0;
          ms.Read(buffer, 0, (int)ms.Length);
          pemPrivateKeyStr = Encoding.UTF8.GetString(buffer);
        }
      }

      return pemPrivateKeyStr;
    }

    /// <summary>
    /// Pem私鑰轉(zhuǎn)成XML私鑰
    /// </summary>
    /// <param name="pemPrivateKeyStr"></param>
    /// <returns></returns>
    public static string PemPrivateKeyToXml(string pemPrivateKeyStr)
    {
      RsaPrivateCrtKeyParameters pemPrivateKey;
      using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(pemPrivateKeyStr)))
      {
        using (var sr = new StreamReader(ms))
        {
          var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sr);
          var keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
          pemPrivateKey = (RsaPrivateCrtKeyParameters)keyPair.Private;
        }
      }

      var p = new RSAParameters
      {
        Modulus = pemPrivateKey.Modulus.ToByteArrayUnsigned(),
        Exponent = pemPrivateKey.PublicExponent.ToByteArrayUnsigned(),
        D = pemPrivateKey.Exponent.ToByteArrayUnsigned(),
        P = pemPrivateKey.P.ToByteArrayUnsigned(),
        Q = pemPrivateKey.Q.ToByteArrayUnsigned(),
        DP = pemPrivateKey.DP.ToByteArrayUnsigned(),
        DQ = pemPrivateKey.DQ.ToByteArrayUnsigned(),
        InverseQ = pemPrivateKey.QInv.ToByteArrayUnsigned(),
      };

      string xmlPrivateKeyStr;
      using (var rsa = new RSACryptoServiceProvider())
      {
        rsa.ImportParameters(p);
        xmlPrivateKeyStr = rsa.ToXmlString(true);
      }

      return xmlPrivateKeyStr;
    }

  }
}

如下是單元測(cè)試代碼:

//公鑰(XML、PEM格式互)測(cè)試
string srcPublicKey = “具體的XML Public Key”;
      string pemPublicKeyStr= RsaKeysFormatConverter.XmlPublicKeyToPem(publicKey);
      string xmlPublicKeyStr= RsaKeysFormatConverter.PemPublicKeyToXml(pemPublicKeyStr);
      Assert.AreEqual(srcPublicKey, xmlPublicKeyStr);
//私鑰(XML、PEM格式互)測(cè)試
string srcPrivateKey = “具體的XML Private Key”;
      string pemPrivateKeyStr = RsaKeysFormatConverter.XmlPrivateKeyToPem(srcPrivateKey);
      string xmlPrivateKeyStr = RsaKeysFormatConverter.PemPrivateKeyToXml(pemPrivateKeyStr);
      Assert.AreEqual(privateKey,xmlPrivateKeyStr)

當(dāng)然也可以不用這么費(fèi)勁自己實(shí)現(xiàn)格式轉(zhuǎn)換,可以使用在線網(wǎng)站直接轉(zhuǎn)換:https://the-x.cn/certificate/XmlToPem.aspx ,另外也有一篇文章實(shí)現(xiàn)了類似的功能,但生成的PEM格式并非完整的格式,缺少注釋頭尾:https://www.cnblogs.com/datous/p/RSAKeyConvert.html

以上就是c# RSA非對(duì)稱加解密及XML&PEM格式互換方案的詳細(xì)內(nèi)容,更多關(guān)于c# RSA非對(duì)稱加解密的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#實(shí)現(xiàn)Access通用訪問類OleDbHelper完整實(shí)例

    C#實(shí)現(xiàn)Access通用訪問類OleDbHelper完整實(shí)例

    這篇文章主要介紹了C#實(shí)現(xiàn)Access通用訪問類OleDbHelper,結(jié)合完整實(shí)例形式分析了C#針對(duì)access數(shù)據(jù)庫(kù)的連接、查詢、遍歷、分頁(yè)顯示等相關(guān)操作技巧,需要的朋友可以參考下
    2017-02-02
  • C#通過ADO.NET訪問數(shù)據(jù)的方法詳解

    C#通過ADO.NET訪問數(shù)據(jù)的方法詳解

    在 C# 的應(yīng)用開發(fā)中,數(shù)據(jù)訪問是極為關(guān)鍵的部分,ADO.NET作為.NET 框架下用于數(shù)據(jù)訪問的核心技術(shù),能夠幫助開發(fā)者便捷地與各類數(shù)據(jù)源進(jìn)行交互,本文將深入剖析ADO.NET,帶你掌握使用 C# 通過ADO.NET訪問數(shù)據(jù)的方法,需要的朋友可以參考下
    2025-02-02
  • WPF TextBox水印效果制作方法詳解

    WPF TextBox水印效果制作方法詳解

    這篇文章主要為大家詳細(xì)介紹了WPF TextBox水印效果的制作方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • C#基于正則表達(dá)式實(shí)現(xiàn)獲取網(wǎng)頁(yè)中所有信息的網(wǎng)頁(yè)抓取類實(shí)例

    C#基于正則表達(dá)式實(shí)現(xiàn)獲取網(wǎng)頁(yè)中所有信息的網(wǎng)頁(yè)抓取類實(shí)例

    這篇文章主要介紹了C#基于正則表達(dá)式實(shí)現(xiàn)獲取網(wǎng)頁(yè)中所有信息的網(wǎng)頁(yè)抓取類,結(jié)合完整實(shí)例形式分析了C#正則網(wǎng)頁(yè)抓取類與使用技巧,需要的朋友可以參考下
    2017-05-05
  • C#中閉包概念講解

    C#中閉包概念講解

    這篇文章主要介紹了C#中閉包概念講解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 深入理解StringBuilder的使用方法

    深入理解StringBuilder的使用方法

    下面小編就為大家?guī)硪黄钊肜斫釹tringBuilder的使用方法。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-05-05
  • C#之WinForm跨線程訪問控件實(shí)例

    C#之WinForm跨線程訪問控件實(shí)例

    這篇文章主要介紹了C#之WinForm跨線程訪問控件,實(shí)例講述了跨線程訪問控件的簡(jiǎn)單實(shí)現(xiàn)方法與用法,需要的朋友可以參考下
    2014-10-10
  • C#通過System.CommandLine快速生成支持命令行的應(yīng)用程序

    C#通過System.CommandLine快速生成支持命令行的應(yīng)用程序

    這篇文章介紹了C#通過System.CommandLine快速生成支持命令行應(yīng)用程序的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • C#身份證識(shí)別相關(guān)技術(shù)功能詳解

    C#身份證識(shí)別相關(guān)技術(shù)功能詳解

    這篇文章主要介紹了C#身份證識(shí)別相關(guān)技術(shù)詳解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 基于C#實(shí)現(xiàn)串口通信

    基于C#實(shí)現(xiàn)串口通信

    這篇文章主要為大家詳細(xì)介紹了基于C#實(shí)現(xiàn)串口通信,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評(píng)論

贺兰县| 攀枝花市| 庆安县| 策勒县| 玛纳斯县| 个旧市| 萨迦县| 罗定市| 汶上县| 旌德县| 嘉定区| 土默特右旗| 永寿县| 蒲城县| 扶风县| 荆州市| 集安市| 江城| 怀柔区| 西乌| 平陆县| 朝阳区| 石楼县| 兴业县| 湘西| 益阳市| 无为县| 涞源县| 西平县| 纳雍县| 若羌县| 河池市| 惠水县| 沙河市| 文化| 顺平县| 花莲市| 靖宇县| 库车县| 庄浪县| 万宁市|