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

RSA 简介及 C# 和 js 实现【加密知多少系列_4】

〇、简介

谈及 RSA 加密算法,我们就需要先了解下这两个专业名词,对称加密和非对称加密。

  • 对称加密:在同一密钥的加持下,发送方将未加密的原文,通过算法加密成密文;相对的接收方通过算法将密文解密出来原文的过程,就是对称加密算法。

  • 非对称加密:发送发和接收方通过不同的密钥加解密的过程就是非对称加密。发送方通过公钥加密后的密文,接收方通过私钥解密密文成明文。公钥就是公开的,让全部发送方使用,私钥是保密的,不能公开,专门供接收方解密收到的密文,没有私钥的第三方就无法解密密文,从而保证了数据传输的安全性。

非对称加密的代表算法是 RSA 算法,其是目前最有影响力的公钥加密算法,并且被普遍认为是目前最优秀的公钥方案之一。本文也将做专门介绍。

RSA 公钥加密算法是 1977 年由 Ron Rivest、Adi Shamirh 和 Len Adleman 在美国麻省理工学院开发的,RSA 取名来自开发他们三者的名字。

RSA 是第一个能同时用于加密和数字签名的算法,它能够抵抗到目前为止已知的所有密码攻击,已被 ISO 推荐为公钥数据加密标准

RSA 公开密钥密码体制的原理是:根据数论,寻求两个大素数比较简单,而将它们的乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

强大的加密算法也存在一些缺点:

  • 产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密(密钥只能使用一次,永远不对其它消息重复使用)。
  • 分组长度太大,为保证安全性,n 至少也要 600bits 以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。目前,SET(Secure Electronic Transaction) 协议中要求 CA 采用 2048bits 长的密钥,其他实体使用 1024bits 的密钥。
  • RSA 密钥长度随着保密级别提高,增加很快。

同样的明文经 RSA 公钥加密后的结果,每次都不同。下面简单说明一下:

不管是使用RSA私钥进行签名还是公钥进行加密,操作中都需要对待处理的数据先进行填充,然后再对填充后的数据进行加密处理。

EB = 00 || BT || PS || 00 || D

  • D: data (指待处理数据,即填充前的原始数据)
  • PS: padding string (填充字符串)
  • BT: block type (数据块类型)
  • EB: encryption block (待加密的数据块,经过填充后结果)
  • ||: 表示连接操作 (X||Y 表示将 X 和 Y 的内容连接到一起)

  "填充后数据" = "00" + "数据块类型" + "填充字符串" + "00" + "原始数据"

对私钥处理的数据,BT 取值为 00 或 01:

  • BT 取值为 00 时,PS 为全 00 的字符串;
  • BT 取值为 01 时,PS 为全 FF 的字符串,通过填充得到的整数会足够大,可以阻止某些攻击,因此也是推荐的填充方式。

针对公钥处理的数据,BT 取值为 02:

  • 使用伪随机的 16 进制字符串填充 PS,而且每次操作进行填充的伪随机书都是独立的。

可见,针对公钥处理的数据,其填充内容为伪随机(限制范围的随机数)的 16 进制字符串,每次操作的填充内容都不一样。因此每次使用公钥加密数据得到的结果就不一样了。

  参考:为什么RSA公钥每次加密得到的结果都不一样?  通俗易懂的对称加密与非对称加密原理浅析

一、C# 语言实现

首先需要安装一个包:BouncyCastle.NetCore

注意:检验密文是的选项可参考以下值,Hash:SHA-256;MGFHash:SHA-256;填充模式:ENCRYPTION_PKCS1。

