國產加密算法-java實現SM3


國產加密算法-java實現SM3

一、國產加密算法介紹

國家商用密碼管理辦公室制定了一系列密碼標准,包括SM1(SCB2)、SM2、SM3、SM4、SM7、SM9、祖沖之密碼算法(ZUC)那等等。

其中SM1、SM4、SM7、祖沖之密碼(ZUC)是對稱算法;SM2、SM9是非對稱算法;SM3是哈希算法。目前,這些算法已廣泛應用於各個領域中,期待有一天會有采用國密算法的區塊鏈應用出現。

image-20220107233232842

其中SM1、SM7算法不公開,調用該算法時,需要通過加密芯片的接口進行調用;比較少人了解這些算法,在這里對這些國密算法做簡單的科普

1. SM1對稱密碼

SM1 算法是分組密碼算法,分組長度為128位,密鑰長度都為 128 比特,算法安全保密強度及相關軟硬件實現性能與 AES 相當,算法不公開,僅以IP核的形式存在於芯片中。

采用該算法已經研制了系列芯片、智能IC卡、智能密碼鑰匙、加密卡、加密機等安全產品,廣泛應用於電子政務、電子商務及國民經濟的各個應用領域(包括國家政務通、警務通等重要領域)。

2. SM2橢圓曲線公鑰密碼算法(vs ECDSA、ECDH)

SM2算法就是ECC橢圓曲線密碼機制,但在簽名、密鑰交換方面不同於ECDSA、ECDH等國際標准,而是采取了更為安全的機制。另外,SM2推薦了一條256位的曲線作為標准曲線。
SM2標准包括總則,數字簽名算法,密鑰交換協議,公鑰加密算法四個部分,並在每個部分的附錄詳細說明了實現的相關細節及示例。

SM2算法主要考慮素域Fp和F2m上的橢圓曲線,分別介紹了這兩類域的表示,運算,以及域上的橢圓曲線的點的表示,運算和多倍點計算算法。然后介紹了編程語言中的數據轉換,包括整數和字節串,字節串和比特串,域元素和比特串,域元素和整數,點和字節串之間的數據轉換規則。

詳細說明了有限域上橢圓曲線的參數生成以及驗證,橢圓曲線的參數包括有限域的選取,橢圓曲線方程參數,橢圓曲線群基點的選取等,並給出了選取的標准以便於驗證。最后給橢圓曲線上密鑰對的生成以及公鑰的驗證,用戶的密鑰對為(s,sP),其中s為用戶的私鑰,sP為用戶的公鑰,由於離散對數問題從sP難以得到s,並針對素域和二元擴域給出了密鑰對生成細節和驗證方式。總則中的知識也適用於SM9算法。

在總則的基礎上給出了數字簽名算法(包括數字簽名生成算法和驗證算法),密鑰交換協議以及公鑰加密算法(包括加密算法和解密算法),並在每個部分給出了算法描述,算法流程和相關示例。
數字簽名算法,密鑰交換協議以及公鑰加密算法都使用了國家密管理局批准的SM3密碼雜湊算法和隨機數發生器。數字簽名算法,密鑰交換協議以及公鑰加密算法根據總則來選取有限域和橢圓曲線,並生成密鑰對。
SM2算法在很多方面都優於RSA算法(RSA發展得早應用普遍,SM2領先也很自然),與RSA安全性對比如下圖

image-20220107233312625

3. SM3雜湊算法(vs SHA-256)

SM3密碼雜湊(哈希、散列)算法給出了雜湊函數算法的計算方法和計算步驟,並給出了運算示例。此算法適用於商用密碼應用中的數字簽名和驗證,消息認證碼的生成與驗證以及隨機數的生成,可滿足多種密碼應用的安全需求。在SM2,SM9標准中使用。

此算法對輸入長度小於2的64次方的比特消息,經過填充和迭代壓縮,生成長度為256比特的雜湊值,其中使用了異或,模,模加,移位,與,或,非運算,由填充,迭代過程,消息擴展和壓縮函數所構成。具體算法及運算示例見SM3標准。

2005年,Wang等人給出了MD5算法和SHA-1算法的碰撞攻擊方法,現今被廣泛應用的MD5算法和SHA-1算法不再是安全的算法。

SM3密碼摘要算法是中國國家密碼管理局2010年公布的中國商用密碼雜湊算法標准。SM3算法適用於商用密碼應用中的數字簽名和驗證,是在SHA-256基礎上改進實現的一種算法。SM3算法采用Merkle-Damgard結構,消息分組長度為512位,摘要值長度為256位。

