您的位置:首页 > 汽车 > 新车 > C#加密与java 互通

C#加密与java 互通

2024/11/15 21:44:15 来源:https://blog.csdn.net/qq_42455262/article/details/139318363  浏览:    关键词:C#加密与java 互通

文章目录

  • 前言
  • 对方接口签名要求
  • 我方对接思路
    • 1.RSA 加密
    • 2.AES256加密
  • 完整的加密帮助类


前言

提示:这里可以添加本文要记录的大概内容:

在我们对接其他公司接口的时候,时常会出现对方使用的开发语言和我方使用的开发语言不同的情况,因为每个语言之间都会有些许差别,在进行加密签名中就会出现签名一直对接不上的问题,下面我就来和各位分享一下我所遇到的问题以及解决方案。


对方接口签名要求

  1. 报文发送方自行产生随机密钥,然后再使用接收方公钥对随机秘钥进行RSA 非对称加密,生成 encrypted。
  2. 按照报文规范生成报文原文,然后对报文原文(JSON 格式字符串)使用 对称密钥字节数组进行 AES256 算法加密,再进行 Base64 编码,生成msg
  3. 再对报文原文进行签名,得到签名结果(十六进制字符串),签名算法采用“SHA1withRSA”,生成 signature

可以看到上面这一堆文字,看似字很少,实则却使用到了很多种加密方式
可以梳理出会用到的加密有:RSA加密,AES256加密,Base64加密,SHA1加密

我方对接思路

1.RSA 加密

