國密算法(SM2/SM3/SM4)

文章目錄

      • 國密算法(SM2/SM3/SM4)詳解:從性能對比到Java手機號安全處理實戰
      • 一、 國密核心算法簡介
      • 二、 性能深度對比
      • 三、 Java實戰:手機號的安全處理
        • 方案一:使用SM3哈希存儲(推薦用于驗證場景)
        • 方案二:使用SM4加密存儲(用于需要原文的場景)
      • Java代碼示例
        • 示例1:使用SM3哈希手機號(含加鹽)
        • 示例2:使用SM4加密/解密手機號
      • 結論


國密算法(SM2/SM3/SM4)詳解:從性能對比到Java手機號安全處理實戰

隨著信息安全上升為國家戰略,國密(國家商用密碼)算法在金融、政務、物聯網等關鍵領域得到了廣泛應用。本文將帶您深入了解國密的核心算法(SM2/SM3/SM4),對比它們的性能差異,并提供一份在Java中安全處理手機號的完整代碼示例。

一、 國密核心算法簡介

國密算法是一套由國家密碼管理局發布的商用密碼標準,主要包含以下三個核心算法:

  1. SM2:非對稱加密算法

    • 類型:非對稱加密與簽名算法。
    • 對標:國際上的 ECC(橢圓曲線密碼算法),功能類似 RSA。
    • 用途:主要用于數字簽名身份認證密鑰協商。由于其計算復雜度高,不適合加密大量數據,通常用于加密對稱密鑰(如SM4的密鑰)或對數據摘要進行簽名。
  2. SM3:哈希算法

    • 類型:密碼雜湊算法(哈希函數)。
    • 對標:國際上的 SHA-256。
    • 用途:用于生成數據的唯一“數字指紋”,以保證數據完整性身份驗證。它是一個單向函數,意味著無法從哈希值反推出原文。這是存儲密碼、手機號等敏感信息的理想選擇。
  3. SM4:對稱加密算法

    • 類型:對稱加密算法(分組密碼)。
    • 對標:國際上的 AES。
    • 用途:用于大量數據(如文件、通信報文)的加密和解密。收發雙方使用相同的密鑰進行加解密,速度快,效率高。

二、 性能深度對比

這三個算法的設計目標不同,因此性能差異巨大。簡單來說,它們的計算速度排行如下:

SM3 (最快) > SM4 (很快) > SM2 (相對最慢)

算法類型計算復雜度相對速度形象比喻
SM3哈希算法最低(位運算、邏輯運算)最快指紋識別器:瞬間完成,給出唯一結果。
SM4對稱加密中等(多輪迭代、查表)很快保險箱:用同一把鑰匙開關,操作迅速。
SM2非對稱加密最高(橢圓曲線點乘運算)最慢銀行保險柜:開戶和存取手續嚴謹復雜,但安全性最高。
  • 為什么SM3最快? 它的計算是純粹的位運算,CPU執行效率極高,專為速度而生。
  • 為什么SM4居中? 它需要對數據分組并進行多輪復雜的迭代變換,比SM3慢,但遠快于SM2,適合處理大數據。
  • 為什么SM2最慢? 它基于復雜的橢圓曲線數學難題,計算量巨大,但提供了非對稱加密獨有的安全性(如密鑰交換和數字簽名)。

三、 Java實戰:手機號的安全處理

對于“加密”手機號,我們有兩種主流且安全的方案,適用于不同業務場景。

方案一:使用SM3哈希存儲(推薦用于驗證場景)

當你的業務只需要驗證用戶輸入的手機號是否正確,而不需要知道手機號原文時(例如用戶注冊、登錄),這是最安全、最推薦的做法。

  • 優點:不可逆。即使數據庫泄露,攻擊者也無法獲得原始手機號。
  • 實踐:結合**加鹽(Salt)**可以抵御彩虹表攻擊,安全性更高。
方案二:使用SM4加密存儲(用于需要原文的場景)

