.Net加密與Java互通

.Net加密與Java互通


文章目錄

  • .Net加密與Java互通
  • 前言
  • RSA
    • 生成私鑰和公鑰
    • .net加密出數據傳給Java端
      • 采用java方給出的公鑰進行加密
      • 采用java方給出的私鑰進行解密
    • .net 解密來自Java端的數據
  • AES
    • 帶有向量的AES加密
    • 帶有向量的AES解密
    • 無向量AES加密
    • 無向量AES解密
  • SM2(國密)
    • SM2加密
    • Sm2解密
    • 生成密鑰串
  • SM3加密
  • MD5加密
  • Base64
    • Base64加密
    • Base64解密
  • DES
    • DES加密
    • DES解密
  • SHA1
  • 總結


前言

在接口對接過程中我們常常會遇到需要加密和簽名等情況,像經典的RSA,AES,SM2,SM3,各個語言之間的加密都有些小差異,接下來我就總結一下我做.net開發中與java接口對接時發現的差異與解決辦法。


提示:以下是本篇文章正文內容,下面案例可供參考

RSA

這里我們需要引用 Portable.BouncyCastle 包
在這里插入圖片描述
總所周知RSA加密是對稱加密也就是說在進行加密和解密過程中會用到公鑰私鑰一般來說,我們都是將私鑰留下,將公鑰送給對方,當對方拿到我們的公鑰之后,他們傳輸給我們數據的時候需要用公鑰進行加密,我方接收到信息之后,再用我們留下的這個私鑰進行解密。大概流程如下
在這里插入圖片描述
再此次討論中,我們把A方設定為.net后臺,B方設定為java

這里的重點是他們之間的轉換方法

/// <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 Org.BouncyCastle.Math.BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));BigInteger p = new Org.BouncyCastle.Math.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#(私鑰)/// </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>/// .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);}

生成私鑰和公鑰

這里展示的是.net的密鑰生成方法

  /// <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 表示僅包含公鑰。}

.net加密出數據傳給Java端

