.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();}
总结
以上就是常用的加密和解密方式。希望对大家有所帮助,对于加密和解密不用过多在意他们的计算公式和原理。咱们只管开发就好,过于追求真理只会延迟开发进度。
相关文章:

.Net加密与Java互通
.Net加密与Java互通 文章目录 .Net加密与Java互通前言RSA生成私钥和公钥.net加密出数据传给Java端采用java方给出的公钥进行加密采用java方给出的私钥进行解密 .net 解密来自Java端的数据 AES带有向量的AES加密带有向量的AES解密无向量AES加密无向量AES解密 SM2(国密)SM2加密Sm…...

MySQL 06 章——多表查询
多表查询,也称为关联查询,是指两个表或多个表一起完成查询操作 前提条件,这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段的。这个关联字段可能建立了外键,也可能没…...

猴子吃桃.
本节通过学习解决一个有趣的问题来加深对递归的理解. 问题描述: 有一个猴子摘了桃子吃,第一天吃一半多一个,第二天吃第一天剩余的一半多一个,第三天吃第二天剩余的一半多一个..以此类推,当第n天时,恰好只剩下一个桃子.求猴子一共摘了多少桃子. 思路解析: 解读题目,第n天的桃子…...

游戏引擎学习第72天
无论如何,我们今天有一些调试工作要做,因为昨天做了一些修改,结果没有时间进行调试和处理。我们知道自己还有一些需要解决的问题,却没有及时完成,所以我们想继续进行这些调试。对我们来说,拖延调试工作总是…...

element-ui dialog 组件源码分享
简单分享 dialog 组件源码,主要从以下三个方面: 1、dialog 页面结构。 2、dialog 组件属性。 3、dialog 组件挂载。 4、dialog 组件事件。 一、dialog 页面结构: 二、组件属性: 2.1 visible 是否显示 Dialog,支持…...

unity开发之shader 管道介质流动特效
效果 shader graph 如果出现下面的效果,那是因为你模型的问题,建模做贴图的时候没有设置好UV映射,只需重新设置下映射即可...

人工智能之机器学习算法
所有的机器学习算法都是要优化的,优化的必要条件是确定优化的目标函数(损失函数),目标函数是根据实际问题(数据)转成的数学公式。 一.线性回归原理推导 (1)回归问题概述 在机器学习的有监督算法中,分类与回归二种情…...
Android布局layout的draw简洁clipPath实现圆角矩形布局,Kotlin
Android布局layout的draw简洁clipPath实现圆角矩形布局,Kotlin 通常,如果要把一个相对布局,FrameLayout,或者线性布局等这样的布局变成具有圆角或者圆形的布局,需要增加一个style,给它设置圆角,…...

信息系统常见的系统架构
1.1单文件架构 现在很多企业内部虽然已经建设了一些信息系统,但还是有不少业务没有用专门的信息系统管理起来,普遍都是采用Excel表格来实现这些业务数据的填报和查询统计。Excel就是属单文件架构,这种架构是指整个系统就是一个文件࿰…...

AngularJS 过滤器:提升用户体验的数据处理利器
AngularJS 过滤器:提升用户体验的数据处理利器 AngularJS,作为一款由Google维护的开源JavaScript框架,以其独特的双向数据绑定和MVVM(Model-View-ViewModel)架构在Web应用开发领域占据着重要地位。其中,AngularJS的过滤器(Filters)功能,为开发者提供了一种轻量级、高…...

Upload-labs 第四关(学习记录)
上传.htaccess文件 SetHandler application/x-httpd-php <IfModule mime_module> SetHandler application/x-httpd-php #在当前目录下,所有文件都会被解析成php代码执行 </IfModule> 上传一句话木马 保存为 1.png 文件 成功解析...

金融租赁系统的创新与发展推动行业效率提升
金融租赁系统的技术升级与创新 在当今快速发展的金融市场中,金融租赁系统的技术升级与创新充满了无限可能。想象一下,传统的租赁方式就像一位沉闷的老师,而新兴技术就如同一位活泼的学生,不断追求新鲜事物。通过自动化、人工智能…...