當你的業務必須使用手機號原文時(例如發送短信驗證碼、進行外呼),你需要使用可逆的對稱加密。

  • 優點:可以解密還原出原始手機號。
  • 挑戰密鑰的保護至關重要。密鑰一旦泄露,所有數據都將暴露。

Java代碼示例

首先,請確保你的項目中已添加 Bouncy Castle 依賴。

Maven pom.xml:

<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk18on</artifactId><version>1.78.1</version>
</dependency>
示例1:使用SM3哈希手機號(含加鹽)
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;/*** 國密 SM3 哈希工具類(推薦用于密碼、手機號等敏感信息的存儲)*/
public class Sm3Demo {static {// 注冊 Bouncy Castle 提供者if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {Security.addProvider(new BouncyCastleProvider());}}/*** 生成一個安全的隨機鹽* @param aLength 鹽的字節長度* @return 十六進制表示的鹽字符串*/public static String generateSalt(int length) {SecureRandom random = new SecureRandom();byte[] salt = new byte[length];random.nextBytes(salt);return Hex.toHexString(salt);}/*** 對輸入字符串進行加鹽 SM3 哈希** @param input 待哈希的原文* @param salt  鹽值(十六進制字符串)* @return 64位的十六進制哈希值*/public static String hashWithSalt(String input, String salt) {if (input == null || salt == null) {return null;}// 鹽值在前或在后,或混合都可以,但要保持一致String dataToHash = salt + input;try {MessageDigest digest = MessageDigest.getInstance("SM3", BouncyCastleProvider.PROVIDER_NAME);byte[] hashBytes = digest.digest(dataToHash.getBytes(StandardCharsets.UTF_8));return Hex.toHexString(hashBytes);} catch (NoSuchAlgorithmException e) {throw new RuntimeException("SM3 algorithm not found", e);}}public static void main(String[] args) {String phoneNumber = "15888888888";// 1. 為該手機號生成一個唯一的鹽// 在實際應用中,這個鹽需要與哈希值一起存儲在數據庫的用戶記錄中String salt = generateSalt(16); // 生成16字節(32個十六進制字符)的鹽System.out.println("原始手機號: " + phoneNumber);System.out.println("生成的鹽 (Salt): " + salt);// 2. 計算加鹽后的哈希值String hashedPhoneNumber = hashWithSalt(phoneNumber, salt);System.out.println("SM3 加鹽哈希值: " + hashedPhoneNumber);System.out.println("哈希值長度: " + hashedPhoneNumber.length());// 3. 驗證過程 (模擬用戶登錄)System.out.println("\n--- 用戶驗證 ---");String userInputPhone = "15888888888";// 從數據庫中取出該用戶存儲的 salt 和 hashedPhoneNumberString storedSalt = salt;String storedHash = hashedPhoneNumber;// 使用相同的鹽對用戶輸入進行哈希String verificationHash = hashWithSalt(userInputPhone, storedSalt);System.out.println("驗證哈希: " + verificationHash);System.out.println("驗證是否通過: " + storedHash.equals(verificationHash));// 錯誤輸入String wrongInputPhone = "15800000000";String wrongVerificationHash = hashWithSalt(wrongInputPhone, storedSalt);System.out.println("錯誤輸入驗證是否通過: " + storedHash.equals(wrongVerificationHash));}
}
示例2:使用SM4加密/解密手機號
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.Security;/*** 國密 SM4 對稱加密工具類(用于需要還原原文的場景)*/
public class Sm4Demo {static {if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {Security.addProvider(new BouncyCastleProvider());}}private static final String ALGORITHM_NAME = "SM4";// SM4/CBC/PKCS5Padding 是一種常用的加密模式// CBC 模式需要一個初始化向量 (IV)private static final String PADDING_MODE = "SM4/CBC/PKCS5Padding";/*** 生成一個 SM4 密鑰 (128位/16字節)* @return Base64 編碼的密鑰字符串*/public static String generateKey() throws Exception {KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);kg.init(128, new SecureRandom());return Base64.toBase64String(kg.generateKey().getEncoded());}/*** 生成一個初始化向量 (IV) (128位/16字節)* @return Base64 編碼的 IV 字符串*/public static String generateIv() {byte[] iv = new byte[16];new SecureRandom().nextBytes(iv);return Base64.toBase64String(iv);}/*** SM4 加密* @param plainText 明文* @param key Base64 編碼的密鑰* @param iv Base64 編碼的 IV* @return Base64 編碼的密文*/public static String encrypt(String plainText, String key, String iv) throws Exception {SecretKeySpec keySpec = new SecretKeySpec(Base64.decode(key), ALGORITHM_NAME);IvParameterSpec ivSpec = new IvParameterSpec(Base64.decode(iv));Cipher cipher = Cipher.getInstance(PADDING_MODE, BouncyCastleProvider.PROVIDER_NAME);cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));return Base64.toBase64String(encryptedBytes);}/*** SM4 解密* @param cipherText Base64 編碼的密文* @param key Base64 編碼的密鑰* @param iv Base64 編碼的 IV* @return 明文*/public static String decrypt(String cipherText, String key, String iv) throws Exception {SecretKeySpec keySpec = new SecretKeySpec(Base64.decode(key), ALGORITHM_NAME);IvParameterSpec ivSpec = new IvParameterSpec(Base64.decode(iv));Cipher cipher = Cipher.getInstance(PADDING_MODE, BouncyCastleProvider.PROVIDER_NAME);cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);byte[] decryptedBytes = cipher.doFinal(Base64.decode(cipherText));return new String(decryptedBytes, StandardCharsets.UTF_8);}public static void main(String[] args) throws Exception {String phoneNumber = "15888888888";// 在真實應用中,密鑰和 IV 必須被安全地存儲和管理,例如使用硬件加密機(HSM)或配置中心String sm4Key = generateKey();String sm4Iv = generateIv();System.out.println("原始手機號: " + phoneNumber);System.out.println("SM4 密鑰 (Base64): " + sm4Key);System.out.println("SM4 IV (Base64): " + sm4Iv);// 加密String encryptedPhone = encrypt(phoneNumber, sm4Key, sm4Iv);System.out.println("SM4 加密后 (Base64): " + encryptedPhone);// 解密String decryptedPhone = decrypt(encryptedPhone, sm4Key, sm4Iv);System.out.println("SM4 解密后: " + decryptedPhone);System.out.println("解密是否成功: " + phoneNumber.equals(decryptedPhone));}
}

結論