SM3算法的壓縮函數與SHA-256的壓縮函數具有相似的結構,但是SM3算法的設計更加復雜,比如壓縮函數的每一輪都使用2個消息字。

現今為止,SM3算法的安全性相對較高。

SM3主要用於數字簽名及驗證、消息認證碼生成及驗證、隨機數生成等,其算法公開。據國家密碼管理局表示,其安全性及效率與SHA-256相當。

4. SM4對稱算法(vs DES)

此算法是一個分組算法,用於無線局域網產品。該算法的分組長度為128比特,密鑰長度為128比特。加密算法與密鑰擴展算法都采用32輪非線性迭代結構。解密算法與加密算法的結構相同,只是輪密鑰的使用順序相反,解密輪密鑰是加密輪密鑰的逆序。

此算法采用非線性迭代結構,每次迭代由一個輪函數給出,其中輪函數由一個非線性變換和線性變換復合而成,非線性變換由S盒所給出。其中rki為輪密鑰,合成置換T組成輪函數。輪密鑰的產生與上圖流程類似,由加密密鑰作為輸入生成,輪函數中的線性變換不同,還有些參數的區別。SM4算法的具體描述和示例見SM4標准。

image-20220107233422981

國際的DES算法和國產的SM4算法的目的都是為了加密保護靜態儲存和傳輸信道中的數據,主要特性如下:

5. SM7對稱密碼

SM7算法,是一種分組密碼算法,分組長度為128比特,密鑰長度為128比特。SM7適用於非接觸式IC卡,應用包括身份識別類應用(門禁卡、工作證、參賽證),票務類應用(大型賽事門票、展會門票),支付與通卡類應用(積分消費卡、校園一卡通、企業一卡通等)。

6. SM9標識密碼算法

為了降低公開密鑰系統中密鑰和證書管理的復雜性,以色列科學家、RSA算法發明人之一Adi Shamir在1984年提出了標識密碼(Identity-Based Cryptography)的理念。標識密碼將用戶的標識(如郵件地址、手機號碼、QQ號碼等)作為公鑰,省略了交換數字證書和公鑰過程,使得安全系統變得易於部署和管理,非常適合端對端離線安全通訊、雲端數據加密、基於屬性加密、基於策略加密的各種場合。2008年標識密碼算法正式獲得國家密碼管理局頒發的商密算法型號:SM9(商密九號算法),為我國標識密碼技術的應用奠定了堅實的基礎。

SM9算法不需要申請數字證書,適用於互聯網應用的各種新興應用的安全保障。如基於雲技術的密碼服務、電子郵件安全、智能終端保護、物聯網安全、雲存儲安全等等。這些安全應用可采用手機號碼或郵件地址作為公鑰,實現數據加密、身份認證、通話加密、通道加密等安全應用,並具有使用方便,易於部署的特點,從而開啟了普及密碼算法的大門。

7. ZUC祖沖之算法

祖沖之序列密碼算法是中國自主研究的流密碼算法,是運用於移動通信4G網絡中的國際標准密碼算法,該算法包括祖沖之算法(ZUC)、加密算法(128-EEA3)和完整性算法(128-EIA3)三個部分。目前已有對ZUC算法的優化實現,有專門針對128-EEA3和128-EIA3的硬件實現與優化。

密碼算法作為國家戰略資源,比歷史上任何時候都顯得更為關鍵。在大數據和雲計算的時代,關鍵信息往往通過數據挖掘技術在海量數據中獲得,所以每一個人的信息保護都非常重要。

8. 密碼散列函數

密碼散列函數(英語:Cryptographic hash function),又譯為加密散列函數密碼散列函數加密散列函數,是散列函數的一種。它被認為是一種單向函數,也就是說極其難以由散列函數輸出的結果,回推輸入的數據是什么。這樣的單向函數被稱為“現代密碼學的馱馬”。這種散列函數的輸入數據,通常被稱為消息(message),而它的輸出結果,經常被稱為消息摘要(message digest)或摘要(digest)。

信息安全中,有許多重要的應用,都使用了密碼散列函數來實現,例如數字簽名消息認證碼

二. SM3

2.1 java 實現

SM3摘要算法對應的是目前比較流行的hash算法MD5,結果為32位字節,可轉化成64位16進制字符.

參照網上帖子匯總

import cn.hutool.crypto.SmUtil;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

import java.io.UnsupportedEncodingException;
import java.security.Security;
import java.util.Arrays;


