当前位置: 首页 > news >正文

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==

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


完整的加密帮助类

  /// <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>/// 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);}}}

相关文章:

  • 【运维项目经历|023】Docker自动化部署与监控项目
  • 幼儿园机器人编程介绍自己
  • Debug linux kernel
  • 【LeetCode算法】第101题:对称二叉树
  • 【wiki知识库】02.wiki知识库SpringBoot后端的准备
  • Nacos-SpringBoot-配置中心
  • 《QT实用小工具·六十九》基于QT开发的五子棋AI游戏
  • MySQL统计字符长度:CHAR_LENGTH(str)
  • 数据结构的快速排序(c语言版)
  • 区块链会议投稿资讯CCF A--USENIX Security 2025 截止9.4、1.22 附录用率
  • 失之毫厘差之千里之load和loads
  • BetterZip — 满足你工作中的解压缩需求
  • java.lang.NoClassDefFoundError: org/dom4j/io/SAXReader
  • jmeter基础入门练习题
  • 【银河麒麟V10服务器OS-系统根分区扩容】指导教程手册
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Bytom交易说明(账户管理模式)
  • iOS小技巧之UIImagePickerController实现头像选择
  • Java IO学习笔记一
  • java8 Stream Pipelines 浅析
  • Javascript Math对象和Date对象常用方法详解
  • js写一个简单的选项卡
  • learning koa2.x
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • vuex 笔记整理
  • vue学习系列(二)vue-cli
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 力扣(LeetCode)965
  • 模仿 Go Sort 排序接口实现的自定义排序
  • 如何使用 JavaScript 解析 URL
  • 手写一个CommonJS打包工具(一)
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 微信小程序开发问题汇总
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • #知识分享#笔记#学习方法
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • (152)时序收敛--->(02)时序收敛二
  • (2)STL算法之元素计数
  • (3) cmake编译多个cpp文件
  • (a /b)*c的值
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (二)WCF的Binding模型
  • (二)延时任务篇——通过redis的key监听,实现延迟任务实战
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (原創) 未来三学期想要修的课 (日記)
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • .config、Kconfig、***_defconfig之间的关系和工作原理
  • .libPaths()设置包加载目录
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?