  • 選擇合適的工具:沒有“最好”的算法,只有“最合適”的場景。請根據你的業務需求選擇正確的國密算法。
  • SM3哈希優先:當處理用戶密碼、手機號等用于驗證的敏感信息時,優先采用SM3加鹽哈希,這是最安全的存儲方式。
  • 謹慎使用SM4:只有在業務流程中確實需要恢復原文時,才使用SM4加密。同時,必須投入資源確保密鑰的安全,因為密鑰就是一切。
  • 協同工作:在復雜的系統中,SM2、SM3、SM4往往協同工作,共同構建起一個完整的、高強度的安全體系。

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

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

相關文章

從前端轉go開發的學習路線

從前端開發轉向 Go&#xff08;Golang&#xff09;后端開發&#xff0c;是一個非常可行也很實用的方向&#xff0c;特別是在做 高性能微服務、分布式系統、云原生&#xff08;如Kubernetes&#xff09; 等方面。以下是一份適合你&#xff08;有多年開發經驗的前端開發者&#x…

node或瀏覽器上傳文件到阿里云OSS

阿里云配置 進入阿里云OSS Bucket 列表的某個 Bucket 倉庫下&#xff0c;點擊訪問控制 RAM 創建用戶 勾上 創建 AccessKey ID 和 AccessKey Secret 復制 AccessKey 信息 用文檔保存 創建角色 選擇云賬號 復制 ARN 用文檔保存&#xff0c;然后 新增權限 搜索 oss 選擇 AliyunOSS…

26考研物理復試面試常見問答問題匯總,物理專業保研推免夏令營面試問題匯總,物理本科知識專業面試最全攻略!

還在為物理考研復試面試發愁&#xff1f;還在為物理招聘的專業面試抓狂&#xff1f;還在為即將到來的物理夏令營面試不知從何下手、翻遍了厚厚的教材卻抓不住重點&#xff1f;別慌&#xff0c;接下來我會從「考研的物理復試經歷」「物理面試攻略」「物理面試基礎問答題匯總很全…

(5)機器學習小白入門 YOLOv:數據需求與圖像不足應對策略

(1)機器學習小白入門YOLOv &#xff1a;從概念到實踐 (2)機器學習小白入門 YOLOv&#xff1a;從模塊優化到工程部署 (3)機器學習小白入門 YOLOv&#xff1a; 解鎖圖片分類新技能 (4)機器學習小白入門YOLOv &#xff1a;圖片標注實操手冊 (5)機器學習小白入門 YOLOv&#xff1a;…

百年制造名企,三菱重工引領“智”造新范式

日前&#xff0c;由深圳軟件協會指導、法大大和信息俠聯合出品的《制造行業合同數智化升級白皮書》&#xff08;以下簡稱“白皮書”&#xff09;正式發布&#xff0c;并首次提出 “電子簽法律AI” 雙輪驅動模型。在制造行業面臨供應鏈協同、合規風控及全球化出海等多重挑戰的當…

【學習筆記】計算機操作系統(七)—— 文件管理

第七章 文件管理 文章目錄第七章 文件管理7.1 文件和文件系統7.1.1 數據項、記錄和文件7.1.2 文件名和類型7.1.3 文件系統的層次結構7.1.4 文件操作7.2 文件的邏輯結構7.2.1 文件邏輯結構的類型7.2.2 順序文件(Sequential File)7.2.3 記錄尋址7.2.4 索引文件(Index File)7.2.5 …

基于PyQt5與深度學習的可視化水果識別系統(集成CNN, MobileNetV2, VGG16)

一、項目概述 大家好&#xff01;今天我將分享一個我近期完成的深度學習項目——一個功能強大的、帶圖形化界面&#xff08;GUI&#xff09;的水果識別系統。該系統不僅能識別靜態圖片中的水果&#xff0c;還集成了模型訓練、評估、數據增強等功能于一體&#xff0c;為深度學習…

k8s-服務發布基礎

目錄 Service的定義 核心定義 Service 的類型 關鍵組件與機制 工作流程示例 高級特性 Service工作原理 核心工作原理 標簽選擇器&#xff08;Label Selector&#xff09; Endpoints 對象 網絡代理與負載均衡&#xff08;kube-proxy&#xff09; userspace 模式&#…

洛谷P1514 [NOIP 2010 提高組] 引水入城

洛谷P1514 [NOIP 2010 提高組] 引水入城 洛谷題目傳送門 題目背景 NOIP2010 提高組 T4 題目描述 在一個遙遠的國度&#xff0c;一側是風景秀美的湖泊&#xff0c;另一側則是漫無邊際的沙漠。該國的行政區劃十分特殊&#xff0c;剛好構成一個 NNN 行 MMM 列的矩形&#xff…

【unity小技巧】國內Unity6下載安裝和一些Unity6新功能使用介紹

文章目錄前言一、安裝1、國外下載2、國內下載二、常用的新功能變化1、官方推薦使用inputsystem進行輸入控制2、修復了InputSystem命名錯誤導致listen被遮擋的bug3、自帶去除unity啟動畫面logo功能4、unity官方的behavior行為樹插件5、linearVelocity代替過時的velocity方法6、隨…

Rust 中字符串類型區別解析

在 Rust 中&#xff0c;"hello" 和 String::from("hello") 都表示字符串&#xff0c;但它們在內存表示、所有權和可變性上有本質區別&#xff1a;1. 類型與內存表示"hello" (字符串字面量)&#xff1a;類型為 &str&#xff08;字符串切片引用…

springMVC05-異常處理器

在 SpringMVC 中&#xff0c;異常處理是一個非常重要的功能&#xff0c;它可以讓你優雅地處理程序拋出的各種異常&#xff0c;向用戶展示友好的提示&#xff0c;而不是顯示一堆報錯信息&#xff08;如 500 頁面&#xff09;。一、SpringMVC的異常處理器返回的是ModelAndView&am…

安裝 Elasticsearch IK 分詞器

安裝 Elasticsearch IK 分詞器&#xff08;手動 .zip/.zip 安裝&#xff09; IK 分詞器&#xff08;IK Analysis&#xff09;是 Elasticsearch 最常用的中文分詞插件&#xff0c;支持 細粒度分詞&#xff08;ik_max_word&#xff09; 和 智能切分&#xff08;ik_smart&#xf…

數據庫系統原理實驗1:創建數據庫、數據表及單表查詢

一、實驗目的1&#xff0e;掌握在SQL Server中使用對象資源管理器和SQL命令創建數據庫與修改數據庫的方法。2&#xff0e;掌握在SQL Server中使用對象資源管理器或者SQL命令創建數據表和修改數據表的方法&#xff08;以SQL命令為重點&#xff09;。3&#xff0e;掌握無條件查詢…

【STM32】ADC模數轉換基本原理(提供完整實例代碼)

這篇文章是嵌入式中我通過大量資料 整合成了一份 系統完整、層次清晰的 ADC 模數轉換原理解析 文檔。 這里系統地梳理了 STM32F1 系列 ADC 模數轉換的核心資料&#xff0c;包括&#xff1a; 1.原理 特性 2.通道配置 3.模式選擇&#xff08;單次/連續/掃描&#xff09; 4.關鍵寄…

圖神經網絡 gnn 應用到道路網絡拓撲結構與交通碳排放相關性。,拓撲指標量化、時空關聯模型及演化機制分析

針對您提出的“道路網絡拓撲結構與交通碳排放相關框架&#xff0c;以下結合研究目標、數據與方法進行系統性深化設計&#xff0c;重點強化拓撲指標量化、時空關聯模型及演化機制分析&#xff1a;一、核心研究問題深化 靜態關聯&#xff1a;不同拓撲結構&#xff08;方格網/環射…

7.6 優先隊列| dijkstra | hash | rust

lc1337pair存入&#xff0c;lambda sort后取出&#xff0c;最開始想用hash&#xff0c;寫一半感覺寫復雜了class Solution {public:vector<int> kWeakestRows(vector<vector<int>>& mat, int k) {int m mat.size();int n mat[0].size();vector<pair…

最新 HarmonyOS API 20 知識庫 重磅推出

最新 HarmonyOS API 20 知識庫 重磅推出 前言 最近整理下 華為開發者聯盟最新的 API 20的鴻蒙應用開發文檔&#xff0c;這次的API 20 相比較之前的文檔&#xff0c;要多了不少內容&#xff0c;目前整理后是9000千多篇&#xff0c;不容易呀。 如何使用 基于騰訊的知識庫工具 …

uniapp 監聽物理返回按鈕

import {onShow,onHide,onLoad,onReady,onBackPress} from "dcloudio/uni-app"onBackPress((e) > {showLog("返回按鈕觸發")if(e.frombackbutton){//開始干活}})參數說明屬性類型說明fromString觸發返回行為的來源&#xff1a;backbutton——左上角導航…

多線程(2)

多線程&#xff08;2&#xff09; &#x1f534;&#x1f7e0;&#x1f7e1;&#x1f7e2;&#x1f535;&#x1f7e3;&#x1f534;&#x1f534;&#x1f7e0;&#x1f7e1;&#x1f7e2;&#x1f535;&#x1f7e3;&#x1f534;&#x1f534;&#x1f7e0;&#x1f7e1;&am…