public class Sm3Utils {
    private static final String ENCODING = "UTF-8";
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * sm3算法加密
     * @explain
     * @param paramStr
     *            待加密字符串
     * @return 返回加密后,固定長度=32的16進制字符串
     */
    public static String encrypt(String paramStr){
        // 將返回的hash值轉換成16進制字符串
        String resultHexString = "";
        try {
            // 將字符串轉換成byte數組
            byte[] srcData = paramStr.getBytes(ENCODING);
            // 調用hash()
            byte[] resultHash = hash(srcData);
            // 將返回的hash值轉換成16進制字符串
            resultHexString = ByteUtils.toHexString(resultHash);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return resultHexString;
    }

    /**
     * 返回長度=32的byte數組
     * @explain 生成對應的hash值
     * @param srcData
     * @return
     */
    public static byte[] hash(byte[] srcData) {
        SM3Digest digest = new SM3Digest();
        //update the message digest with a single byte.
        digest.update(srcData, 0, srcData.length);
        byte[] hash = new byte[digest.getDigestSize()];
        //close the digest, producing the final digest value.
        digest.doFinal(hash, 0);
        return hash;
    }
    /**
     * sm3算法加密
     * @explain
     * @param paramStr
     *            待加密字符串
     * @param key
     *            密鑰
     * @return 返回加密后,固定長度=32的16進制字符串
     */
    public static String encryptPlus(String paramStr,String key){
        // 將返回的hash值轉換成16進制字符串
        String resultHexString = "";
        try {
            // 將字符串轉換成byte數組
            byte[] srcData = paramStr.getBytes(ENCODING);
            // 調用hash()
            byte[] resultHash = hmac(srcData,key.getBytes(ENCODING));
            // 將返回的hash值轉換成16進制字符串
            resultHexString = ByteUtils.toHexString(resultHash);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return resultHexString;
    }

    /**
     * 通過密鑰進行加密
     * @explain 指定密鑰進行加密
     * @param key
     *            密鑰
     * @param srcData
     *            被加密的byte數組
     * @return
     */
    public static byte[] hmac(byte[] key, byte[] srcData) {
        KeyParameter keyParameter = new KeyParameter(key);
        SM3Digest digest = new SM3Digest();
        HMac mac = new HMac(digest);
        mac.init(keyParameter);
        mac.update(srcData, 0, srcData.length);
        byte[] result = new byte[mac.getMacSize()];
        mac.doFinal(result, 0);
        return result;
    }

    /**
     * 判斷源數據與加密數據是否一致
     * @explain 通過驗證原數組和生成的hash數組是否為同一數組,驗證2者是否為同一數據
     * @param srcStr
     *            原字符串
     * @param sm3HexString
     *            16進制字符串
     * @return 校驗結果
     */
    public static boolean verify(String srcStr, String sm3HexString) {
        boolean flag = false;
        try {
            //使用指定的字符集將字符串編碼為 byte 序列,並將結果存儲到一個新的 byte 數組中
            byte[] srcData = srcStr.getBytes(ENCODING);
            //16進制 --> byte[]
            byte[] sm3Hash = ByteUtils.fromHexString(sm3HexString);
            byte[] newHash = hash(srcData);
            //判斷數組是否相等
            if (Arrays.equals(newHash, sm3Hash)) {
                flag = true;
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return flag;
    }
/***********************使用Hutool工具類*****************************************************************************************/
    /**
     * sm3算法加密
     *
     * @param paramStr 待加密字符串
     * @return 返回加密后,固定長度=32的16進制字符串
     * @explain
     */
    public static String encryptSm3ByHutool(String paramStr) {
        return SmUtil.sm3(paramStr);
    }
    /**
     * 判斷源數據與加密數據是否一致(Hutool)
     *
     * @param srcStr       原字符串
     * @param sm3HexString 16進制字符串
     * @return 校驗結果
     */
    public static boolean verifySm3ByHutool(String srcStr, String sm3HexString) {
        boolean flag = false;
        if (sm3HexString.equals(encryptSm3ByHutool(srcStr))) {
            flag = true;
        }
        return flag;
    }
/***********************使用Hutool工具類*****************************************************************************************/
}

三、參考文檔

官方文檔:

  1. 密碼行業標准化技術委員會

  2. 國家密碼管理局

  3. SM3Digest類的API;

感覺寫的好的博文:

  1. 【人人都懂密碼學】一篇最易懂的Java密碼學入門教程

  2. B站-尚硅谷-網絡安全之密碼學

  3. https://zhuanlan.zhihu.com/p/272212452

  4. https://blog.csdn.net/cg129054036/article/details/83032978

  5. https://jueee.github.io/2021/01/2021-01-21-Java實現SM3加密算法/

  6. https://www.jianshu.com/p/8c3657a1769f;

圖片來源網上,如有侵權請聯系我刪除


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM