【密碼學實戰】Java 實現 SM2 國密算法(簽名帶id、驗簽及 C1C3C2 加密解密)

前言

SM2是中國國家密碼管理局發布的橢圓曲線公鑰密碼算法標準(GB/T 32918),屬于國密算法體系。與RSA和ECDSA相比,SM2在相同安全強度下密鑰更短、計算效率更高。本文將介紹如何在Java中實現SM2的密鑰生成數字簽名驗簽加密解密功能。

一、結果驗證

1.代碼運行結果

1.1 不帶id簽名驗簽代碼運行結果

在這里插入圖片描述

1.2 帶id簽名驗簽代碼運行結果

在這里插入圖片描述

1.3 SM2加密解密代碼運行結果

在這里插入圖片描述

2.工具驗證結果

2.1 不帶id簽名驗簽工具運行結果

在這里插入圖片描述

2.2 帶id簽名驗簽工具運行結果

在這里插入圖片描述

2.3 SM2加密解密工具運行結果

在這里插入圖片描述

二、SM2簽名原理

SM2簽名過程的核心是利用私鑰對消息進行簽名,生成簽名值 (r, s)。具體步驟如下:

  1. 計算消息的哈希值
    使用SM3哈希算法對消息 M 進行哈希處理,得到哈希值 e

  2. 生成隨機數
    選擇一個隨機數 k,滿足 1 < k < n,其中 n 是橢圓曲線的階。

  3. 計算橢圓曲線點
    使用隨機數 k 計算橢圓曲線上的點 Q = kG,其中 G 是橢圓曲線的基點。取點 Qx 坐標 x1

  4. 計算簽名值 r
    計算 r = (e + x1) mod n。如果 r = 0r + k = n,則重新選擇隨機數 k

  5. 計算簽名值 s
    計算 s = (1 + d)^{-1} * (k - r * d) mod n,其中 d 是私鑰。

  6. 輸出簽名結果
    簽名結果為 (r, s),通常以字節數組的形式存儲和傳輸。

三、SM2驗簽原理

SM2驗簽過程的核心是利用公鑰驗證簽名的有效性。具體步驟如下:

  1. 計算消息的哈希值
    使用SM3哈希算法對消息 M 進行哈希處理,得到哈希值 e

  2. 計算值 t
    計算 t = (r + s) mod n,其中 rs 是簽名值。

  3. 計算橢圓曲線點
    計算點 R = sG + tP,其中 G 是橢圓曲線的基點,P 是簽名者的公鑰。取點 Rx 坐標 x1

  4. 驗證簽名
    驗證等式 r = (e + x1) mod n 是否成立。如果成立,則簽名有效;否則,簽名無效。

四、SM2簽名與驗簽的Java實現

1. 添加依賴

pom.xml中添加Bouncy Castle依賴:

<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.70</version>
</dependency>

2. 生成密鑰對