// 测试
RsaSecretKey rSASecretKey = SecurityRSA.GenerateRsaSecretKey(1024);
// 密钥示例:(每次结果都不同)
// MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL8xl2yVjjt0DRzJMhq7WZrOP+8Vivuf+Ut3AxuhKoiD6yQGrgzLLQz7tQ30WuucDgzAIDnhFCyxkydMkrpGpd1sN/d8F2n8VE4zj9Tus2eFYQZeKSvw1fKDWiuy2j2yNOHjyKUtALeX4UNViizRRgK407v84orQk8607UfzfrGtAgMBAAECgYBBt0vy2JzgtozjPgxov8iWuxmilecFggDv/WImFwlFjwI9icY9Q4Cim8mpmDnADg2OOGNbQY/rpMWNlnZAbJQJo+TG/J2n3klWzC5KM5O289faw/EguSl3MChqvunvZZqMfSAcqpAxjj4aZHyWDBhsgJZtZNbKBdn5t2JnGdbVSQJBAP3/P6s/g83jhvahNML2sr+fKBMIq6++1UdX0ZI0GusoT/dLWdSGz0T8i4YvIsHC8a//OVBBUsZr9Vdj6C57EX8CQQDAs49RsDsk5zsj30GeVtPTYr1FJn50keqkrptp5dHd0xBZCaZqCUKCOD2txfl7srNJk0cQUX9bXhA36xTxJ7rTAkAwAeWj1X5xFNc2mGOjkgNZCpkFd/cTYatoL6YRzz1jQxxSLnDNJanZbS5l71TPcKxDyqanj6E4lcEqglypJGO7AkBsDUMzvumrC61xs+ILcwxb32XZvHfzzU4RAYdLnf5Lr+newzZ5BrAwbHDJW9VEszMs8lRKpigPh3L4p+yaPHjZAkACSoguX4h81aZWQz5jMxEWsGrydqz5H5+NCPI0uuaZBGLc9mFclhLgKfXC2eh24lKkvxWmjuM10lA+Bl/GDeWH
// MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/MZdslY47dA0cyTIau1mazj/vFYr7n/lLdwMboSqIg+skBq4Myy0M+7UN9FrrnA4MwCA54RQssZMnTJK6RqXdbDf3fBdp/FROM4/U7rNnhWEGXikr8NXyg1orsto9sjTh48ilLQC3l+FDVYos0UYCuNO7/OKK0JPOtO1H836xrQIDAQAB
string jiamih = SecurityRSA.RsaEncrypt(rSASecretKey.PublicKey, "TestString测试");
// 加密后 Base64 编码结果示例:(每次结果都不同)
// Mync8QBZFLx30wYAOjsiO2+GYdI0pVABDPJ7S/eBSt6+PNVkmSGudEXIDUWBWu4kWwpbTeKpolQCOR+O060eZWD6bFCRovX4AHQAodqGyT/9Q1b0u2YgWhyV1NeaJebm+3QZp9HjMHFzRjoBiGv/v3CEF2I/1SiKz0yfpLGwlwg=
string jiemih = SecurityRSA.RsaDecrypt(rSASecretKey.PrivateKey, jiamih);/// <summary>
/// RSA 密钥生成及加解密
/// </summary>
public class SecurityRSA
{/// <summary>/// RSA 加密/// </summary>/// <param name="xmlpublickey"></param>/// <param name="content"></param>/// <returns></returns>public static string RsaEncrypt(string xmlpublickey, string content){string encryptedcontent = string.Empty;using (RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider()){rSACryptoServiceProvider.FromXmlString(RSAPublicKeyBase64ToXml(xmlpublickey));byte[] encrypteddata = rSACryptoServiceProvider.Encrypt(Encoding.Default.GetBytes(content), false);encryptedcontent = Convert.ToBase64String(encrypteddata);}return encryptedcontent;}/// <summary>/// RSA 解密/// </summary>/// <param name="xmlprivatekey"></param>/// <param name="content"></param>/// <returns></returns>public static string RsaDecrypt(string xmlprivatekey, string content){string decryptedcontent = string.Empty;using (RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider()){rSACryptoServiceProvider.FromXmlString(RSAPrivateKeyBase64ToXml(xmlprivatekey));byte[] decryptedData = rSACryptoServiceProvider.Decrypt(Convert.FromBase64String(content), false);decryptedcontent = Encoding.GetEncoding("UTF-8").GetString(decryptedData);}return decryptedcontent;}/// <summary>/// 生成 RSA 公钥和私钥/// </summary>/// <param name="keysize">目前 SET(Secure Electronic Transaction)协议中要求 CA 采用 2048bits 长的密钥,其他实体使用 1024bits 的密钥</param>/// <returns></returns>public static RsaSecretKey GenerateRsaSecretKey(int keysize){RsaSecretKey rSASecretKey = new RsaSecretKey();using (RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider(keysize)){rSASecretKey.PrivateKey = RSAPrivateKeyXmlToBase64(rSACryptoServiceProvider.ToXmlString(true));rSASecretKey.PublicKey = RSAPublicKeyXmlToBase64(rSACryptoServiceProvider.ToXmlString(false));}return rSASecretKey;}/// <summary>/// XML 字符串转 Base64 编码的字符串(公钥)/// </summary>/// <param name="publicKey"></param>/// <returns></returns>public static string RSAPublicKeyXmlToBase64(string publicKey){XmlDocument doc = new XmlDocument();doc.LoadXml(publicKey);Org.BouncyCastle.Math.BigInteger m = new Org.BouncyCastle.Math.BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));Org.BouncyCastle.Math.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>/// XML 字符串转 Base64 编码的字符串(私钥)/// </summary>/// <param name="privateKey"></param>/// <returns></returns>public static string RSAPrivateKeyXmlToBase64(string privateKey){XmlDocument doc = new XmlDocument();doc.LoadXml(privateKey);Org.BouncyCastle.Math.BigInteger m = new Org.BouncyCastle.Math.BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));Org.BouncyCastle.Math.BigInteger exp = new Org.BouncyCastle.Math.BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));Org.BouncyCastle.Math.BigInteger d = new Org.BouncyCastle.Math.BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[0].InnerText));Org.BouncyCastle.Math.BigInteger p = new Org.BouncyCastle.Math.BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[0].InnerText));Org.BouncyCastle.Math.BigInteger q = new Org.BouncyCastle.Math.BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[0].InnerText));Org.BouncyCastle.Math.BigInteger dp = new Org.BouncyCastle.Math.BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[0].InnerText));Org.BouncyCastle.Math.BigInteger dq = new Org.BouncyCastle.Math.BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[0].InnerText));Org.BouncyCastle.Math.BigInteger qinv = new Org.BouncyCastle.Math.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>/// Base64 编码字符串转 XML 字符串(私钥)/// </summary>/// <param name="privateKey"></param>/// <returns></returns>public static string RSAPrivateKeyBase64ToXml(string privateKey){RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));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>/// Base64 编码字符串转 XML 字符串(公钥)/// </summary>/// <param name="publicKey"></param>/// <returns></returns>public static string RSAPublicKeyBase64ToXml(string publicKey){RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));}
}
/// <summary>
/// RSA 密钥类
/// </summary>
public class RsaSecretKey
{public RsaSecretKey(string privatekey = "", string publickey = ""){PrivateKey = privatekey;PublicKey = publickey;}public string PublicKey { get; set; }public string PrivateKey { get; set; }public override string ToString(){return string.Format("PrivateKey: {0}\r\nPublicKey: {1}", PrivateKey, PublicKey);}
}


  参考:C#的秘钥跟JAVA的密钥区别