由于对方时使用的java,java密钥的key格式和我们C#这边RSA加密使用的key格式不一样,需要进行格式处理也就是下面的“RSAPrivateKeyJava2DotNet”方法。

  public class RSAUtils{/// <summary>/// 生成私钥/// </summary>/// <returns></returns>public static string CreatePrivateKey(){string str = Guid.NewGuid().ToString("N");Byte[] bytes = Encoding.GetEncoding("utf-8").GetBytes(str);byte[] aesKey = new byte[16];for (int i = 0; i < 16; i++){aesKey[i] = bytes[i];}return Convert.ToBase64String(aesKey);}/// <summary>/// 生成密钥/// <param name="privateKey">私钥</param>/// <param name="publicKey">公钥</param>/// <param name="keySize">密钥长度:512,1024,2048,4096,8192</param>/// </summary>public static void Generator(out string privateKey, out string publicKey, int keySize = 1024){RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize);privateKey = rsa.ToXmlString(true); //将RSA算法的私钥导出到字符串PrivateKey中 参数为true表示导出私钥 true 表示同时包含 RSA 公钥和私钥;false 表示仅包含公钥。publicKey = rsa.ToXmlString(false); //将RSA算法的公钥导出到字符串PublicKey中 参数为false表示不导出私钥 true 表示同时包含 RSA 公钥和私钥;false 表示仅包含公钥。}/// <summary>/// RSA加密 将公钥导入到RSA对象中,准备加密/// </summary>/// <param name="publicKey">公钥</param>/// <param name="encryptstring">待加密的字符串</param>public static string RsaEncrypt(string publicKey, string encryptstring){using (var rsaProvider = new RSACryptoServiceProvider()){string key = RSAPublicKeyJava2DotNet(publicKey);var inputBytes = Encoding.UTF8.GetBytes(encryptstring);//有含义的字符串转化为字节流rsaProvider.FromXmlString(key);//载入公钥int bufferSize = (rsaProvider.KeySize / 8) - 11;//单块最大长度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());//转化为字节流方便传输}}}/// <summary>/// Java转.net格式/// </summary>/// <param name="JavaPublicKey">Java格式公钥</param>/// <returns></returns>public static string RSAPublicKeyJava2DotNet(string JavaPublicKey){RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(JavaPublicKey));return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));}/// <summary>/// .NET格式转Java格式/// </summary>/// <param name="cPublicKey">c#的.net格式公钥</param>/// <returns></returns>public static string RSAPublicKeyDotNet2Java(string cPublicKey){XmlDocument doc = new XmlDocument(); doc.LoadXml(cPublicKey);BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));RsaKeyParameters pub = new RsaKeyParameters(false, m, p);SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();return Convert.ToBase64String(serializedPublicBytes);}/// <summary>/// .java格式密钥转c#使用的.net格式密钥/// </summary>/// <param name="JavaPrivateKey">.java密钥</param>/// <returns></returns>public static string RSAPrivateKeyJava2DotNet(string JavaPrivateKey){RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(JavaPrivateKey));return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));}/// <summary>/// c#使用的.net格式密钥转换成.Java格式密钥/// </summary>/// <param name="cPrivateKey">.net格式密钥</param>/// <returns></returns>public static string RSAPrivateKeyDotNet2Java(string cPrivateKey){XmlDocument doc = new XmlDocument();doc.LoadXml(cPrivateKey);BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));BigInteger exp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));BigInteger d = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[0].InnerText));BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[0].InnerText));BigInteger q = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[0].InnerText));BigInteger dp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[0].InnerText));BigInteger dq = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[0].InnerText));BigInteger qinv = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[0].InnerText));RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv);PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();return Convert.ToBase64String(serializedPrivateBytes);}/// <summary>  /// RSA解密 载入私钥,解密数据  /// </summary>  /// <param name="privateKey">私钥</param>  /// <param name="decryptstring">待解密的字符串</param>  public static string RsaDecrypt(string privateKey, string decryptstring){using (var rsaProvider = new RSACryptoServiceProvider()){string key = RSAPrivateKeyJava2DotNet(privateKey);rsaProvider.FromXmlString(key); //载入私钥  var encryptedBytes = Convert.FromBase64String(decryptstring); //将传入的字符串转化为字节流  //var outputStream = new MemoryStream(encryptedBytes);var bufferSize = rsaProvider.KeySize / 8;var buffer = new byte[bufferSize];using (MemoryStream inputStream = new MemoryStream(encryptedBytes), 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 decryptedBytes = rsaProvider.Decrypt(temp, false);outputStream.Write(decryptedBytes, 0, decryptedBytes.Length);}return Encoding.UTF8.GetString(outputStream.ToArray()); //转化为字符串  }}}/// <summary>/// RSA私钥加密/// </summary>/// <param name="privateKey">私钥</param>/// <param name="encryptstring">待加密的字符串</param>public static string RsaPrivateEncrypt(string privateKey, string encryptstring){var rsaProvider = new RSACryptoServiceProvider();rsaProvider.FromXmlString(privateKey);//载入私钥var inputBytes = Convert.FromBase64String(encryptstring);//有含义的字符串转化为字节流int bufferSize = (rsaProvider.KeySize / 8) - 11;//单块最大长度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 = RsaPrivateEncrypt(privateKey, temp);outputStream.Write(encryptedBytes, 0, encryptedBytes.Length);}return Convert.ToBase64String(outputStream.ToArray());//转化为字节流方便传输}}/// <summary>  /// RSA公钥解密/// </summary>  /// <param name="publicKey">公钥</param>  /// <param name="decryptstring">待解密的字符串</param>  public static string RsaPublicDecrypt(string publicKey, string decryptstring){var rsaProvider = new RSACryptoServiceProvider();rsaProvider.FromXmlString(publicKey); //载入私钥  var encryptedBytes = Convert.FromBase64String(decryptstring); //将传入的字符串转化为字节流  var bufferSize = rsaProvider.KeySize / 8;var buffer = new byte[bufferSize];using (MemoryStream inputStream = new MemoryStream(encryptedBytes), 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 decryptedBytes = decryptByPublicKey(publicKey, temp);outputStream.Write(decryptedBytes, 0, decryptedBytes.Length);}return Convert.ToBase64String(outputStream.ToArray());}}/// <summary>/// SHA1 加密,返回大写字符串/// </summary>/// <param name="content">需要加密字符串</param>/// <returns>返回40位UTF8 大写</returns>public static string SHA1(string content){return SHA1(content, Encoding.UTF8);}/// <summary>/// SHA1 加密,返回大写字符串/// </summary>/// <param name="content">需要加密字符串</param>/// <param name="encode">指定加密编码</param>/// <returns>返回40位大写字符串</returns>private static string SHA1(string content, Encoding encode){try{SHA1 sha1 = new SHA1CryptoServiceProvider();byte[] bytes_in = encode.GetBytes(content);byte[] bytes_out = sha1.ComputeHash(bytes_in);sha1.Dispose();string result = BitConverter.ToString(bytes_out);result = result.Replace("-", "");return result;}catch (Exception ex){throw new Exception("SHA1加密出错:" + ex.Message);}}/// <summary>/// 私钥加密/// 这个方法只能加密 私钥长度/8 -11 个字符,分段加密的代码要自己处理了。/// </summary>/// <param name="privateKey">密钥</param>/// <param name="data">要加密的数据</param>/// <returns></returns>public static byte[] RsaPrivateEncrypt(string privateKey, byte[] data){string xmlPrivateKey = privateKey;//加载私钥  RSACryptoServiceProvider privateRsa = new RSACryptoServiceProvider();privateRsa.FromXmlString(xmlPrivateKey);//转换密钥  AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetKeyPair(privateRsa);//IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 参数与Java中加密解密的参数一致       IBufferedCipher c = CipherUtilities.GetCipher("RSA");c.Init(true, keyPair.Private); //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥 byte[] DataToEncrypt = data;byte[] outBytes = c.DoFinal(DataToEncrypt);//加密  return outBytes;}/// <summary>/// 用公钥解密/// 这个方法只能加密 私钥长度/8 -11 个字符,分段加密的代码要自己处理了。/// </summary>/// <param name="data"></param>/// <param name="key"></param>/// <returns></returns>public static byte[] decryptByPublicKey(string publicKey, byte[] data){string xmlPublicKey = publicKey;RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider();publicRsa.FromXmlString(xmlPublicKey);AsymmetricKeyParameter keyPair = DotNetUtilities.GetRsaPublicKey(publicRsa);//转换密钥  // AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetRsaKeyPair(publicRsa);//IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 参数与Java中加密解密的参数一致       IBufferedCipher c = CipherUtilities.GetCipher("RSA");c.Init(false, keyPair); //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥 byte[] DataToEncrypt = data;byte[] outBytes = c.DoFinal(DataToEncrypt);//解密  return outBytes;}}

调用方法

  string pkey= RSAUtils.CreatePrivateKey();encrypt.data.encrypted = RSAUtils.RsaEncrypt(publicKey, pkey);

其中publicKey 是对方公司(JAVA)给我们的公钥,
这里我们生成的KEY是:Q2THHWOD1H4L81DO
加密出来的值是:rZdVr8ksB4EyJ0L6GGjcgHR+XYKwRnxxs+94Hyd/Y52SgqaROFva3DLACjYrzyAHetmGrMpPLKf4TRq0V8F5eDrjZRhOQelA5ogSWRoLwzpN4KZirBc1HCHyrfaEvHDtoJeNabZzKFTDHvNZ94NRQfpHXqABlS7TzOXJKLK1Z/BiQjGuyOGL3xohwhyZ+vgjqNFjpTYU7gqobno5kBK6zoG8B2wilsDP+4hkF7IAn6dAlw8scBMpuULZF6ceBCEakkgWrBYn4E5DiC5c1tz2x3yViBNO+2XV0YdZIrBVkWKZGCWBYVkq53ovyPavuMMyK16HF7CnKlE3RdMc2WvT6g==

这一步我们加密后对方公司的java是能解密出正确明文的。

2.AES256加密

这里问题就来了

下面是错误方法:

        /// <summary>/// AES加密/// </summary>/// <param name="encryptStr">明文</param>/// <param name="key">密钥</param>/// <returns></returns>public static string Encrypt(string encryptStr,string key){byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(encryptStr);RijndaelManaged rDel = new RijndaelManaged();rDel.Key = keyArray;rDel.Mode = CipherMode.ECB;rDel.Padding = PaddingMode.PKCS7;ICryptoTransform cTransform = rDel.CreateEncryptor();byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);return Convert.ToBase64String(resultArray, 0, resultArray.Length);}/// <summary>/// AES解密/// </summary>/// <param name="decryptStr">密文</param>/// <param name="key">密钥</param>/// <returns></returns>public static string Decrypt(string decryptStr,string key){byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);byte[] toEncryptArray = Convert.FromBase64String(decryptStr);RijndaelManaged rDel = new RijndaelManaged();rDel.Key = keyArray;rDel.Mode = CipherMode.ECB;rDel.Padding = PaddingMode.PKCS7;ICryptoTransform cTransform = rDel.CreateDecryptor();byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);return UTF8Encoding.UTF8.GetString(resultArray);}

这种方式加密在网上的在线解密工具都解密不了,只有我们C#写的解密方法能解密,估计是因为填充类型或者其他什么地方有问题。在这里我也困惑了很久

下面是正确方法:

public class AESUtils
{/// <summary>/// AES256加密/// </summary>/// <param name="content">明文</param>/// <param name="passphase">密钥</param>/// <returns></returns>public static string Encrypt(string content, string passphase){byte[] bytes = Encoding.UTF8.GetBytes(content);byte[] key, iv, salt = new byte[8];using (var rng = new RNGCryptoServiceProvider()){rng.GetBytes(salt); }using (var md5 = new MD5CryptoServiceProvider()){var preHash = Encoding.UTF8.GetBytes(passphase).Concat(salt).ToArray();var bs1 = md5.ComputeHash(preHash);var bs2 = md5.ComputeHash(bs1.Concat(preHash).ToArray());var bs3 = md5.ComputeHash(bs2.Concat(preHash).ToArray());key = bs1.Concat(bs2).ToArray();iv = bs3;}using (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })using (var encryptor = aes.CreateEncryptor()){var encryptedBytes = encryptor.TransformFinalBlock(bytes, 0, bytes.Length);var concated = Encoding.UTF8.GetBytes("Salted__").Concat(salt).Concat(encryptedBytes);return Convert.ToBase64String(concated.ToArray());}}/// <summary>/// AES256解密/// </summary>/// <param name="content">密文</param>/// <param name="passphase">密钥</param>/// <returns></returns>public static string Decrypt(string content, string passphase){// openssl aes-256-cbc -k 123456789 -md md5 -e -base64//byte[] bytes = Convert.FromBase64String(content);byte[] key, iv, salt = new byte[8], encryptedBytes = new byte[bytes.Length - 8 - 8];//提取 saltArray.ConstrainedCopy(sourceArray: bytes,sourceIndex: 8, //剔除开头的 "Salted__"destinationArray: salt,destinationIndex: 0,length: salt.Length);//提取 encryptedBytesArray.ConstrainedCopy(sourceArray: bytes,sourceIndex: 8 + 8, //并剔除开头的 saltdestinationArray: encryptedBytes,destinationIndex: 0,length: encryptedBytes.Length);using (var md5 = new MD5CryptoServiceProvider()){var preHash = Encoding.UTF8.GetBytes(passphase).Concat(salt).ToArray();var bs1 = md5.ComputeHash(preHash);var bs2 = md5.ComputeHash(bs1.Concat(preHash).ToArray());var bs3 = md5.ComputeHash(bs2.Concat(preHash).ToArray());key = bs1.Concat(bs2).ToArray();iv = bs3;}using (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })using (var decryptor = aes.CreateDecryptor()){byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);return Encoding.UTF8.GetString(decryptedBytes);}}/// <summary>/// 加密 (新的思路)/// </summary>/// <param name="content">明文</param>/// <param name="passphase">密码(固定32位)</param>/// <returns>密文(base64)</returns>static string CryptoJsEncrypt_New(string content, string passphase ){byte[] bytes = Encoding.UTF8.GetBytes(content);byte[] key = Encoding.UTF8.GetBytes(passphase); //32位的keybyte[] iv = new byte[16];using (var rng = new RNGCryptoServiceProvider())rng.GetBytes(iv); // 产生16个字节的随机ivusing (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })using (var encryptor = aes.CreateEncryptor()){var encryptedBytes = encryptor.TransformFinalBlock(bytes, 0, bytes.Length);var concated = iv.Concat(encryptedBytes);return "aes256:" + Convert.ToBase64String(concated.ToArray());}}/// <summary>/// 解密 (新的思路)/// </summary>/// <param name="content">密文(base64)</param>/// <param name="passphase">密码(固定32位)</param>/// <returns>明文</returns>static string CryptoJsDecrypt_New(string content, string passphase ){byte[] bytes = Convert.FromBase64String(content.Substring(7)); //剔除开头的 "aes256:"byte[] key = Encoding.UTF8.GetBytes(passphase); //32位的keybyte[] iv = new byte[16];byte[] encryptedBytes = new byte[bytes.Length - 16];//提取 ivArray.ConstrainedCopy(sourceArray: bytes,sourceIndex: 0,destinationArray: iv,destinationIndex: 0,length: iv.Length);//提取 加密结果Array.ConstrainedCopy(sourceArray: bytes,sourceIndex: 16, //并剔除开头的 ivdestinationArray: encryptedBytes,destinationIndex: 0,length: encryptedBytes.Length);using (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })using (var decryptor = aes.CreateDecryptor()){byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);return Encoding.UTF8.GetString(decryptedBytes);}}
}

调用方法

AESUtils.Encrypt(datastr, pkey);

加密前明文字符串:
{"storeId":"1788431406828474370","merchantId":"1788027169854296065","tradeNo":"123456","phone":"13366237305","tradeAmount":"5.0","notifyUrl":"http://wx.wjy99.com/onlinemtorder/yunxin/orderMsg","callbackUrl":"http://wx.wjy99.com/onlinemtorder/yunxin/orderMsg","remark":"测试请求"}
加密后密文:
U2FsdGVkX1+FSSnYrXRRcvfDoSeLLPcaA2LEN0/ix7Z41jXIYRdCdIm3DMob+xwvVdMnFwv4iq7LhFxAZcetRHbS3hxhbjObhNvkQrvd79+AnZdEMoM/BGTx66U/c8xtdMheqxrRWoXoIIpfRf++UQCGZBuU5upwMjTmuU3vJKQX/2r5qUHkjH05qkR+ioLb6bvi1FKI6vp3Bs4sKPEKtq+5M26aBdOfo5RmmrSJ023GkvC4DGxlyVn7ac97bBj3X/8h2yfpT1E6zW6FwZIBK+aVPlPFVeKVeXBZwdX5tgpgB+4e6duHPAjArQ1XYRfx2ugNn38IDxwtap7ocBi3GnPB8U4iTXPCz+/7uFutDzIQi0hRVEMpVRqaaaw2Ri2fFV84QYgotJC+qXkKRwyx9g==

这种加密方式,网上的解密都能解开了。


完整的加密帮助类

 using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Xml;namespace HKBSKD.Common
{/// <summary>/// RSA/// </summary>public class RSAUtils{/// <summary>/// 生成私钥/// </summary>/// <returns></returns>public static string CreatePrivateKey(){string str = Guid.NewGuid().ToString("N");Byte[] bytes = Encoding.GetEncoding("utf-8").GetBytes(str);byte[] aesKey = new byte[16];for (int i = 0; i < 16; i++){aesKey[i] = bytes[i];}return Convert.ToBase64String(aesKey);}/// <summary>/// 生成密钥/// <param name="privateKey">私钥</param>/// <param name="publicKey">公钥</param>/// <param name="keySize">密钥长度:512,1024,2048,4096,8192</param>/// </summary>public static void Generator(out string privateKey, out string publicKey, int keySize = 1024){RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize);privateKey = rsa.ToXmlString(true); //将RSA算法的私钥导出到字符串PrivateKey中 参数为true表示导出私钥 true 表示同时包含 RSA 公钥和私钥;false 表示仅包含公钥。publicKey = rsa.ToXmlString(false); //将RSA算法的公钥导出到字符串PublicKey中 参数为false表示不导出私钥 true 表示同时包含 RSA 公钥和私钥;false 表示仅包含公钥。}/// <summary>/// RSA加密 将公钥导入到RSA对象中,准备加密/// </summary>/// <param name="publicKey">公钥</param>/// <param name="encryptstring">待加密的字符串</param>public static string RsaEncrypt(string publicKey, string encryptstring){using (var rsaProvider = new RSACryptoServiceProvider()){string key = RSAPublicKeyJava2DotNet(publicKey);var inputBytes = Encoding.UTF8.GetBytes(encryptstring);//有含义的字符串转化为字节流rsaProvider.FromXmlString(key);//载入公钥int bufferSize = (rsaProvider.KeySize / 8) - 11;//单块最大长度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());//转化为字节流方便传输}}}/// <summary>/// Java转.net格式/// </summary>/// <param name="JavaPublicKey">Java格式公钥</param>/// <returns></returns>public static string RSAPublicKeyJava2DotNet(string JavaPublicKey){RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(JavaPublicKey));return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));}/// <summary>/// .NET格式转Java格式/// </summary>/// <param name="cPublicKey">c#的.net格式公钥</param>/// <returns></returns>public static string RSAPublicKeyDotNet2Java(string cPublicKey){XmlDocument doc = new XmlDocument(); doc.LoadXml(cPublicKey);BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));RsaKeyParameters pub = new RsaKeyParameters(false, m, p);SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();return Convert.ToBase64String(serializedPublicBytes);}/// <summary>/// .java格式密钥转c#使用的.net格式密钥/// </summary>/// <param name="JavaPrivateKey">.java密钥</param>/// <returns></returns>public static string RSAPrivateKeyJava2DotNet(string JavaPrivateKey){RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(JavaPrivateKey));return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));}/// <summary>/// c#使用的.net格式密钥转换成.Java格式密钥/// </summary>/// <param name="cPrivateKey">.net格式密钥</param>/// <returns></returns>public static string RSAPrivateKeyDotNet2Java(string cPrivateKey){XmlDocument doc = new XmlDocument();doc.LoadXml(cPrivateKey);BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));BigInteger exp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));BigInteger d = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[0].InnerText));BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[0].InnerText));BigInteger q = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[0].InnerText));BigInteger dp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[0].InnerText));BigInteger dq = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[0].InnerText));BigInteger qinv = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[0].InnerText));RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv);PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();return Convert.ToBase64String(serializedPrivateBytes);}/// <summary>  /// RSA解密 载入私钥,解密数据  /// </summary>  /// <param name="privateKey">私钥</param>  /// <param name="decryptstring">待解密的字符串</param>  public static string RsaDecrypt(string privateKey, string decryptstring){using (var rsaProvider = new RSACryptoServiceProvider()){string key = RSAPrivateKeyJava2DotNet(privateKey);rsaProvider.FromXmlString(key); //载入私钥  var encryptedBytes = Convert.FromBase64String(decryptstring); //将传入的字符串转化为字节流  //var outputStream = new MemoryStream(encryptedBytes);var bufferSize = rsaProvider.KeySize / 8;var buffer = new byte[bufferSize];using (MemoryStream inputStream = new MemoryStream(encryptedBytes), 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 decryptedBytes = rsaProvider.Decrypt(temp, false);outputStream.Write(decryptedBytes, 0, decryptedBytes.Length);}return Encoding.UTF8.GetString(outputStream.ToArray()); //转化为字符串  }}}/// <summary>/// RSA私钥加密/// </summary>/// <param name="privateKey">私钥</param>/// <param name="encryptstring">待加密的字符串</param>public static string RsaPrivateEncrypt(string privateKey, string encryptstring){var rsaProvider = new RSACryptoServiceProvider();rsaProvider.FromXmlString(privateKey);//载入私钥var inputBytes = Convert.FromBase64String(encryptstring);//有含义的字符串转化为字节流int bufferSize = (rsaProvider.KeySize / 8) - 11;//单块最大长度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 = RsaPrivateEncrypt(privateKey, temp);outputStream.Write(encryptedBytes, 0, encryptedBytes.Length);}return Convert.ToBase64String(outputStream.ToArray());//转化为字节流方便传输}}/// <summary>  /// RSA公钥解密/// </summary>  /// <param name="publicKey">公钥</param>  /// <param name="decryptstring">待解密的字符串</param>  public static string RsaPublicDecrypt(string publicKey, string decryptstring){var rsaProvider = new RSACryptoServiceProvider();rsaProvider.FromXmlString(publicKey); //载入私钥  var encryptedBytes = Convert.FromBase64String(decryptstring); //将传入的字符串转化为字节流  var bufferSize = rsaProvider.KeySize / 8;var buffer = new byte[bufferSize];using (MemoryStream inputStream = new MemoryStream(encryptedBytes), 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 decryptedBytes = decryptByPublicKey(publicKey, temp);outputStream.Write(decryptedBytes, 0, decryptedBytes.Length);}return Convert.ToBase64String(outputStream.ToArray());}}/// <summary>/// SHA1 加密,返回大写字符串/// </summary>/// <param name="content">需要加密字符串</param>/// <returns>返回40位UTF8 大写</returns>public static string SHA1(string content){return SHA1(content, Encoding.UTF8);}/// <summary>/// SHA1 加密,返回大写字符串/// </summary>/// <param name="content">需要加密字符串</param>/// <param name="encode">指定加密编码</param>/// <returns>返回40位大写字符串</returns>private static string SHA1(string content, Encoding encode){try{SHA1 sha1 = new SHA1CryptoServiceProvider();byte[] bytes_in = encode.GetBytes(content);byte[] bytes_out = sha1.ComputeHash(bytes_in);sha1.Dispose();string result = BitConverter.ToString(bytes_out);result = result.Replace("-", "");return result;}catch (Exception ex){throw new Exception("SHA1加密出错:" + ex.Message);}}/// <summary>/// 私钥加密/// 这个方法只能加密 私钥长度/8 -11 个字符,分段加密的代码要自己处理了。/// </summary>/// <param name="privateKey">密钥</param>/// <param name="data">要加密的数据</param>/// <returns></returns>public static byte[] RsaPrivateEncrypt(string privateKey, byte[] data){string xmlPrivateKey = privateKey;//加载私钥  RSACryptoServiceProvider privateRsa = new RSACryptoServiceProvider();privateRsa.FromXmlString(xmlPrivateKey);//转换密钥  AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetKeyPair(privateRsa);//IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 参数与Java中加密解密的参数一致       IBufferedCipher c = CipherUtilities.GetCipher("RSA");c.Init(true, keyPair.Private); //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥 byte[] DataToEncrypt = data;byte[] outBytes = c.DoFinal(DataToEncrypt);//加密  return outBytes;}/// <summary>/// 用公钥解密/// 这个方法只能加密 私钥长度/8 -11 个字符,分段加密的代码要自己处理了。/// </summary>/// <param name="data"></param>/// <param name="key"></param>/// <returns></returns>public static byte[] decryptByPublicKey(string publicKey, byte[] data){string xmlPublicKey = publicKey;RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider();publicRsa.FromXmlString(xmlPublicKey);AsymmetricKeyParameter keyPair = DotNetUtilities.GetRsaPublicKey(publicRsa);//转换密钥  // AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetRsaKeyPair(publicRsa);//IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 参数与Java中加密解密的参数一致       IBufferedCipher c = CipherUtilities.GetCipher("RSA");c.Init(false, keyPair); //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥 byte[] DataToEncrypt = data;byte[] outBytes = c.DoFinal(DataToEncrypt);//解密  return outBytes;}}/// <summary>/// AES /// </summary>public class AESUtils{/// <summary>/// AES加密/// </summary>/// <param name="encryptStr">明文</param>/// <param name="key">密钥</param>/// <returns></returns>public static string Encrypt(string encryptStr, string key){byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(encryptStr);RijndaelManaged rDel = new RijndaelManaged();rDel.Key = keyArray;rDel.Mode = CipherMode.ECB;rDel.Padding = PaddingMode.PKCS7;ICryptoTransform cTransform = rDel.CreateEncryptor();byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);return Convert.ToBase64String(resultArray, 0, resultArray.Length);}/// <summary>/// AES解密/// </summary>/// <param name="decryptStr">密文</param>/// <param name="key">密钥</param>/// <returns></returns>public static string Decrypt(string decryptStr, string key){byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);byte[] toEncryptArray = Convert.FromBase64String(decryptStr);RijndaelManaged rDel = new RijndaelManaged();rDel.Key = keyArray;rDel.Mode = CipherMode.ECB;rDel.Padding = PaddingMode.PKCS7;ICryptoTransform cTransform = rDel.CreateDecryptor();byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);return UTF8Encoding.UTF8.GetString(resultArray);}/// <summary>/// AES256加密/// </summary>/// <param name="content">明文</param>/// <param name="passphase">密钥</param>/// <returns></returns>public static string Encrypt256(string content, string passphase){byte[] bytes = Encoding.UTF8.GetBytes(content);byte[] key, iv, salt = new byte[8];using (var rng = new RNGCryptoServiceProvider()){rng.GetBytes(salt); }using (var md5 = new MD5CryptoServiceProvider()){var preHash = Encoding.UTF8.GetBytes(passphase).Concat(salt).ToArray();var bs1 = md5.ComputeHash(preHash);var bs2 = md5.ComputeHash(bs1.Concat(preHash).ToArray());var bs3 = md5.ComputeHash(bs2.Concat(preHash).ToArray());key = bs1.Concat(bs2).ToArray();iv = bs3;}using (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })using (var encryptor = aes.CreateEncryptor()){var encryptedBytes = encryptor.TransformFinalBlock(bytes, 0, bytes.Length);var concated = Encoding.UTF8.GetBytes("Salted__").Concat(salt).Concat(encryptedBytes);return Convert.ToBase64String(concated.ToArray());}}/// <summary>/// AES256解密/// </summary>/// <param name="content">密文</param>/// <param name="passphase">密钥</param>/// <returns></returns>public static string Decrypt256(string content, string passphase){// openssl aes-256-cbc -k 123456789 -md md5 -e -base64//byte[] bytes = Convert.FromBase64String(content);byte[] key, iv, salt = new byte[8], encryptedBytes = new byte[bytes.Length - 8 - 8];//提取 saltArray.ConstrainedCopy(sourceArray: bytes,sourceIndex: 8, //剔除开头的 "Salted__"destinationArray: salt,destinationIndex: 0,length: salt.Length);//提取 encryptedBytesArray.ConstrainedCopy(sourceArray: bytes,sourceIndex: 8 + 8, //并剔除开头的 saltdestinationArray: encryptedBytes,destinationIndex: 0,length: encryptedBytes.Length);using (var md5 = new MD5CryptoServiceProvider()){var preHash = Encoding.UTF8.GetBytes(passphase).Concat(salt).ToArray();var bs1 = md5.ComputeHash(preHash);var bs2 = md5.ComputeHash(bs1.Concat(preHash).ToArray());var bs3 = md5.ComputeHash(bs2.Concat(preHash).ToArray());key = bs1.Concat(bs2).ToArray();iv = bs3;}using (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })using (var decryptor = aes.CreateDecryptor()){byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);return Encoding.UTF8.GetString(decryptedBytes);}}/// <summary>/// 加密 (新的思路)/// </summary>/// <param name="content">明文</param>/// <param name="passphase">密码(固定32位)</param>/// <returns>密文(base64)</returns>static string CryptoJsEncrypt_New(string content, string passphase ){byte[] bytes = Encoding.UTF8.GetBytes(content);byte[] key = Encoding.UTF8.GetBytes(passphase); //32位的keybyte[] iv = new byte[16];using (var rng = new RNGCryptoServiceProvider())rng.GetBytes(iv); // 产生16个字节的随机ivusing (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })using (var encryptor = aes.CreateEncryptor()){var encryptedBytes = encryptor.TransformFinalBlock(bytes, 0, bytes.Length);var concated = iv.Concat(encryptedBytes);return "aes256:" + Convert.ToBase64String(concated.ToArray());}}/// <summary>/// 解密 (新的思路)/// </summary>/// <param name="content">密文(base64)</param>/// <param name="passphase">密码(固定32位)</param>/// <returns>明文</returns>static string CryptoJsDecrypt_New(string content, string passphase ){byte[] bytes = Convert.FromBase64String(content.Substring(7)); //剔除开头的 "aes256:"byte[] key = Encoding.UTF8.GetBytes(passphase); //32位的keybyte[] iv = new byte[16];byte[] encryptedBytes = new byte[bytes.Length - 16];//提取 ivArray.ConstrainedCopy(sourceArray: bytes,sourceIndex: 0,destinationArray: iv,destinationIndex: 0,length: iv.Length);//提取 加密结果Array.ConstrainedCopy(sourceArray: bytes,sourceIndex: 16, //并剔除开头的 ivdestinationArray: encryptedBytes,destinationIndex: 0,length: encryptedBytes.Length);using (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })using (var decryptor = aes.CreateDecryptor()){byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);return Encoding.UTF8.GetString(decryptedBytes);}}}}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com