/*** 生成SM2密鑰對。** @return 生成的密鑰對(包含公鑰和私鑰)* @throws Exception 如果密鑰生成過程中發生錯誤*/public static KeyPair generateKeyPair() throws Exception {// 添加Bouncy Castle安全提供者Security.addProvider(new BouncyCastleProvider());// 獲取SM2橢圓曲線參數(使用sm2p256v1曲線)ECParameterSpec sm2Spec = ECNamedCurveTable.getParameterSpec("sm2p256v1");// 創建EC密鑰對生成器實例KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");// 初始化密鑰對生成器,指定橢圓曲線參數和隨機數生成器kpg.initialize(sm2Spec, new SecureRandom());// 生成密鑰對并返回return kpg.generateKeyPair();}

3. 簽名不帶ID

 /*** 使用SM2算法進行簽名(不使用用戶ID)。** @param data       待簽名的數據(字節數組)* @param privateKey 簽名使用的私鑰* @return 簽名結果(字節數組)* @throws Exception 如果簽名過程中發生錯誤*/public static String signNoId(byte[] data, PrivateKey privateKey) throws Exception {// 創建SM2簽名實例,指定使用SM3哈希算法Signature signature = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), BouncyCastleProvider.PROVIDER_NAME);// 初始化簽名器,使用私鑰signature.initSign(privateKey);// 更新待簽名的數據signature.update(data);// 生成簽名byte[] signatureBytes = signature.sign();// 解析 DER 編碼的簽名結果ASN1Sequence sequence = ASN1Sequence.getInstance(signatureBytes);BigInteger r = ASN1Integer.getInstance(sequence.getObjectAt(0)).getValue();BigInteger s = ASN1Integer.getInstance(sequence.getObjectAt(1)).getValue();// 打印 r 和 s 的值System.out.println("r 的十六進制值: " + r.toString(16));System.out.println("s 的十六進制值: " + s.toString(16));// 將 r 和 s 拼接為 64 字節的簽名結果byte[] rBytes = to32Bytes(r);byte[] sBytes = to32Bytes(s);byte[] rawSignature = new byte[64];System.arraycopy(rBytes, 0, rawSignature, 0, 32);System.arraycopy(sBytes, 0, rawSignature, 32, 32);// 生成簽名并返回return Hex.toHexString(rawSignature);}

4. 驗簽不帶ID

/*** 驗證SM2簽名(不使用用戶ID)** @param data       待驗證的數據(明文)* @param signature  簽名數據(字節數組)* @param publicKey  公鑰* @return 驗簽結果(true表示成功,false表示失敗)* @throws Exception 如果驗簽過程中發生錯誤*/public static boolean verifyNoId(byte[] data, byte[] signature, PublicKey publicKey) throws Exception {// 初始化SM2簽名算法(使用SM3哈希算法)Signature verifier = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), BouncyCastleProvider.PROVIDER_NAME);// 初始化驗證器,使用公鑰verifier.initVerify(publicKey);// 更新待驗證的數據verifier.update(data);// 將 r 和 s 拼接格式的簽名結果轉換為 DER 編碼格式byte[] derSignature = convertRawSignatureToDER(signature);// 驗證簽名return verifier.verify(derSignature);}

5. 測試代碼

public static void main(String[] args) throws Exception {// 生成密鑰對KeyPair keyPair = generateKeyPair();PublicKey publicKey = keyPair.getPublic();PrivateKey privateKey = keyPair.getPrivate();// 提取公鑰的 x 和 y 坐標String publicKeyX = ((ECPublicKey) publicKey).getQ().getAffineXCoord().toBigInteger().toString(16);String publicKeyY = ((ECPublicKey) publicKey).getQ().getAffineYCoord().toBigInteger().toString(16);// 拼接 x 和 y 坐標String publicKeyXY = publicKeyX + publicKeyY;System.out.println("X: " + publicKeyX);System.out.println("Y: " + publicKeyY);//System.out.println("公鑰: " + publicKeyXY);// 打印私鑰的十六進制表示BigInteger privateKeyD = ((ECPrivateKey) privateKey).getD();System.out.println("私鑰HEX: " + privateKeyD.toString(16));// 待簽名數據String data = "12345";String newData = "1234567";byte[] dataBytes = data.getBytes();//System.out.printf("原文: "+data);byte[] newDat = newData.getBytes();//System.out.printf("原文修改: "+newData);// 簽名String signature = signNoId(dataBytes, privateKey);System.out.println("簽名結果: " + signature);// 驗簽boolean isValid = verifyNoId(dataBytes, Hex.decode(signature), publicKey);System.out.println("驗簽值: " + isValid);// 修改原文驗簽boolean isVa = verifyNoId(newDat, Hex.decode(signature), publicKey);System.out.println("修改原文驗簽結果: " + isVa);System.out.printf("==========================================================: ");// 簽名帶idString dataID = "12345";String dataNew = "123456";String userId ="1234567812345678";String signatureId = signWithID(privateKey, publicKey, dataID, userId);System.out.println("帶id簽名結果: " + signatureId);// 驗簽帶idboolean isValidId = verifyWithID(publicKey, dataID, userId, Hex.decode(signatureId));System.out.println("帶id驗簽值: " + isValidId);// 驗簽帶id原文修改驗證boolean isValidIdNew = verifyWithID(publicKey, dataNew, userId, Hex.decode(signatureId));System.out.println("帶id驗簽值原文修改: " + isValidIdNew);}

五 、SM2帶ID簽名與驗簽Java實現

SM2簽名標準要求計算哈希值時包含用戶身份標識(ID),默認ID為空字符串。但在實際應用中(如金融場景),需明確指定用戶ID(如身份證號、手機號等)。以下是Java實現方法:

1.算法原理解析

SM2簽名算法中,用戶ID(即userId)被用于生成一個關鍵值 ZA,其目的是將用戶身份與密鑰綁定,增強安全性。具體步驟如下:

  1. ZA值計算
    ZA通過哈希函數(SM3)生成,計算公式為:

    復制

    ZA = HASH( ENTLA || ID || a || b || xG || yG || xA || yA )
    
    • ENTLA:用戶ID的比特長度(占2字節,如ID長度256比特則值為0x0100)
    • ID:用戶自定義標識(如身份證號、手機號)
    • a, b:橢圓曲線方程參數
    • (xG, yG):橢圓曲線基點坐標
    • (xA, yA):簽名方的公鑰坐標
  2. 簽名過程

    • 輸入:私鑰、待簽名數據M、用戶ID
    • 輸出:簽名結果(r, s)
    1. 計算 ZA(如上)
    2. 計算 e = HASH(ZA || M)
    3. 生成隨機數k,計算橢圓曲線點(x1, y1) = [k]G
    4. 計算 r = (e + x1) mod n
    5. 若r=0或r+k=n,則重新生成k
    6. 計算 s = ((1 + d)^?1 * (k ? r * d)) mod n(d為私鑰)
    7. 返回(r, s)
    
  3. 驗簽過程

    • 輸入:公鑰、簽名(r, s)、原始數據M、用戶ID
    • 輸出:驗簽結果(true/false)
    1. 校驗r和s是否在[1, n-1]范圍內
    2. 計算 ZA(與簽名方相同ID)
    3. 計算 e = HASH(ZA || M)
    4. 計算 t = (r + s) mod n
    5. 計算橢圓曲線點(x1, y1) = [s]G + [t]P(P為公鑰)
    6. 驗證 R = (e + x1) mod n 是否等于r
    

2.代碼實現

  1. 帶ID的簽名
/*** 使用 SM2 算法進行帶用戶 ID 的簽名,并返回 r 和 s 的拼接結果** @param privateKey 私鑰* @param publicKey  公鑰* @param data       待簽名的數據* @param userId     用戶 ID(如企業編號、用戶身份證等)* @return 簽名結果(Hex 編碼的字符串,64 字節)* @throws Exception 如果簽名過程中發生錯誤*/public static String signWithID(PrivateKey privateKey, PublicKey publicKey, String data, String userId) throws Exception {// 將私鑰轉換為 ECPrivateKeyParametersECPrivateKeyParameters ecPrivateKey = convertPrivateKey(privateKey);// 將公鑰轉換為 ECPublicKeyParametersECPublicKeyParameters ecPublicKey = convertPublicKey(publicKey);// 創建 SM2 簽名器SM2Signer signer = new SM2Signer(new SM3Digest());// 初始化簽名器,傳入私鑰和用戶 IDsigner.init(true, new ParametersWithID(ecPrivateKey, userId.getBytes(StandardCharsets.UTF_8)));// 更新待簽名的數據signer.update(data.getBytes(StandardCharsets.UTF_8), 0, data.length());// 生成簽名byte[] signResult = signer.generateSignature();// 解析 DER 編碼的簽名結果ASN1Sequence sequence = ASN1Sequence.getInstance(signResult);BigInteger r = ASN1Integer.getInstance(sequence.getObjectAt(0)).getValue();BigInteger s = ASN1Integer.getInstance(sequence.getObjectAt(1)).getValue();// 打印 r 和 s 的值System.out.println("r 的十六進制值: " + r.toString(16));System.out.println("s 的十六進制值: " + s.toString(16));// 將 r 和 s 拼接為 64 字節的簽名結果byte[] rBytes = to32Bytes(r);byte[] sBytes = to32Bytes(s);byte[] rawSignature = new byte[64];System.arraycopy(rBytes, 0, rawSignature, 0, 32);System.arraycopy(sBytes, 0, rawSignature, 32, 32);// 返回 Hex 編碼的簽名結果return Hex.toHexString(rawSignature);}
  1. 帶ID的驗簽
/*** 使用 SM2 算法進行帶用戶 ID 的驗簽** @param publicKey  公鑰* @param data       待驗簽的數據* @param userId     用戶 ID(必須與簽名時一致)* @param signature  簽名結果(字節數組,r 和 s 的拼接格式)* @return 驗簽結果(true 表示驗簽成功,false 表示驗簽失敗)* @throws Exception 如果驗簽過程中發生錯誤*/public static boolean verifyWithID(PublicKey publicKey, String data, String userId, byte[] signature) throws Exception {// 將公鑰轉換為 ECPublicKeyParametersECPublicKeyParameters ecPublicKey = convertPublicKey(publicKey);// 創建 SM2 驗簽器SM2Signer verifier = new SM2Signer(new SM3Digest());// 初始化驗簽器,傳入公鑰和用戶 IDverifier.init(false, new ParametersWithID(ecPublicKey, userId.getBytes(StandardCharsets.UTF_8)));// 更新待驗簽的數據verifier.update(data.getBytes(StandardCharsets.UTF_8), 0, data.length());// 將 r 和 s 拼接格式的簽名結果轉換為 DER 編碼格式byte[] derSignature = convertRawSignatureToDER(signature);// 驗簽return verifier.verifySignature(derSignature);}

六、SM2加密與解密Java實現

1.SM2加密原理

  1. SM2加密過程主要基于橢圓曲線的數學特性,通過公鑰對明文數據進行加密。具體步驟如下:

    1. 選擇橢圓曲線參數
      • 使用橢圓曲線參數(如sm2p256v1),這些參數包括橢圓曲線方程的系數、基點G以及基點的階n
    2. 生成隨機數k
      • 選擇一個隨機數k1 < k < n),用于生成橢圓曲線上的一個點R = [k]G
    3. 計算密文
      • 使用公鑰P(簽名方的公鑰)和隨機點R,根據SM2的加密公式計算密文。SM2支持兩種加密模式:
        • C1C3C2模式:密文格式為C1 || C3 || C2
        • C1C2C3模式:密文格式為C1 || C2 || C3
      • 其中:
        • C1是隨機點R的編碼。
        • C2是經過加密的明文數據。
        • C3是消息的哈希值,用于驗證數據完整性。
    4. 輸出密文
      • 將計算得到的C1C2C3拼接成最終的密文。

2.SM2解密原理

解密過程是加密的逆操作,使用私鑰對密文進行解密,還原出原始明文。具體步驟如下:

  1. 解析密文
    • 將密文拆分為C1C2C3
  2. 計算橢圓曲線點
    • 使用私鑰dC1中的點R,根據SM2的解密公式計算橢圓曲線上的一個點。
  3. 還原明文
    • 利用橢圓曲線的數學特性,結合C1C2C3,通過解密公式還原出原始明文。
  4. 驗證數據完整性
    • 使用C3驗證解密后的數據是否被篡改。

3.代碼實現

  1. 添加依賴

pom.xml中添加Bouncy Castle依賴:

<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.70</version>
</dependency>
  1. 生成密鑰對
  /*** 生成SM2密鑰對*/public static KeyPair generateSM2KeyPair() throws Exception {// 獲取SM2橢圓曲線參數X9ECParameters ecParameters = GMNamedCurves.getByName("sm2p256v1");ECParameterSpec ecSpec = new ECParameterSpec(ecParameters.getCurve(),ecParameters.getG(),ecParameters.getN(),ecParameters.getH());// 創建密鑰對生成器KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");keyPairGenerator.initialize(ecSpec, new SecureRandom());return keyPairGenerator.generateKeyPair();}
  1. 公鑰加密
 /*** SM2加密(C1C3C2模式)* @param publicKey 公鑰* @param data 待加密數據* @return 加密后的字節數組(C1C3C2格式)*/public static byte[] encrypt(BCECPublicKey publicKey, byte[] data) throws Exception {// 獲取橢圓曲線參數ECDomainParameters domainParams = new ECDomainParameters(publicKey.getParameters().getCurve(),publicKey.getParameters().getG(),publicKey.getParameters().getN());// 創建加密引擎(默認輸出C1C3C2格式)SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);// 初始化加密引擎ECPublicKeyParameters pubKeyParams = new ECPublicKeyParameters(publicKey.getQ(),domainParams);engine.init(true, new ParametersWithRandom(pubKeyParams, new SecureRandom()));return engine.processBlock(data, 0, data.length);}
  1. 私鑰解密
/*** SM2解密(C1C3C2模式)* @param privateKey 私鑰* @param cipherData 密文數據(C1C3C2格式)* @return 解密后的字節數組*/public static byte[] decrypt(BCECPrivateKey privateKey, byte[] cipherData) throws Exception {// 獲取橢圓曲線參數ECDomainParameters domainParams = new ECDomainParameters(privateKey.getParameters().getCurve(),privateKey.getParameters().getG(),privateKey.getParameters().getN());// 創建解密引擎(設置為C1C3C2模式)SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);// 初始化解密引擎ECPrivateKeyParameters priKeyParams = new ECPrivateKeyParameters(privateKey.getD(),domainParams);engine.init(false, priKeyParams);return engine.processBlock(cipherData, 0, cipherData.length);}

注意事項

  1. 密鑰管理:私鑰需安全存儲(如密碼機或云密碼機等)
  2. 性能優化:加解密大數據時建議使用SM4對稱加密配合SM2密鑰交換
  3. ID編碼userId.getBytes() 需與業務方約定編碼格式(如UTF-8、HEX等)
  4. 長度限制:ID長度建議不超過65535字節(規范限制)
  5. 跨系統交互:與其他系統(如C++、Go)對接時需確認ID處理邏輯一致性

總結

希望這篇文章對你有所幫助!如果覺得不錯,別忘了關注哦!

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

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

相關文章

網絡原理---TCP/IP

活動發起人小虛竹 想對你說&#xff1a; 這是一個以寫作博客為目的的創作活動&#xff0c;旨在鼓勵大學生博主們挖掘自己的創作潛能&#xff0c;展現自己的寫作才華。如果你是一位熱愛寫作的、想要展現自己創作才華的小伙伴&#xff0c;那么&#xff0c;快來參加吧&#xff01…

【大語言模型筆記進階一步】提示語設計學習筆記,跳出框架思維,自己構建提示詞

一、大語言模型應用場景 1. 文本生成 文本創作&#xff1a; 詩歌故事&#xff0c;劇本&#xff0c;推文帖子 摘要與改寫&#xff1a; 長文本摘要與簡化&#xff0c;多語言翻譯與本地化 結構化生成&#xff1a; 表格&#xff0c;根據需求生成代碼片段&#xff0c;API文檔生成…

Unity XR-XR Interaction Toolkit開發使用方法(十一)組件介紹(XR Interactable)

目錄 一、插件介紹 二、主要組件 XR Interaction Manager XR Controller XR Interactor XR Direct Interactor XR Ray Interactor XR Socket Interactor XR Gaze Interactor XR Interaction Group 三、XR Interactable 1、組件介紹 2、核心功能與特點 交互類型支…

Spring Boot spring-boot-maven-plugin 參數配置詳解

一 spring-boot-maven-plugin 插件的5個Goals spring-boot:repackage&#xff0c;默認goal。在mvn package之后&#xff0c;再次打包可執行的jar/war&#xff0c;同時保留mvn package生成的jar/war為.origin&#xff1b;重新打包存在的jar或者war包從而使他們可以在命令行使用…

eMMC安全簡介

1. 引言 術語“信息安全”涵蓋多種不同的設計特性。一般而言&#xff0c; 信息安全是指通過實踐防止信息遭受未經授權的訪問、使用、披露、中斷、篡改、檢查、記錄或銷毀。 信息安全的三大核心目標為 機密性&#xff08;Confidentiality&#xff09;、完整性&#xff08;Integr…

Python 數據結構 2.時間復雜度和空間復雜度

Life is a journey —— 25.2.28 一、引例&#xff1a;窮舉法 1.單層循環 所謂窮舉法&#xff0c;就是我們通常所說的枚舉&#xff0c;就是把所有情況都遍歷了的意思。 例&#xff1a;給定n&#xff08;n ≤ 1000&#xff09;個元素ai&#xff0c;求其中奇數有多少個 判斷一…

FFmpeg-chapter3-讀取視頻流(原理篇)

ffmpeg網站&#xff1a;About FFmpeg 1 庫介紹 &#xff08;1&#xff09;libavutil是一個包含簡化編程函數的庫&#xff0c;包括隨機數生成器、數據結構、數學例程、核心多媒體實用程序等等。 &#xff08;2&#xff09;libavcodec是一個包含音頻/視頻編解碼器的解碼器和編…

面試(進階) —虛擬列表在什么場景使用,如何實現?

面試(進階) —虛擬列表在什么場景使用&#xff0c;如何實現&#xff1f; 在前端開發中&#xff0c;當需要渲染大量數據時&#xff0c;傳統的渲染方式往往會遇到性能瓶頸。一次性將大量數據渲染到DOM中&#xff0c;不僅會導致頁面加載緩慢&#xff0c;還可能占用大量內存&#x…

Linux Mem -- 關于AArch64 MTE功能的疑問

目錄 1.虛擬地址和物理地址映射完成后&#xff0c;才可以設置虛擬地址對應的memory tag &#xff1f; 2.各種memory allocator中的address tag從哪來&#xff0c;怎么產生&#xff1f; 2.1 vmalloc allocator 2.2 slub分配器 2.3 用戶可以指定IRG指令產生的address tag 3.kasan…

python-leetcode-顏色分類

75. 顏色分類 - 力扣&#xff08;LeetCode&#xff09; class Solution:def sortColors(self, nums: List[int]) -> None:"""Do not return anything, modify nums in-place instead."""low, mid, high 0, 0, len(nums) - 1while mid < h…

ArcGIS Pro技巧實戰:高效矢量化天地圖地表覆蓋圖

在地理信息系統&#xff08;GIS&#xff09;領域&#xff0c;地表覆蓋圖的矢量化是一項至關重要的任務。天地圖作為中國國家級的地理信息服務平臺&#xff0c;提供了豐富且詳盡的地表覆蓋數據。然而&#xff0c;這些數據通常以柵格格式存在&#xff0c;不利于進行空間分析和數據…

【江科大STM32】TIM輸出比較(學習筆記)

本章圖片文字內容也為重要知識&#xff0c;請馬住&#xff01; 輸出比較簡介 OC&#xff08;Output Compare&#xff09;輸出比較輸出比較可以通過比較CNT與CCR寄存器值的關系&#xff0c;來對輸出電平進行置1、置0或翻轉的操作&#xff0c;用于輸出一定頻率和占空比的PWM波形…

【網絡安全 | 漏洞挖掘】利用文件上傳功能的 IDOR 和 XSS 劫持會話

未經許可,不得轉載。 本文涉及漏洞均已修復。 文章目錄 前言正文前言 想象這樣一個場景:一個專門處理敏感文檔的平臺,如保險理賠或身份驗證系統,卻因一個設計疏漏而成為攻擊者的“金礦”。在對某個保險門戶的文件上傳功能進行測試時,我意外發現了一個可導致大規模賬戶接管…

飛算 JavaAI 如何讓微服務開發快人一步?

在當今競爭激烈的軟件開發領域&#xff0c;微服務架構因其靈活性和可擴展性備受青睞。然而&#xff0c;微服務開發過程復雜&#xff0c;從需求分析到最終代碼實現&#xff0c;每個環節都需要耗費大量時間和精力。飛算 JavaAI 的出現&#xff0c;猶如一道曙光&#xff0c;為開發…

Python—Excel全字段轉json文件(極速版+GUI界面打包)

目錄 專欄導讀1、背景介紹2、庫的安裝3、核心代碼4、完整代碼(簡易版)5、進階版(GUI)總結專欄導讀 ?? 歡迎來到Python辦公自動化專欄—Python處理辦公問題,解放您的雙手 ?????? 博客主頁:請點擊——> 一晌小貪歡的博客主頁求關注 ?? 該系列文章專欄:請點擊——…

2025年光電科學與智能傳感國際學術會議(ICOIS 2025)

重要信息 官網&#xff1a;www.ic-icois.org 時間&#xff1a;2025年3月14-16日 地點&#xff1a;中國-長春 簡介 2025年光電科學與智能傳感國際學術會議&#xff08;ICOIS 2025&#xff09;將于2025年3月14-16日在中國-長春隆重召開。會議將圍繞“光學光電”、“智能傳感”…

企業微信里可以使用的企業內刊制作工具,FLBOOK

如何讓員工及時了解公司動態、行業資訊、學習專業知識&#xff0c;并有效沉淀企業文化&#xff1f;一份高質量的企業內刊是不可或缺的。現在讓我來教你該怎么制作企業內刊吧 1.登錄與上傳 訪問FLBOOK官網&#xff0c;注冊賬號后上傳排版好的文檔 2.選擇模板 FLBOOK提供了豐富的…

YOLOv5 + SE注意力機制:提升目標檢測性能的實踐

一、引言 目標檢測是計算機視覺領域的一個重要任務&#xff0c;廣泛應用于自動駕駛、安防監控、工業檢測等領域。YOLOv5作為YOLO系列的最新版本&#xff0c;以其高效性和準確性在實際應用中表現出色。然而&#xff0c;隨著應用場景的復雜化&#xff0c;傳統的卷積神經網絡在處…

跟我學C++中級篇——定時器的設計

一、定時器 談到定時器&#xff0c;理論上講是各種語言和各種設計都無法避開的一個技術點。對于定時器來說&#xff0c;表面上就是一種時間間隔的處理約定&#xff0c;但對程序來說&#xff0c;可能就是設計層面、接口層面和庫或框架以及系統應用的一個大集合。不同的系統&…

智能機器人加速進化:AI大模型與傳感器的雙重buff加成

Deepseek不僅可以在手機里為你解答現在的困惑、占卜未來的可能&#xff0c;也將成為你的貼心生活幫手&#xff01; 2月21日&#xff0c;追覓科技旗下Dreamehome APP正式接入DeepSeek-R1大模型&#xff0c;2月24日發布的追覓S50系列掃地機器人也成為市面上首批搭載DeepSeek-R1的…