二、js 语言实现

 本示例采用引入开源的 js 库:JSEncrypt,来实现 RSA 的加解密。另外暂不建议在前端生成密钥,本示例也无示例。

// 先引入 js 库
<script src="https://cdn.bootcdn.net/ajax/libs/jsencrypt/3.3.2/jsencrypt.min.js"></script>
// npm 方式引入
npm install encryptjs --save-dev// 调用方法 message() 查看测试结果
function message() {var publickey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/MZdslY47dA0cyTIau1mazj/vFYr7n/lLdwMboSqIg+skBq4Myy0M+7UN9FrrnA4MwCA54RQssZMnTJK6RqXdbDf3fBdp/FROM4/U7rNnhWEGXikr8NXyg1orsto9sjTh48ilLQC3l+FDVYos0UYCuNO7/OKK0JPOtO1H836xrQIDAQAB';//这个是公钥,建议后端生成var data_en = RsaEncrypt(publickey, "TestString测试");console.log(data_en); // 输出结果:elHQslM7RM9aewSZHetgAJ4X7VNGcpCa9/xFiKv33+QTXy6Utc6Ca4B502ZO2J3zmmSYzk+YOkh8I8NgQFu+s8rYIy1hQjnCaCJI1xWC47vdEfZN79AbX/bmYb0eyjpCaIptIlrIKRPyPDl/H3D/FtNsqVhIEr7mG9a8u+odnus=var privatekey = 'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL8xl2yVjjt0DRzJMhq7WZrOP+8Vivuf+Ut3AxuhKoiD6yQGrgzLLQz7tQ30WuucDgzAIDnhFCyxkydMkrpGpd1sN/d8F2n8VE4zj9Tus2eFYQZeKSvw1fKDWiuy2j2yNOHjyKUtALeX4UNViizRRgK407v84orQk8607UfzfrGtAgMBAAECgYBBt0vy2JzgtozjPgxov8iWuxmilecFggDv/WImFwlFjwI9icY9Q4Cim8mpmDnADg2OOGNbQY/rpMWNlnZAbJQJo+TG/J2n3klWzC5KM5O289faw/EguSl3MChqvunvZZqMfSAcqpAxjj4aZHyWDBhsgJZtZNbKBdn5t2JnGdbVSQJBAP3/P6s/g83jhvahNML2sr+fKBMIq6++1UdX0ZI0GusoT/dLWdSGz0T8i4YvIsHC8a//OVBBUsZr9Vdj6C57EX8CQQDAs49RsDsk5zsj30GeVtPTYr1FJn50keqkrptp5dHd0xBZCaZqCUKCOD2txfl7srNJk0cQUX9bXhA36xTxJ7rTAkAwAeWj1X5xFNc2mGOjkgNZCpkFd/cTYatoL6YRzz1jQxxSLnDNJanZbS5l71TPcKxDyqanj6E4lcEqglypJGO7AkBsDUMzvumrC61xs+ILcwxb32XZvHfzzU4RAYdLnf5Lr+newzZ5BrAwbHDJW9VEszMs8lRKpigPh3L4p+yaPHjZAkACSoguX4h81aZWQz5jMxEWsGrydqz5H5+NCPI0uuaZBGLc9mFclhLgKfXC2eh24lKkvxWmjuM10lA+Bl/GDeWH';//这个是私钥,建议后端生成var data_de = RsaDecrypt(privatekey, data_en);console.log(data_de);
}
// 加密
function RsaEncrypt(publickey, encrypt_content) {var encryptpk = new JSEncrypt();encryptpk.setPublicKey(publickey);let result = encryptpk.encrypt(encrypt_content)console.log("RsaEncrypt:", result)return result;
}
// 解密
function RsaDecrypt(privatekey, decrypt_content) {var encryptpk = new JSEncrypt();encryptpk.setPrivateKey(privatekey);let result = encryptpk.decrypt(decrypt_content)console.log("RsaDecrypt:", result)return result;
}

