SHA256WithRSA

妖狐艹你老母 2023-08-17 16:16 195阅读 0赞

在上文中了解到SHA和RSA,工作中恰好用到扩展应用:SHA256WithRSA,本文总结下学习过程,备忘の
再提供另外一种方法,实现Java版pem密钥和.Net版xml密钥相互转换的方法

密钥转换

准备:引入BouncyCastle.Crypto.dll

  • RSA密钥:Pem —> XML

    public static string RSAKeyPemToXml(string pemKey, bool isPrivateKey)
    {

    1. string rsaKey = string.Empty;
    2. object pemObject = null;
    3. RSAParameters rsaPara = new RSAParameters();
    4. using (var sReader = new StringReader(pemKey)) {
    5. var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sReader);
    6. pemObject = pemReader.ReadObject();//(AsymmetricCipherKeyPair)
    7. }
    8. if (isPrivateKey)//RSA私钥
    9. {
    10. RsaPrivateCrtKeyParameters key = (RsaPrivateCrtKeyParameters)((AsymmetricCipherKeyPair)pemObject).Private;
    11. rsaPara = new RSAParameters {
    12. Modulus = key.Modulus.ToByteArrayUnsigned(),
    13. Exponent = key.PublicExponent.ToByteArrayUnsigned(),
    14. D = key.Exponent.ToByteArrayUnsigned(),
    15. P = key.P.ToByteArrayUnsigned(),
    16. Q = key.Q.ToByteArrayUnsigned(),
    17. DP = key.DP.ToByteArrayUnsigned(),
    18. DQ = key.DQ.ToByteArrayUnsigned(),
    19. InverseQ = key.QInv.ToByteArrayUnsigned(), };
    20. }
    21. else//RSA公钥
    22. {
    23. RsaKeyParameters key = (RsaKeyParameters)pemObject;
    24. rsaPara = new RSAParameters {
    25. Modulus = key.Modulus.ToByteArrayUnsigned(),
    26. Exponent = key.Exponent.ToByteArrayUnsigned(), };
    27. }
    28. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
    29. rsa.ImportParameters(rsaPara);
    30. using (StringWriter sw = new StringWriter()) {
    31. sw.Write(rsa.ToXmlString(isPrivateKey ? true : false));
    32. rsaKey = sw.ToString();
    33. }
    34. return rsaKey;

    }

  • RSA密钥:XML —> Pem

    public static string RSAKeyXmlToPem(string RSAKeyXml, bool isPrivateKey, bool replacefix)
    {

    1. string pemKey = string.Empty;
    2. var rsa = new RSACryptoServiceProvider();
    3. rsa.FromXmlString(RSAKeyXml);
    4. RSAParameters rsaPara = new RSAParameters();
    5. RsaKeyParameters key = null;
    6. //RSA私钥
    7. if (isPrivateKey) {
    8. rsaPara = rsa.ExportParameters(true);
    9. key = new RsaPrivateCrtKeyParameters(
    10. new BigInteger(1, rsaPara.Modulus), new BigInteger(1, rsaPara.Exponent), new BigInteger(1, rsaPara.D),
    11. new BigInteger(1, rsaPara.P), new BigInteger(1, rsaPara.Q), new BigInteger(1, rsaPara.DP), new BigInteger(1, rsaPara.DQ),
    12. new BigInteger(1, rsaPara.InverseQ));
    13. }
    14. //RSA公钥
    15. else {
    16. rsaPara = rsa.ExportParameters(false);
    17. key = new RsaKeyParameters(false,
    18. new BigInteger(1, rsaPara.Modulus), new BigInteger(1, rsaPara.Exponent));
    19. }
    20. using (TextWriter sw = new StringWriter()) {
    21. var pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(sw);
    22. pemWriter.WriteObject(key);
    23. pemWriter.Writer.Flush();
    24. pemKey = sw.ToString();
    25. }
    26. if (replacefix) {
    27. //去掉证书的头部和尾部
    28. pemKey = isPrivateKey ? pemKey.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "") :
    29. pemKey.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "");
    30. return pemKey.Replace("\n", "").Replace("\r", "");
    31. }
    32. else { return pemKey; }

    }

注意,调用RSAKeyPemToXml()方法时,pemKey必须格式正确(带前后缀且换行),否则调用报错。

  1. -----BEGIN RSA PRIVATE KEY-----
  2. ...
  3. -----END RSA PRIVATE KEY-----

此外,调用RSAKeyXmlToPem()方法做私钥转换时,结果与原Pem密钥不一致,慎用。

pfx证书

  • PFX证书:由Public Key Cryptography Standards #12,PKCS#12标准定义,包含公钥和私钥的二进制格式的证书形式,以pfx作为证书文件后缀名
  • CER证书:证书中没有私钥,DER编码二进制格式的证书文件/BASE64编码格式的证书文件,以cer作为证书文件后缀名

综上所述:pfx证书文件中比cer文件中多了私钥。
通过pfx证书实现数据签名和验签

  1. public static string Sign(string dataForSign, string priKeyFile, string keyPwd)
  2. {
  3. var rsa = GetPrivateKey(priKeyFile, keyPwd);
  4. // Create a new RSACryptoServiceProvider
  5. var rsaClear = new RSACryptoServiceProvider();
  6. // Export RSA parameters from 'rsa' and import them into 'rsaClear'
  7. var paras = rsa.ExportParameters(true);
  8. rsaClear.ImportParameters(paras);
  9. using (var sha256 = new SHA256CryptoServiceProvider()) {
  10. var signData = rsaClear.SignData(Encoding.UTF8.GetBytes(dataForSign), sha256);
  11. return BytesToHex(signData);
  12. }
  13. }
  14. public bool VerifySign(string dataForSign, string signedData, string pubKeyFile)
  15. {
  16. var rsa = GetPublicKey(pubKeyFile);
  17. using (var sha256 = new SHA256CryptoServiceProvider()) {
  18. return rsa.VerifyData(Encoding.UTF8.GetBytes(dataForSign), sha256, HexToBytes(signedData));
  19. }
  20. }

其中,从.pfx证书中提取公钥和私钥的方法

  1. private static RSACryptoServiceProvider GetPrivateKey(string priKeyFile, string keyPwd) {
  2. var pc = new X509Certificate2(priKeyFile, keyPwd,
  3. X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
  4. return (RSACryptoServiceProvider)pc.PrivateKey; //return cert.PrivateKey.ToXmlString(true);
  5. }
  6. private static RSACryptoServiceProvider GetPublicKey(string pubKeyFile) {
  7. var pc = new X509Certificate2(pubKeyFile);
  8. return (RSACryptoServiceProvider)pc.PublicKey.Key; //return cert.PublicKey.Key.ToXmlString(false);
  9. }

具体参见:.NET版SHA256WithRSA签名验签,java版本参见:java版SHA256withRSA
关于如何生成数字证书,仅供参考:方法1,方法2
该文C#创建数字证书并导出为pfx,并使用pfx进行非对称加解密有时间可以研究下。

转载于:https://www.cnblogs.com/wjcx-sqh/p/11580450.html

发表评论

表情:
评论列表 (有 0 条评论,195人围观)

还没有评论,来说两句吧...

相关阅读

    相关 SHA256WithRSA

    在[上文][Link 1]中了解到SHA和RSA,工作中恰好用到扩展应用:SHA256WithRSA,本文总结下学习过程,备忘の 再提供另外一种方法,实现Java版pem密