MYSQL在Windows平台上的限制
以下限制适用于在Windows平台上使用MySQL: 程序内存 在windows32位上,一个进程(包括MySQL)内默认使用超过2GB的内存是不可能的。这是因为windows 32位的物理地址限制是4GB,视窗内的默认设置是在内核(2GB&a…...

Rust 泛型、特征与生命周期详解
Rust 泛型、特征与生命周期详解 泛型编程 泛型函数 // 泛型函数:找出最大值 fn largest<T: PartialOrd>(list: &[T]) -> &T {let mut largest &list[0];for item in list {if item > largest {largest item;}}largest }fn main() {let…...

基于 Python 虎扑网站的 NBA 球员大数据分析与可视化
标题:基于 Python 虎扑网站的 NBA 球员大数据分析与可视化 内容:1.摘要 摘要:本文介绍了一种基于 Python 的虎扑网站 NBA 球员大数据分析与可视化方法。通过网络爬虫技术获取球员数据,利用数据分析和可视化工具对数据进行处理和展示,帮助用户…...

小程序组件 —— 26 组件案例 - 跳转到商品列表
在上一节实现了商品导航区域,这一节实现跳转到商品列表的功能;当用户在点击商品导航时,需要能够跳转到商品列表页面;在微信小程序中,如果需要进行跳转,需要使用 navigator 组件,navigator 组件有…...

【Spring学习】为什么Spring中的IOC(控制反转)能够降低耦合性(解耦)?
为什么Spring中的IOC能够降低耦合性? 前言1.传统方式2.使用接口3.工厂方法4.反射改造工厂类5.IOC总结参考 前言 本文目标:本文旨在讲解为什么IOC能够降低耦合性。 情景:假设你是一个爱摸鱼的程序员,现在需要测试一个游戏&#x…...

机场安全项目|基于改进 YOLOv8 的机场飞鸟实时目标检测方法
目录 论文信息 背景 摘要 YOLOv8模型结构 模型改进 FFC3 模块 CSPPF 模块 数据集增强策略 实验结果 消融实验 对比实验 结论 论文信息 《科学技术与工程》2024年第24卷第32期刊载了中国民用航空飞行学院空中交通管理学院孔建国, 张向伟, 赵志伟, 梁海军的论文——…...

卸载干净 IDEA(图文讲解)
目录 1、卸载 IDEA 程序 2、注册表清理 3、残留清理 1、卸载 IDEA 程序 点击屏幕左下角 Windows 图标 -> 设置-控制面板->intellij idea 勾选第一栏 Delete IntelliJ IDEA 2022.2 caches and local history,表示同时删除 IDEA 本地缓存以及历史。 Delete I…...

云端微光,AI启航:低代码开发的智造未来
文章目录 前言一、引言:技术浪潮中的个人视角初次体验腾讯云开发 Copilot1.1 低代码的时代机遇1.1.1 为什么低代码如此重要? 1.2 AI 的引入:革新的力量1.1.2 Copilot 的亮点 1.3 初学者的视角1.3.1 Copilot 带来的改变 二、体验记录ÿ…...

工程师了解的Lua语言
1、关于lua语言 lua语言是用于嵌入式领域当中的一门脚本语言,其实在大学期间,我也没有接触过这门语言,但是在未来的发展之路当中,需要用到这门语言,所以在我的知识库当中添加这门语言知识是必要而且重要的,…...

著名的软件都用什么语言编写?
你是否曾经好奇,身边那些耳熟能详的软件,它们究竟是用什么语言编写的?从操作系统到浏览器、从数据库到编程工具,每一款软件背后都承载着开发者们的智慧与技术选型。那么,究竟哪些编程语言成就了这些世界级的软件呢&…...

设计模式 结构型 代理模式(Proxy Pattern)与 常见技术框架应用 解析
代理模式(Proxy Pattern)是一种常见的设计模式,在软件开发中有着广泛的应用。其核心思想是通过创建一个代理类来控制对另一个对象的访问,从而实现对目标对象功能的扩展、保护或其他附加操作。 一、核心思想 代理模式的核心思想在…...

Linux环境(CentOs7) 安装 Node环境
Linux环境(CentOs7) 安装 Node环境 使用NodeSource安装Node.js 1、清除缓存(可选但推荐) sudo yum clean all2、添加NodeSource仓库,根据你想要安装的Node.js版本,选择相应的NodeSource安装脚本。例如&am…...

Tailwind CSS 实战:现代登录注册页面开发
在前端开发中,登录注册页面是最常见的需求之一。一个设计精美、交互友好的登录注册页面不仅能提升用户体验,还能增加产品的专业度。本文将详细介绍如何使用 Tailwind CSS 开发一个现代化的登录注册页面。 设计思路 在开始编码之前,我们先明…...

Unity2022接入Google广告与支付SDK、导出工程到Android Studio使用JDK17进行打包完整流程与过程中的相关错误及处理经验总结
注:因为本人也是第一次接入广告与支付SDK相关的操作,网上也查了很多教程,很多也都是只言片语或者缺少一些关键步骤的说明,导致本人也是花了很多时间与精力踩了很多的坑才搞定,发出来也是希望能帮助到其他人在遇到相似问…...
反向传播算法的偏置更新步骤
偏置的更新步骤 假设我们有一个三层神经网络(输入层、隐藏层和输出层),并且每层的激活函数为 sigmoid 函数。我们需要更新隐藏层和输出层的偏置。以下是详细的步骤: 1. 计算误差项(Error Term) 输出层的…...

条款47:请使用 traits classes 表现类型信息(Use traits classes for information about types)
条款47:请使用 traits classes 表现类型信息 1.1 提出问题 想一想,下面的功能如何实现?(可以查看std::advance源码) template<typename IterT, typename DistT> void advance(IterT& iter, DistT d); /…...

yolov5和yolov8的区别
1. yolov5有建议框,yolov8没有建议框 2. yolov5标签中有自信度,而yolov8没有自信度。因为自信度是建议框和真实框的交集 3. yolov5有三个损失函数,回归问题:预测框和建议框的损失(中心点宽高偏移量的损失):CIOUFocal…...

Redis 实现分布式锁
文章目录 引言一、Redis的两种原子操作1.1 Redis 的原子性1.2 单命令1.3 Lua 脚本1.4 对比单命令与 Lua 脚本 二、Redis 实现分布式锁2.1 分布式锁的概念与需求2.1.1 什么是分布式锁?2.1.2 分布式锁的常见应用场景 2.2 基于 Redis 的分布式锁实现2.2.1 锁的获取与释…...