相关文章:

RSA 简介及 C# 和 js 实现【加密知多少系列_4】

〇、简介 谈及 RSA 加密算法&#xff0c;我们就需要先了解下这两个专业名词&#xff0c;对称加密和非对称加密。 对称加密&#xff1a;在同一密钥的加持下&#xff0c;发送方将未加密的原文&#xff0c;通过算法加密成密文&#xff1b;相对的接收方通过算法将密文解密出来原文…...

在IDEA中快速注释所有console.log

在IDEA中快速注释所有console.log 在前端IDEA中&#xff0c;快速注释所有console.log语句可以通过以下步骤实现2&#xff1a; 打开要修改的文件。使用快捷键CtrlF打开搜索框。点击打开使用正则搜索的开关或者通过AltR快捷键来打开。在搜索框输入[]*console.log[]*&#xff0c;…...

GPT-4o图像生成功能:技术突破与隐忧并存

2025年3月25日&#xff0c;OpenAI正式推出GPT-4o原生图像生成功能&#xff0c;宣称其实现了“文本到图像的终极跨越”。然而&#xff0c;这一被市场追捧的技术在短短72小时内便因用户需求过载触发限流&#xff0c;暴露出算力瓶颈与商业化矛盾的尖锐性。这场技术狂欢的背后&…...