采用java方給出的公鑰進行加密

    public static string RSAEncryptByJavaPublicKey(string javaPublicKey, string data){string xml = Pem2XmlPublic(javaPublicKey);RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();rsa.FromXmlString(xml);// 加密using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()){byte[] dataToEncrypt = Encoding.UTF8.GetBytes(data);byte[] digest = sha1.ComputeHash(dataToEncrypt);// 使用RSA的OAEP填充進行加密return Convert.ToBase64String(rsa.Encrypt(digest, false));}}/// <summary>/// RSA公鑰格式轉換,java->.net/// </summary>/// <param name="keyInfoData">java生成的公鑰</param>/// <returns>.net公鑰</returns>private static string RSAPublicKeyJava2DotNet(byte[] keyInfoData){RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(keyInfoData);return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));}private static string Pem2XmlPublic(string pemFileConent){pemFileConent = pemFileConent.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");var data = Convert.FromBase64String(pemFileConent);return RSAPublicKeyJava2DotNet(data);}

采用java方給出的私鑰進行解密

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

.net 解密來自Java端的數據

注意這里解密的數據是java端采用.net提供的公鑰進行加密后的數據。

//將之前生成的Base64字符串轉為Xml格式private static string ToXmlPrivateKey(string privateKey){RsaPrivateCrtKeyParameters privateKeyParams =PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey)) as RsaPrivateCrtKeyParameters;using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()){RSAParameters rsaParams = new RSAParameters(){Modulus = privateKeyParams.Modulus.ToByteArrayUnsigned(),Exponent = privateKeyParams.PublicExponent.ToByteArrayUnsigned(),D = privateKeyParams.Exponent.ToByteArrayUnsigned(),DP = privateKeyParams.DP.ToByteArrayUnsigned(),DQ = privateKeyParams.DQ.ToByteArrayUnsigned(),P = privateKeyParams.P.ToByteArrayUnsigned(),Q = privateKeyParams.Q.ToByteArrayUnsigned(),InverseQ = privateKeyParams.QInv.ToByteArrayUnsigned()};rsa.ImportParameters(rsaParams);return rsa.ToXmlString(true);}}public string RSADecrypt(string PrivateKey, string decryptString)  {  try  {  string xmlPrivateKey=ToXmlPrivateKey(PrivateKey);byte[] PlainTextBArray;  byte[] DypherTextBArray;  string Result;  System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();  rsa.FromXmlString(xmlPrivateKey);  PlainTextBArray = Convert.FromBase64String(decryptString);  DypherTextBArray = rsa.Decrypt(PlainTextBArray, false);  Result = (new UnicodeEncoding()).GetString(DypherTextBArray);  return Result;  }  catch (Exception ex)  {  throw ex;  }  }  

AES

帶有向量的AES加密

    /// <summary>/// AES加密/// </summary>/// <param name="text">明文字符串</param>/// <param name="key">秘鑰</param>/// <param name="iv">加密輔助向量</param>/// <returns>密文</returns>public static string AESEncrypt(string text, string key, string iv){RijndaelManaged rijndaelCipher = new RijndaelManaged();rijndaelCipher.Mode = CipherMode.CBC;rijndaelCipher.Padding = PaddingMode.PKCS7;rijndaelCipher.KeySize = 128;rijndaelCipher.BlockSize = 128;byte[] pwdBytes = System.Text.Encoding.UTF8.GetBytes(key);byte[] keyBytes = new byte[16];int len = pwdBytes.Length;if (len > keyBytes.Length) len = keyBytes.Length;System.Array.Copy(pwdBytes, keyBytes, len);rijndaelCipher.Key = keyBytes;byte[] ivBytes = System.Text.Encoding.UTF8.GetBytes(iv);rijndaelCipher.IV = ivBytes;ICryptoTransform transform = rijndaelCipher.CreateEncryptor();byte[] plainText = Encoding.UTF8.GetBytes(text);byte[] cipherBytes = transform.TransformFinalBlock(plainText, 0, plainText.Length);return Convert.ToBase64String(cipherBytes);}

帶有向量的AES解密

/// <summary>
/// AES解密
/// </summary>
/// <param name="text">加密字符串</param>
/// <param name="key">秘鑰</param>
/// <param name="iv">加密輔助向量</param>
/// <returns>明文</returns>
public static string AESDecrypt(string text, string key, string iv)
{try{///空格替換為+ 否則解密會失敗byte[] EncryptedBytes = Convert.FromBase64String(text.Replace(" ", "+"));//Setup the AES provider for decrypting.            AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();aesProvider.Key = System.Text.Encoding.UTF8.GetBytes(key);aesProvider.IV = System.Text.Encoding.UTF8.GetBytes(iv);aesProvider.Padding = PaddingMode.None;aesProvider.Mode = CipherMode.CBC;ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor(aesProvider.Key, aesProvider.IV);byte[] DecryptedBytes = cryptoTransform.TransformFinalBlock(EncryptedBytes, 0, EncryptedBytes.Length);string result = System.Text.Encoding.UTF8.GetString(DecryptedBytes).Replace("\0", "");return result;}catch(Exception ex){return ex.Message;}
}

無向量AES加密

 /// <summary>/// AES加密(無向量)/// </summary>/// <param name="plainBytes">被加密的明文</param>/// <param name="key">密鑰</param>/// <returns>密文</returns>public static string AESEncrypt(string Data, string Key,int KeySize=128){MemoryStream mStream = new MemoryStream();RijndaelManaged aes = new RijndaelManaged();byte[] plainBytes = Encoding.UTF8.GetBytes(Data);Byte[] bKey = new Byte[32];Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);aes.Mode = CipherMode.ECB;aes.Padding = PaddingMode.PKCS7;aes.KeySize = KeySize;//aes.Key = _key;aes.Key = bKey;//aes.IV = _iV;CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateEncryptor(), CryptoStreamMode.Write);try{cryptoStream.Write(plainBytes, 0, plainBytes.Length);cryptoStream.FlushFinalBlock();return Convert.ToBase64String(mStream.ToArray());}finally{cryptoStream.Close();mStream.Close();aes.Clear();}}

無向量AES解密

 /// <summary>/// AES解密(無向量)/// </summary>/// <param name="encryptedBytes">被加密的明文</param>/// <param name="key">密鑰</param>/// <returns>明文</returns>public static string AESDecrypt(string Data, string Key){Byte[] encryptedBytes = Convert.FromBase64String(Data);Byte[] bKey = new Byte[32];Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);MemoryStream mStream = new MemoryStream(encryptedBytes);//mStream.Write( encryptedBytes, 0, encryptedBytes.Length );//mStream.Seek( 0, SeekOrigin.Begin );RijndaelManaged aes = new RijndaelManaged();aes.Mode = CipherMode.ECB;aes.Padding = PaddingMode.PKCS7;aes.KeySize = 128;aes.Key = bKey;//aes.IV = _iV;CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateDecryptor(), CryptoStreamMode.Read);try{byte[] tmp = new byte[encryptedBytes.Length + 32];int len = cryptoStream.Read(tmp, 0, encryptedBytes.Length + 32);byte[] ret = new byte[len];Array.Copy(tmp, 0, ret, 0, len);return Encoding.UTF8.GetString(ret);}finally{cryptoStream.Close();mStream.Close();aes.Clear();}}

SM2(國密)

這里我要分享的也是java和.net之間互相傳遞過程中的細節問題
這里要用到:BouncyCastle.Crypto包
下載地址:https://www.bouncycastle.org/download/bouncy-castle-c/

以下是相關幫助類

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.GM;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.X509;
using System;
using System.Collections.Generic;
using System.IO;namespace CommonUtils
{/*** 用BC的注意點:* 這個版本的BC對SM3withSM2的結果為asn1格式的r和s,如果需要直接拼接的r||s需要自己轉換。下面rsAsn1ToPlainByteArray、rsPlainByteArrayToAsn1就在干這事。* 這個版本的BC對SM2的結果為C1||C2||C3,據說為舊標準,新標準為C1||C3||C2,用新標準的需要自己轉換。下面(被注釋掉的)changeC1C2C3ToC1C3C2、changeC1C3C2ToC1C2C3就在干這事。java版的高版本有加上C1C3C2,csharp版沒準以后也會加,但目前還沒有,java版的目前可以初始化時“ SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);”。* * 按要求國密算法僅允許使用加密機,本demo國密算法僅供學習使用,請不要用于生產用途。*/public class GmUtil{//private static readonly ILog log = LogManager.GetLogger(typeof(GmUtil));private static X9ECParameters x9ECParameters = GMNamedCurves.GetByName("sm2p256v1");private static ECDomainParameters ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);/**** @param msg* @param userId* @param privateKey* @return r||s,直接拼接byte數組的rs*/public static byte[] SignSm3WithSm2(byte[] msg, byte[] userId, AsymmetricKeyParameter privateKey){return RsAsn1ToPlainByteArray(SignSm3WithSm2Asn1Rs(msg, userId, privateKey));}/*** @param msg* @param userId* @param privateKey* @return rs in <b>asn1 format</b>*/public static byte[] SignSm3WithSm2Asn1Rs(byte[] msg, byte[] userId, AsymmetricKeyParameter privateKey){try{ISigner signer = SignerUtilities.GetSigner("SM3withSM2");signer.Init(true, new ParametersWithID(privateKey, userId));signer.BlockUpdate(msg, 0, msg.Length);byte[] sig = signer.GenerateSignature();return sig;}catch (Exception e){//log.Error("SignSm3WithSm2Asn1Rs error: " + e.Message, e);return null;}}/**** @param msg* @param userId* @param rs r||s,直接拼接byte數組的rs* @param publicKey* @return*/public static bool VerifySm3WithSm2(byte[] msg, byte[] userId, byte[] rs, AsymmetricKeyParameter publicKey){if (rs == null || msg == null || userId == null) return false;if (rs.Length != RS_LEN * 2) return false;return VerifySm3WithSm2Asn1Rs(msg, userId, RsPlainByteArrayToAsn1(rs), publicKey);}/**** @param msg* @param userId* @param rs in <b>asn1 format</b>* @param publicKey* @return*/public static bool VerifySm3WithSm2Asn1Rs(byte[] msg, byte[] userId, byte[] sign, AsymmetricKeyParameter publicKey){try{ISigner signer = SignerUtilities.GetSigner("SM3withSM2");signer.Init(false, new ParametersWithID(publicKey, userId));signer.BlockUpdate(msg, 0, msg.Length);return signer.VerifySignature(sign);}catch (Exception e){//log.Error("VerifySm3WithSm2Asn1Rs error: " + e.Message, e);return false;}}/*** bc加解密使用舊標c1||c2||c3,此方法在加密后調用,將結果轉化為c1||c3||c2* @param c1c2c3* @return*/private static byte[] ChangeC1C2C3ToC1C3C2(byte[] c1c2c3){int c1Len = (x9ECParameters.Curve.FieldSize + 7) / 8 * 2 + 1; //sm2p256v1的這個固定65。可看GMNamedCurves、ECCurve代碼。const int c3Len = 32; //new SM3Digest().getDigestSize();byte[] result = new byte[c1c2c3.Length];Buffer.BlockCopy(c1c2c3, 0, result, 0, c1Len); //c1Buffer.BlockCopy(c1c2c3, c1c2c3.Length - c3Len, result, c1Len, c3Len); //c3Buffer.BlockCopy(c1c2c3, c1Len, result, c1Len + c3Len, c1c2c3.Length - c1Len - c3Len); //c2return result;}/*** bc加解密使用舊標c1||c3||c2,此方法在解密前調用,將密文轉化為c1||c2||c3再去解密* @param c1c3c2* @return*/private static byte[] ChangeC1C3C2ToC1C2C3(byte[] c1c3c2){int c1Len = (x9ECParameters.Curve.FieldSize + 7) / 8 * 2 + 1; //sm2p256v1的這個固定65。可看GMNamedCurves、ECCurve代碼。const int c3Len = 32; //new SM3Digest().GetDigestSize();byte[] result = new byte[c1c3c2.Length];Buffer.BlockCopy(c1c3c2, 0, result, 0, c1Len); //c1: 0->65Buffer.BlockCopy(c1c3c2, c1Len + c3Len, result, c1Len, c1c3c2.Length - c1Len - c3Len); //c2Buffer.BlockCopy(c1c3c2, c1Len, result, c1c3c2.Length - c3Len, c3Len); //c3return result;}/*** c1||c3||c2* @param data* @param key* @return*/public static byte[] Sm2Decrypt(byte[] data, AsymmetricKeyParameter key){return Sm2DecryptOld(ChangeC1C3C2ToC1C2C3(data), key);}/*** c1||c3||c2* @param data* @param key* @return*/public static byte[] Sm2Encrypt(byte[] data, AsymmetricKeyParameter key){return ChangeC1C2C3ToC1C3C2(Sm2EncryptOld(data, key));}/*** c1||c2||c3* @param data* @param key* @return*/public static byte[] Sm2EncryptOld(byte[] data, AsymmetricKeyParameter pubkey){try{SM2Engine sm2Engine = new SM2Engine();sm2Engine.Init(true, new ParametersWithRandom(pubkey, new SecureRandom()));return sm2Engine.ProcessBlock(data, 0, data.Length);}catch (Exception e){//log.Error("Sm2EncryptOld error: " + e.Message, e);return null;}}/*** c1||c2||c3* @param data* @param key* @return*/public static byte[] Sm2DecryptOld(byte[] data, AsymmetricKeyParameter key){try{SM2Engine sm2Engine = new SM2Engine();sm2Engine.Init(false, key);return sm2Engine.ProcessBlock(data, 0, data.Length);}catch (Exception e){//log.Error("Sm2DecryptOld error: " + e.Message, e);return null;}}/*** @param bytes* @return*/public static byte[] Sm3(byte[] bytes){try{SM3Digest digest = new SM3Digest();digest.BlockUpdate(bytes, 0, bytes.Length);byte[] result = DigestUtilities.DoFinal(digest);return result;}catch (Exception e){//log.Error("Sm3 error: " + e.Message, e);return null;}}private const int RS_LEN = 32;private static byte[] BigIntToFixexLengthBytes(BigInteger rOrS){// for sm2p256v1, n is 00fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123,// r and s are the result of mod n, so they should be less than n and have length<=32byte[] rs = rOrS.ToByteArray();if (rs.Length == RS_LEN) return rs;else if (rs.Length == RS_LEN + 1 && rs[0] == 0) return Arrays.CopyOfRange(rs, 1, RS_LEN + 1);else if (rs.Length < RS_LEN){byte[] result = new byte[RS_LEN];Arrays.Fill(result, (byte)0);Buffer.BlockCopy(rs, 0, result, RS_LEN - rs.Length, rs.Length);return result;}else{throw new ArgumentException("err rs: " + Hex.ToHexString(rs));}}/*** BC的SM3withSM2簽名得到的結果的rs是asn1格式的,這個方法轉化成直接拼接r||s* @param rsDer rs in asn1 format* @return sign result in plain byte array*/private static byte[] RsAsn1ToPlainByteArray(byte[] rsDer){Asn1Sequence seq = Asn1Sequence.GetInstance(rsDer);byte[] r = BigIntToFixexLengthBytes(DerInteger.GetInstance(seq[0]).Value);byte[] s = BigIntToFixexLengthBytes(DerInteger.GetInstance(seq[1]).Value);byte[] result = new byte[RS_LEN * 2];Buffer.BlockCopy(r, 0, result, 0, r.Length);Buffer.BlockCopy(s, 0, result, RS_LEN, s.Length);return result;}/*** BC的SM3withSM2驗簽需要的rs是asn1格式的,這個方法將直接拼接r||s的字節數組轉化成asn1格式* @param sign in plain byte array* @return rs result in asn1 format*/private static byte[] RsPlainByteArrayToAsn1(byte[] sign){if (sign.Length != RS_LEN * 2) throw new ArgumentException("err rs. ");BigInteger r = new BigInteger(1, Arrays.CopyOfRange(sign, 0, RS_LEN));BigInteger s = new BigInteger(1, Arrays.CopyOfRange(sign, RS_LEN, RS_LEN * 2));Asn1EncodableVector v = new Asn1EncodableVector();v.Add(new DerInteger(r));v.Add(new DerInteger(s));try{return new DerSequence(v).GetEncoded("DER");}catch (IOException e){//log.Error("RsPlainByteArrayToAsn1 error: " + e.Message, e);return null;}}public static AsymmetricCipherKeyPair GenerateKeyPair(){try{ECKeyPairGenerator kpGen = new ECKeyPairGenerator();kpGen.Init(new ECKeyGenerationParameters(ecDomainParameters, new SecureRandom()));return kpGen.GenerateKeyPair();}catch (Exception e){//log.Error("generateKeyPair error: " + e.Message, e);return null;}}public static ECPrivateKeyParameters GetPrivatekeyFromD(BigInteger d){return new ECPrivateKeyParameters(d, ecDomainParameters);}public static ECPublicKeyParameters GetPublickeyFromXY(BigInteger x, BigInteger y){return new ECPublicKeyParameters(x9ECParameters.Curve.CreatePoint(x, y), ecDomainParameters);}public static AsymmetricKeyParameter GetPublickeyFromX509File(FileInfo file){FileStream fileStream = null;try{//file.DirectoryName + "\\" + file.NamefileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read);X509Certificate certificate = new X509CertificateParser().ReadCertificate(fileStream);return certificate.GetPublicKey();}catch (Exception e){//log.Error(file.Name + "讀取失敗,異常:" + e);}finally{if (fileStream != null)fileStream.Close();}return null;}public class Sm2Cert{public AsymmetricKeyParameter privateKey;public AsymmetricKeyParameter publicKey;public String certId;}private static byte[] ToByteArray(int i){byte[] byteArray = new byte[4];byteArray[0] = (byte)(i >> 24);byteArray[1] = (byte)((i & 0xFFFFFF) >> 16);byteArray[2] = (byte)((i & 0xFFFF) >> 8);byteArray[3] = (byte)(i & 0xFF);return byteArray;}/*** 字節數組拼接** @param params* @return*/private static byte[] Join(params byte[][] byteArrays){List<byte> byteSource = new List<byte>();for (int i = 0; i < byteArrays.Length; i++){byteSource.AddRange(byteArrays[i]);}byte[] data = byteSource.ToArray();return data;}/*** 密鑰派生函數** @param Z* @param klen*            生成klen字節數長度的密鑰* @return*/private static byte[] KDF(byte[] Z, int klen){int ct = 1;int end = (int)Math.Ceiling(klen * 1.0 / 32);List<byte> byteSource = new List<byte>();try{for (int i = 1; i < end; i++){byteSource.AddRange(GmUtil.Sm3(Join(Z, ToByteArray(ct))));ct++;}byte[] last = GmUtil.Sm3(Join(Z, ToByteArray(ct)));if (klen % 32 == 0){byteSource.AddRange(last);}elsebyteSource.AddRange(Arrays.CopyOfRange(last, 0, klen % 32));return byteSource.ToArray();}catch (Exception e){//log.Error("KDF error: " + e.Message, e);}return null;}public static byte[] Sm4DecryptCBC(byte[] keyBytes, byte[] cipher, byte[] iv, String algo){if (keyBytes.Length != 16) throw new ArgumentException("err key length");if (cipher.Length % 16 != 0 && algo.Contains("NoPadding")) throw new ArgumentException("err data length");try{KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);IBufferedCipher c = CipherUtilities.GetCipher(algo);if (iv == null) iv = ZeroIv(algo);c.Init(false, new ParametersWithIV(key, iv));return c.DoFinal(cipher);}catch (Exception e){//log.Error("Sm4DecryptCBC error: " + e.Message, e);return null;}}public static byte[] Sm4EncryptCBC(byte[] keyBytes, byte[] plain, byte[] iv, String algo){if (keyBytes.Length != 16) throw new ArgumentException("err key length");if (plain.Length % 16 != 0 && algo.Contains("NoPadding")) throw new ArgumentException("err data length");try{KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);IBufferedCipher c = CipherUtilities.GetCipher(algo);if (iv == null) iv = ZeroIv(algo);c.Init(true, new ParametersWithIV(key, iv));return c.DoFinal(plain);}catch (Exception e){//log.Error("Sm4EncryptCBC error: " + e.Message, e);return null;}}public static byte[] Sm4EncryptECB(byte[] keyBytes, byte[] plain, string algo){if (keyBytes.Length != 16) throw new ArgumentException("err key length");//NoPadding 的情況下需要校驗數據長度是16的倍數.if (plain.Length % 16 != 0 && algo.Contains("NoPadding")) throw new ArgumentException("err data length");try{KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);IBufferedCipher c = CipherUtilities.GetCipher(algo);c.Init(true, key);return c.DoFinal(plain);}catch (Exception e){//log.Error("Sm4EncryptECB error: " + e.Message, e);return null;}}public static byte[] Sm4DecryptECB(byte[] keyBytes, byte[] cipher, string algo){if (keyBytes.Length != 16) throw new ArgumentException("err key length");if (cipher.Length % 16 != 0 && algo.Contains("NoPadding")) throw new ArgumentException("err data length");try{KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);IBufferedCipher c = CipherUtilities.GetCipher(algo);c.Init(false, key);return c.DoFinal(cipher);}catch (Exception e){//log.Error("Sm4DecryptECB error: " + e.Message, e);return null;}}public const String SM4_ECB_NOPADDING = "SM4/ECB/NoPadding";public const String SM4_CBC_NOPADDING = "SM4/CBC/NoPadding";public const String SM4_CBC_PKCS7PADDING = "SM4/CBC/PKCS7Padding";/*** cfca官網CSP沙箱導出的sm2文件* @param pem 二進制原文* @param pwd 密碼* @return*/public static Sm2Cert readSm2File(byte[] pem, String pwd){Sm2Cert sm2Cert = new Sm2Cert();try{Asn1Sequence asn1Sequence = (Asn1Sequence)Asn1Object.FromByteArray(pem);//            ASN1Integer asn1Integer = (ASN1Integer) asn1Sequence.getObjectAt(0); //version=1Asn1Sequence priSeq = (Asn1Sequence)asn1Sequence[1];//private keyAsn1Sequence pubSeq = (Asn1Sequence)asn1Sequence[2];//public key and x509 cert//            ASN1ObjectIdentifier sm2DataOid = (ASN1ObjectIdentifier) priSeq.getObjectAt(0);//            ASN1ObjectIdentifier sm4AlgOid = (ASN1ObjectIdentifier) priSeq.getObjectAt(1);Asn1OctetString priKeyAsn1 = (Asn1OctetString)priSeq[2];byte[] key = KDF(System.Text.Encoding.UTF8.GetBytes(pwd), 32);byte[] priKeyD = Sm4DecryptCBC(Arrays.CopyOfRange(key, 16, 32),priKeyAsn1.GetOctets(),Arrays.CopyOfRange(key, 0, 16), SM4_CBC_PKCS7PADDING);sm2Cert.privateKey = GetPrivatekeyFromD(new BigInteger(1, priKeyD));//            log.Info(Hex.toHexString(priKeyD));//            ASN1ObjectIdentifier sm2DataOidPub = (ASN1ObjectIdentifier) pubSeq.getObjectAt(0);Asn1OctetString pubKeyX509 = (Asn1OctetString)pubSeq[1];X509Certificate x509 = (X509Certificate)new X509CertificateParser().ReadCertificate(pubKeyX509.GetOctets());sm2Cert.publicKey = x509.GetPublicKey();sm2Cert.certId = x509.SerialNumber.ToString(10); //這里轉10進賬,有啥其他進制要求的自己改改return sm2Cert;}catch (Exception e){//log.Error("readSm2File error: " + e.Message, e);return null;}}/**** @param cert* @return*/public static Sm2Cert ReadSm2X509Cert(byte[] cert){Sm2Cert sm2Cert = new Sm2Cert();try{X509Certificate x509 = new X509CertificateParser().ReadCertificate(cert);sm2Cert.publicKey = x509.GetPublicKey();sm2Cert.certId = x509.SerialNumber.ToString(10); //這里轉10進賬,有啥其他進制要求的自己改改return sm2Cert;}catch (Exception e){//log.Error("ReadSm2X509Cert error: " + e.Message, e);return null;}}public static byte[] ZeroIv(String algo){try{IBufferedCipher cipher = CipherUtilities.GetCipher(algo);int blockSize = cipher.GetBlockSize();byte[] iv = new byte[blockSize];Arrays.Fill(iv, (byte)0);return iv;}catch (Exception e){//log.Error("ZeroIv error: " + e.Message, e);return null;}}}
}

SM2加密

注意:publicKey是一個全局變量,是java方提供給.net方的公鑰
格式如下:
在這里插入圖片描述

  /// <summary>/// SM2加密/// </summary>/// <param name="publicKey"></param>/// <param name="message"></param>/// <returns></returns>public string Encrypt(string message){if (publicKey.Length == 130){publicKey = publicKey.Substring(2, 128);}//公鑰X,前64位String x = publicKey.Substring(0, 64);//公鑰Y,后64位String y = publicKey.Substring(64);//獲取公鑰對象AsymmetricKeyParameter publicKey1 = GmUtil.GetPublickeyFromXY(new BigInteger(x, 16), new BigInteger(y, 16));byte[] digestByte = GmUtil.Sm2Encrypt(Encoding.UTF8.GetBytes(message), publicKey1);//如果對方要的是16進制字符串的話需要轉換之后去除04之后直接返回newCipherText 就可以了。//string newCipherText = Hex.ToHexString(digestByte);//if (newCipherText.StartsWith("04"))//{//    newCipherText = newCipherText.Substring(2);//}//如果對方要的是base64字符串的話可以直接轉換string   newCipherText = Convert.ToBase64String(digestByte);return newCipherText; }

Sm2解密

這里的privateKey也是一個全局變量,是.net這邊自己生成的一對密鑰串(私鑰和公鑰一對一)中的私鑰
格式如下:
在這里插入圖片描述

 /// <summary>/// SM2解密/// </summary>/// <param name="privateKey"></param>/// <param name="message"></param>/// <returns></returns>public string Decrypt(string message){BigInteger d = new BigInteger(privateKey, 16);AsymmetricKeyParameter bcecPrivateKey = CommonUtils.GmUtil.GetPrivatekeyFromD(d);string datastr = Base64ToHexString(message);if (!datastr.StartsWith("04")){datastr = "04" + datastr;}byte[] byToDecrypt = Hex.Decode(datastr);byte[] byDecrypted = GmUtil.Sm2Decrypt(byToDecrypt, bcecPrivateKey);if (byDecrypted != null && byDecrypted.Length > 0){string strDecrypted = Encoding.UTF8.GetString(byDecrypted);return strDecrypted;}else{return "解密失敗!";}}

生成密鑰串

  • 第一種方式:

這里是采用我上面貼出來的幫助類中的方法生成的公鑰和私鑰

   AsymmetricCipherKeyPair kp2 = GmUtil.GenerateKeyPair();AsymmetricKeyParameter publicKey2 = kp2.Public;AsymmetricKeyParameter privateKey2 = kp2.Private;

當然還有其他方法可以生成

  • 第二種方式:
  /// <summary>/// 密鑰生成/// </summary>/// <returns></returns>public static (string, string) GenerateKeyPair(){X9ECParameters sm2Params = GMNamedCurves.GetByName("sm2p256v1");ECDomainParameters domainParams = new ECDomainParameters(sm2Params.Curve, sm2Params.G, sm2Params.N, sm2Params.H);ECKeyPairGenerator keyGen = new ECKeyPairGenerator();SecureRandom random = new SecureRandom();ECKeyGenerationParameters keyGenParam = new ECKeyGenerationParameters(domainParams, random);keyGen.Init(keyGenParam);AsymmetricCipherKeyPair keyPair = keyGen.GenerateKeyPair();ECPrivateKeyParameters privateKeyParams = (ECPrivateKeyParameters)keyPair.Private;ECPublicKeyParameters publicKeyParams = (ECPublicKeyParameters)keyPair.Public;string privateKeyHex = privateKeyParams.D.ToString(16);string publicKeyHex = Hex.ToHexString(publicKeyParams.Q.GetEncoded());return (privateKeyHex, publicKeyHex);}

SM3加密

 /// <summary>/// SM3生成加密/// </summary>/// <param name="input"></param>/// <returns></returns>public static string SM3Encrypt(string input){byte[] dataBytes = Encoding.GetEncoding("UTF-8").GetBytes(input);SM3Digest sm3Digest = new SM3Digest();sm3Digest.BlockUpdate(dataBytes, 0, dataBytes.Length);byte[] ret = new byte[sm3Digest.GetDigestSize()];sm3Digest.DoFinal(ret, 0);return Hex.ToHexString(ret);}

MD5加密

 public string MD5Encrypt(string input){if (string.IsNullOrEmpty(input)) input= "";MD5 md5Hash = MD5.Create();byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input)); StringBuilder sBuilder = new StringBuilder(); for (int i = 0; i < data.Length; i++){sBuilder.Append(data[i].ToString("x2"));} return sBuilder.ToString(); }

Base64

Base64加密

		/// <summary>/// Base64加密,采用utf8編碼方式加密/// </summary>/// <param name="source">待加密的明文</param>/// <returns>加密后的字符串</returns>public static string Base64Encode(string source){return Base64Encode(Encoding.UTF8, source);}/// <summary>/// Base64加密/// </summary>/// <param name="encodeType">加密采用的編碼方式</param>/// <param name="source">待加密的明文</param>/// <returns></returns>public static string Base64Encode(Encoding encodeType, string source){string encode = string.Empty;byte[] bytes = encodeType.GetBytes(source);try{encode = Convert.ToBase64String(bytes);}catch{encode = source;}return encode;} 

Base64解密

/// <summary>/// Base64解密,采用utf8編碼方式解密/// </summary>/// <param name="result">待解密的密文</param>/// <returns>解密后的字符串</returns>public static string Base64Decode(string result){return Base64Decode(Encoding.UTF8, result);}/// <summary>/// Base64解密/// </summary>/// <param name="encodeType">解密采用的編碼方式,注意和加密時采用的方式一致</param>/// <param name="result">待解密的密文</param>/// <returns>解密后的字符串</returns>public static string Base64Decode(Encoding encodeType, string result){string decode = string.Empty;byte[] bytes = Convert.FromBase64String(result);try{decode = encodeType.GetString(bytes);}catch{decode = result;}return decode;}  

DES

//默認密鑰向量private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };private static string DESKey = "CQYRZHXG"; 

DES加密

		/// <summary>/// <summary>/// 加密【可逆】/// </summary>/// <param name="Text">需要加密的字符串</param>/// <param name="DESKey">加密密鑰,要求為8位</param>/// <returns></returns>public static string Encrypt(string Text){return EncryptDES(Text, DESKey);}/// <summary> /// 加密數據/// </summary> /// <param name="Text"></param> /// <param name="sKey"></param> /// <returns></returns> /// DES加密字符串/// </summary>/// <param name="encryptString">待加密的字符串</param>/// <param name="encryptKey">加密密鑰,要求為8位</param>/// <returns>加密成功返回加密后的字符串,失敗返回源串</returns>public static string EncryptDES(string encryptString, string encryptKey){try{byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));byte[] rgbIV = Keys;byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();MemoryStream mStream = new MemoryStream();CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);cStream.Write(inputByteArray, 0, inputByteArray.Length);cStream.FlushFinalBlock();return Convert.ToBase64String(mStream.ToArray());}catch{return encryptString;}} 

DES解密

/// <summary>/// 解密/// </summary>/// <param name="Text">需要解密的字符串</param>/// <returns></returns>public static string Decrypt(string Text){if (!string.IsNullOrEmpty(Text)){return DecryptDES(Text, DESKey);}else{return "";}}/// <summary>/// DES解密字符串/// </summary>/// <param name="decryptString">待解密的字符串</param>/// <param name="decryptKey">解密密鑰,要求為8位,和加密密鑰相同</param>/// <returns>解密成功返回解密后的字符串,失敗返源串</returns>public static string DecryptDES(string decryptString, string decryptKey){try{byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey);byte[] rgbIV = Keys;byte[] inputByteArray = Convert.FromBase64String(decryptString);DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();MemoryStream mStream = new MemoryStream();CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);cStream.Write(inputByteArray, 0, inputByteArray.Length);cStream.FlushFinalBlock();return Encoding.UTF8.GetString(mStream.ToArray());}catch{return decryptString;}} 

SHA1

  • 第一種方法:
/// <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);}}
  • 第二種方法:
  public string SHA1Encrypt(string Source_String){byte[] StrRes = Encoding.Default.GetBytes(Source_String);HashAlgorithm iSHA = new SHA1CryptoServiceProvider();StrRes = iSHA.ComputeHash(StrRes);StringBuilder EnText = new StringBuilder();foreach (byte iByte in StrRes){EnText.AppendFormat("{0:x2}", iByte);}return EnText.ToString();}

總結

以上就是常用的加密和解密方式。希望對大家有所幫助,對于加密和解密不用過多在意他們的計算公式和原理。咱們只管開發就好,過于追求真理只會延遲開發進度。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/64658.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64658.shtml
英文地址,請注明出處:http://en.pswp.cn/web/64658.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

工作中常用Vim的命令

Hi, 我是你們的老朋友&#xff0c;主要專注于嵌入式軟件開發&#xff0c;有興趣不要忘記點擊關注【碼思途遠】 目錄 0. ctags -R 1.認識 Vim的幾種工作模式 2.高頻使用命令 2.1 修改文件 2.2 關于行號 2.3 刪除多行&#xff0c;刪除部分 2.4 復制粘貼 2.5 光標移動 2.…

如何在 Vue 2 中使用 Swiper 5.4.5 處理靜態與后端數據不能切換問題

一、文章大綱 1.前言 介紹 Swiper 作為一款強大的輪播組件,常用于處理圖片、文章、商品等內容的滑動展示。 在 Vue.js 項目中集成 Swiper,尤其是在 Vue 2 中使用,常見的兩種數據來源:靜態數據與后端數據。 在 Vue 2 項目中集成 Swiper 5.4.5 2.如何通過 npm 安裝 Swiper…

究極炫酷3D立方體宇宙

演示動畫&#xff1a;https://life.mdjsjd.me/2024/12/27/3d-cube-animation/ 一個使用Python和Pygame制作的炫酷3D立方體動畫效果。結合了多種視覺特效,包括: 動態旋轉的3D立方體炫彩漸變的顏色系統星空背景粒子效果動態殘影拖尾效果深度透視投影 主要特性 動態變換: 立方…

什么是 Azure OpenAI ?了解微軟 Azure OpenAI 和 OpenAI 的關系

一、什么是Azure OpenAI &#xff1f; 微軟已與 OpenAI 合作以實現三個主要目標&#xff1a; ?利用 Azure 的基礎結構&#xff08;包括安全性、合規性和區域可用性&#xff09;&#xff0c;幫助用戶構建企業級應用程序。 ?在微軟產品&#xff08;包括 Azure AI 產品以及以外…

Linux day 1129

家人們今天繼續學習Linux&#xff0c;ok話不多說一起去看看吧 三.Linux常用命令 3.1 Linux命令體驗 3.1.1 常用命令演示 在這一部分中&#xff0c;我們主要介紹幾個常用的命令&#xff0c;讓大家快速感 受以下 Linux 指令的操作方式。主要包含以下幾個指令&#xff1a; ls命…

mysql8 從C++源碼角度看 Statement cancelled due to timeout or client request異常

##Statement cancelled due to timeout or client request 異常 Caused by: com.mysql.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client requestat com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1932)at …

【數據結構-單調隊列】力扣1438. 絕對差不超過限制的最長連續子數組

給你一個整數數組 nums &#xff0c;和一個表示限制的整數 limit&#xff0c;請你返回最長連續子數組的長度&#xff0c;該子數組中的任意兩個元素之間的絕對差必須小于或者等于 limit 。 如果不存在滿足條件的子數組&#xff0c;則返回 0 。 示例 1&#xff1a; 輸入&#x…

SAP HCM 標準報表與前臺操作的增強差異邏輯分析(rhgrenz4)

導讀 增強差異:SAP的HCM模塊組織和人事增強都有標準的增強點&#xff0c;不管你調用標準的函數還是前臺操作都會觸發對應的增強。所以很多業務不需要考慮那么多分散點&#xff0c;只要找到一個合適的增強點&#xff0c;就能解決很多和外圍系統集成的業務邏輯&#xff0c;今天遇…

【Spring】Spring DI(依賴注入)詳解——自動裝配——手動裝配與自動裝配的區別

在spring開發中&#xff0c;依賴注入&#xff08;Dependency Injection&#xff0c;DI&#xff09;是實現松耦合和高內聚設計的重要模式。它使得對象的創建和管理與其依賴關系分離&#xff0c;從而提高了代碼的可維護性、可測試性和靈活性。Spring框架通過IoC&#xff08;控制反…

EZ-USB? FX3 USB 5 Gbps 外設控制器

EZ-USB? FX3 USB 5 Gbps 外設控制器 EZ-USB? FX3 提供 USB 5Gbps 至 32 位數據總線&#xff0c;并配備 ARM9&#xff0c;可為任何系統添加 USB 3.0 連接 英飛凌的 EZ-USB? FX3 是業界用途最廣泛的 USB 外圍設備控制器&#xff0c;可以為幾乎任何系統添加 USB 5Gbps 連接。 …

【數據倉庫】spark大數據處理框架

文章目錄 概述架構spark 架構角色下載安裝啟動pyspark啟動spark-sehll啟動spark-sqlspark-submit經驗 概述 Spark是一個性能優異的集群計算框架&#xff0c;廣泛應用于大數據領域。類似Hadoop&#xff0c;但對Hadoop做了優化&#xff0c;計算任務的中間結果可以存儲在內存中&a…

數據庫容災備份的意義+分類+執行工具!

數據庫容災解決方案的背景 數據庫容災&#xff08;Disaster Recovery&#xff0c;DR&#xff09;解決方案的背景主要源于企業對數據安全性、業務連續性和系統高可用性的需求。隨著數字化轉型的加速&#xff0c;企業的數據量迅猛增長&#xff0c;數據庫已成為支撐核心業務的關鍵…

PDF怎么壓縮得又小又清晰?5種PDF壓縮方法

PDF 文件在日常辦公與學習中使用極為頻繁&#xff0c;可想要把它壓縮得又小又清晰卻困難重重。一方面&#xff0c;PDF 格式本身具有高度兼容性&#xff0c;集成了文字、圖像、矢量圖等多樣元素&#xff0c;壓縮時難以兼顧不同元素特性&#xff0c;稍不注意&#xff0c;文字就會…

SpringBoot數據字典字段自動生成對應code和desc

效果&#xff1a;接口會返回orderType&#xff0c;但是這個orderType是枚舉的類型&#xff08;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff09;&#xff0c;我想多返回一個orderTypeDesc給前端展示&#xff0c;這樣前端就可以直接拿orderTypeDesc使用了。 1. 定義注解 …

【YashanDB知識庫】imp導入數據庫時,報錯YAS-08023

本文內容來自YashanDB官網&#xff0c;原文內容請見 https://www.yashandb.com/newsinfo/7849010.html?templateId1718516 **【問題分類】**數據導入導出 **【關鍵字】**imp、YAS-08023 【問題描述】 導出數據庫時&#xff0c;使用以下命令&#xff0c;導出正常&#xff1…

又一年。。。。。。

2024&#xff0c;渾渾噩噩的一年。 除了100以內的加減法&#xff08;數據&#xff0c;數據&#xff0c;還是數據。。。。。。&#xff09;&#xff0c;似乎沒做些什么。 臉盲癥越來越重的&#xff0c;怕是哪天連自己都不認得自己的了。 看到什么&#xff0c;聽到什…

FreeRTOS: ISR(中斷服務例程)和 TCB(任務控制塊)

在討論 ISR&#xff08;中斷服務例程&#xff09;和 TCB&#xff08;任務控制塊&#xff0c;Task Control Block&#xff09;時&#xff0c;我們實際上是在探討 FreeRTOS 中兩個不同但又相互關聯的概念&#xff1a;一個是用于處理硬件或軟件觸發的中斷事件&#xff0c;另一個是…

GoldenDB組件及對應的用戶和進程

1. GoldenDB組件及對應的用戶和進程 GoldenDB數據庫由管理節點、全局事務節點GTM、計算節點CN、數據節點DN等組成。 1.1. 管理節點 管理節點分為集群管理、Insight運維管理平臺&#xff08;InsightServer、RDB、ZK&#xff09;。 1.1.1. 集群管理 1. 集群管理包括Metadatas…

OpenStack系列第四篇:云平臺基礎功能與操作(Dashboard)

文章目錄 1. 鏡像&#xff08;Image&#xff09;添加鏡像查看鏡像刪除鏡像 2. 卷&#xff08;Volume&#xff09;創建卷查看卷刪除卷 3. 網絡&#xff08;虛擬網絡&#xff09;創建網絡查看網絡刪除網絡 4. 實例類型創建實例類型查看實例類型刪除實例類型 4. 密鑰對&#xff08…

CSDN編輯器

這里寫自定義目錄標題 歡迎使用Markdown編輯器新的改變功能快捷鍵合理的創建標題&#xff0c;有助于目錄的生成如何改變文本的樣式插入鏈接與圖片如何插入一段漂亮的代碼片生成一個適合你的列表創建一個表格設定內容居中、居左、居右SmartyPants 創建一個自定義列表如何創建一個…