SQL语言分类及命令详解(二)

目录 一、DQL (Data Query Language) 数据查询语言 核心命令&#xff1a;SELECT 基本语法&#xff1a; 详细分析&#xff1a; 高级特性&#xff1a; 示例&#xff1a; 二、DDL (Data Definition Language) 数据定义语言 核心命令 CREATE ALTER DROP TRUNCATE 详细…...

机器学习——LightGBM

LightGBM(light gradient boosting machine&#xff0c;轻量梯度提升机)是对XGBoost进行改进的模型版本&#xff0c;其三者之间的演变关系为&#xff1a;GBDT-》XGBoost-》LightGBM&#xff0c;依次对性能进行优化&#xff0c;尽管XGBoost已经很高效了&#xff0c;但是仍然有缺…...

linux 常见命令使用介绍

Linux 常见命令使用介绍 Linux 是一个功能强大的操作系统&#xff0c;其核心是命令行工具。掌握一些常用的 Linux 命令可以极大地提高工作效率。本文将详细介绍一些常见的 Linux 命令及其用法。 1. 文件与目录操作 ls - 列出文件和目录 # 查看当前目录下的所有文件和子目录&…...

故障识别 | 基于改进螂优化算法(MSADBO)优化变分模态提取(VME)结合稀疏最大谐波噪声比解卷积(SMHD)进行故障诊断识别,matlab代码

基于改进螂优化算法&#xff08;MSADBO&#xff09;优化变分模态提取&#xff08;VME&#xff09;结合稀疏最大谐波噪声比解卷积&#xff08;SMHD&#xff09;进行故障诊断识别 一、引言 1.1 机械故障诊断的背景和意义 在工业生产的宏大画卷中&#xff0c;机械设备的稳定运行…...

[已解决]服务器CPU突然飙高98%----Java程序OOM问题 (2024.9.5)

目录 问题描述问题排查问题解决参考资料 问题描述 业主单位服务器自8月29日晚上21:00起CPU突然飙高至98%&#xff0c;内存爆满&#xff0c;一直到9月5日&#xff1a; 问题排查 ①执行 top 命令查看Java进程PID top②执行top -Hp PID 命令查看具体的线程情况 top -Hp 3058输入上…...

spring如何用三级缓存解决循环依赖问题

spring为何会出现循环依赖问题&#xff1f; 我们举个会产生循环依赖的例子&#xff0c;如下所示&#xff0c;可以看到AService类中依赖了BService类&#xff0c;同理呢&#xff0c;BService类中依赖了AService类&#xff0c;这就是所谓的循环依赖。 Component("aService&…...

【C#】`Task.Factory.StartNew` 和 `Task.Run` 区别

Task.Factory.StartNew 和 Task.Run 都是用来启动新任务的&#xff0c;但它们有一些关键区别&#xff0c;我们来一条一条讲清楚&#xff08;配例子 结论&#xff09;。 &#x1f19a; 1. 语法和使用目的 对比项Task.RunTask.Factory.StartNew用途简化写法&#xff0c;用于启动…...

谈谈空间复杂度考量,特别是递归调用栈空间消耗?

空间复杂度考量是算法设计的核心要素之一&#xff0c;递归调用栈的消耗问题在前端领域尤为突出。 以下结合真实开发场景进行深度解析&#xff1a; 一、递归调用栈的典型问题 1. 深层次DOM遍历的陷阱 // 危险操作&#xff1a;递归遍历未知层级的DOM树 function countDOMNode…...

【2.项目管理】2.4 Gannt图【甘特图】

甘特图&#xff08;Gantt&#xff09;深度解析与实践指南 &#x1f4ca; 一、甘特图基础模板 项目进度表示例 工作编号工作名称持续时间(月)项目进度&#xff08;周&#xff09;1需求分析3▓▓▓░░░░░░░2设计建模3░▓▓▓░░░░░░3编码开发3.5░░░▓▓▓▓░░…...

Ai工作流工具有那些如Dify、coze扣子等以及他们是否开源

Dify &#xff08;https://difycloud.com/&#xff09; 核心定位&#xff1a;专业级 LLM 应用开发平台&#xff0c;支持复杂 AI 工作流构建与企业级管理。典型场景&#xff1a;企业智能客服、数据分析系统、复杂自动化流程构建等。适合需要深度定制、企业级管理和复杂 AI 逻辑…...

【项目】C++同步异步日志系统-包含运行教程

文章目录 项目介绍地址&#xff1a;https://gitee.com/royal-never-give-up/c-log-system 开发环境核心技术为什么需要日志系统同步日志异步日志 知识补充不定参宏函数__FILE____LINE____VA_ARGS__ C使用C使用左值右值sizeof...() 运算符完美转发完整例子sizeof...() 运算符获取…...

Yolo_v8的安装测试

前言 如何安装Python版本的Yolo&#xff0c;有一段时间不用了&#xff0c;Yolo的版本也在不断地发展&#xff0c;所以重新安装了运行了一下&#xff0c;记录了下来&#xff0c;供参考。 一、搭建环境 1.1、创建Pycharm工程 首先创建好一个空白的工程&#xff0c;如下图&…...

Success is the sum of small efforts repeated day in and day out.

&#xff08;翻译&#xff1a;"成功是日复一日微小努力的总和。"&#xff09; 文章内容&#xff1a; Title: The Silent Power of Consistency &#xff08;标题翻译&#xff1a;《持续坚持的无声力量》&#xff09; Consistency is the quiet force that turns asp…...

软件兼容性测试的矩阵爆炸问题有哪些解决方案

解决软件兼容性测试中的矩阵爆炸问题主要有优先级划分、组合测试方法、自动化测试技术等方案。其中&#xff0c;组合测试方法尤其有效。组合测试通过科学的组合算法&#xff0c;能够显著降低测试用例的数量&#xff0c;同时保持较高的测试覆盖率&#xff0c;例如正交实验设计&a…...

嵌入式学习(32)-TTS语音模块SYN6288

一、概述 SYN6288 中文语音合成芯片是北京宇音天下科技有限公司于 2010年初推出的一款性/价比更高,效果更自然的一款中高端语音合成芯片。SYN6288 通过异步串口(UART)通讯方式&#xff0c;接收待合成的文本数据&#xff0c;实现文本到语音(或 TTS 语音)的转换。宇音天下于 2002…...

霸王茶姬小程序(2025年1月版)任务脚本

脚本用于自动执行微信小程序霸王茶姬的日常签到和积分管理任务。 脚本概述 脚本设置了定时任务(cron),每天运行两次,主要用于自动签到以获取积分,积分可以用来换取优惠券。 核心方法 constructor:构造函数,用于初始化网络请求的配置,设置了基础的 HTTP 请求头等。 logi…...

从零到一:打造顶尖生成式AI应用的全流程实战

简介 生成式AI正以前所未有的速度改变我们的世界&#xff0c;从内容创作到智能客服&#xff0c;再到医疗诊断&#xff0c;它正在成为各行各业的核心驱动力。然而&#xff0c;构建一个高效、安全且负责任的生成式AI系统并非易事。本文将带你从零开始&#xff0c;逐步完成一个完整…...

Windows 10更新失败解决方法

在我们使用 Windows 时的时候&#xff0c;很多时候遇到系统更新 重启之后却一直提示“我们无法完成更新&#xff0c;正在撤销更改” 这种情况非常烦人&#xff0c;但其实可以通过修改文件的方法解决&#xff0c;并且正常更新到最新版操作系统 01修改注册表 管理员身份运行注…...

Windows下在IntelliJ IDEA 使用 Git 拉取、提交脚本出现换行符问题

文章目录 背景问题拉取代码时提交代码时 问题原因解决方案1.全局配置 Git 的换行符处理策略2.在 IntelliJ IDEA 中配置换行符3.使用 .gitattributes 文件 背景 在 Windows 系统下使用 IntelliJ IDEA 进行 Git 操作&#xff08;如拉取和提交脚本&#xff09;时&#xff0c;经常…...

ubuntu24.04.2 NVIDIA GeForce RTX 4060笔记本安装驱动

https://www.nvidia.cn/drivers/details/242281/ 上面是下载地址 sudo chmod x NVIDIA-Linux-x86_64-570.133.07.run # 赋予执行权限把下载的驱动复制到家目录下&#xff0c;基本工具准备&#xff0c;如下 sudo apt update sudo apt install build-essential libglvnd-dev …...

一种监控录像视频恢复的高效解决方案,从每一帧中寻找可能性

该软件旨在恢复从监控设备中删除或丢失的视频。该程序经过调整以处理大多数流行供应商的闭路电视系统中使用的专有格式&#xff0c;并通过智能重建引擎进行了增强&#xff0c;能够为监控记录提供任何通用解决方案都无法实现的恢复结果。如果不需要持续使用该软件&#xff0c;则…...

如何快速下载并安装 Postman?

从下载、安装、启动 Postman 这三个方面为大家详细讲解下载安装 Postman 每一步操作&#xff0c;帮助初学者快速上手。 Postman 下载及安装教程(2025最新)...

Unity Shader 学习18:Shader书写基本功整理

1. Drawer [HideInInspector]&#xff1a;面板上隐藏[NoScaleOffset]&#xff1a;隐藏该纹理贴图的TillingOffset[Normal]&#xff1a;检查该纹理是否设为法线贴图[HDR]&#xff1a;将颜色类型设为高动态范围颜色&#xff08;摄像机也要开启HDR才有效果&#xff09;[PowerSlid…...

1.1 计算机网络的概念

首先来看什么是计算机网络&#xff0c;关于计算机网络的定义并没有一个统一的标准&#xff0c;不同的教材有 不同的说法&#xff08;这是王道书对于计算机网络的定义&#xff09;&#xff0c;我们可以结合自己的生活经验去体会这个 定义。 可以用不同类型的设备去连接计算机网络…...

Blender绘图——旋转曲线(以LCP与RCP为例)

最近在做左旋圆偏振光&#xff08;LCP&#xff09;与右旋圆偏振光&#xff08;RCP&#xff09;的研究&#xff0c;因此需要画出他们的图&#xff0c;接下来我就介绍一下用Blender怎么去画LCP与RCP。 首先你需要下载Blender软件&#xff0c;网上直接能搜到&#xff0c;图标如下…...

Spring与Mybatis整合

持久层整合 1.Spring框架为什么要与持久层技术进行整合 JavaEE开发需要持久层进行数据库的访问操作 JDBC Hibernate Mybatis进行持久层开发存在大量的代码冗余 Spring基于模板设计模式对于上述的持久层技术进行了封装 2.Mybatis整合 SqlSessionFactoryBean MapperScannerConfi…...

JDBC FetchSize不生效,批量变全量致OOM问题分析

背景 一个简单的基于 JDBC 采集数据库表的功能&#xff0c;当采集 Postgre SQL 某表&#xff0c;其数据量达到 500万左右的时候&#xff0c;程序一启动就将 JVM 堆内存「6G」干满了。 问题是程序中使用了游标的只前进配置&#xff0c;且设置了 fetchSize 属性&#xff1a; q…...