国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

國(guó)密SM2/SM3算法

這篇具有很好參考價(jià)值的文章主要介紹了國(guó)密SM2/SM3算法。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

國(guó)密算法

國(guó)密算法

分類

1、SM1是一種分組加密算法
對(duì)稱加密算法中的分組加密算法,其分組長(zhǎng)度、秘鑰長(zhǎng)度都是128bit,算法安全保密強(qiáng)度跟 AES 相當(dāng),但是算法不公開(kāi),僅以IP核的形式存在于芯片中,需要通過(guò)加密芯片的接口進(jìn)行調(diào)用。

采用該算法已經(jīng)研制了系列芯片、智能IC卡、智能密碼鑰匙、加密卡、加密機(jī)等安全產(chǎn)品,廣泛應(yīng)用于電子政務(wù)、電子商務(wù)及國(guó)民經(jīng)濟(jì)的各個(gè)應(yīng)用領(lǐng)域(包括國(guó)家政務(wù)通、警務(wù)通等重要領(lǐng)域)。

2、SM2是非對(duì)稱加密算法
它是基于橢圓曲線密碼的公鑰密碼算法標(biāo)準(zhǔn),其秘鑰長(zhǎng)度256bit,包含數(shù)字簽名、密鑰交換和公鑰加密,用于替換RSA/DH/ECDSA/ECDH等國(guó)際算法??梢詽M足電子認(rèn)證服務(wù)系統(tǒng)等應(yīng)用需求,由國(guó)家密碼管理局于2010年12月17號(hào)發(fā)布。

SM2采用的是ECC 256位的一種,其安全強(qiáng)度比RSA 2048位高,且運(yùn)算速度快于RSA。

3、SM3是一種密碼雜湊算法
用于替代MD5/SHA-1/SHA-2等國(guó)際算法,適用于數(shù)字簽名和驗(yàn)證、消息認(rèn)證碼的生成與驗(yàn)證以及隨機(jī)數(shù)的生成,可以滿足電子認(rèn)證服務(wù)系統(tǒng)等應(yīng)用需求,于2010年12月17日發(fā)布。

它是在SHA-256基礎(chǔ)上改進(jìn)實(shí)現(xiàn)的一種算法,采用Merkle-Damgard結(jié)構(gòu),消息分組長(zhǎng)度為512bit,輸出的摘要值長(zhǎng)度為256bit。

4、SM4是分組加密算法
跟SM1類似,是我國(guó)自主設(shè)計(jì)的分組對(duì)稱密碼算法,用于替代DES/AES等國(guó)際算法。SM4算法與AES算法具有相同的密鑰長(zhǎng)度、分組長(zhǎng)度,都是128bit。于2012年3月21日發(fā)布,適用于密碼應(yīng)用中使用分組密碼的需求。

5、SM7是一種分組加密算法
該算法沒(méi)有公開(kāi)。SM7適用于非接IC卡應(yīng)用包括身份識(shí)別類應(yīng)用(門禁卡、工作證、參賽證),票務(wù)類應(yīng)用(大型賽事門票、展會(huì)門票),支付與通卡類應(yīng)用(積分消費(fèi)卡、校園一卡通、企業(yè)一卡通、公交一卡通)。

6、SM9是基于標(biāo)識(shí)的非對(duì)稱密碼算法
用橢圓曲線對(duì)實(shí)現(xiàn)的基于標(biāo)識(shí)的數(shù)字簽名算法、密鑰交換協(xié)議、密鑰封裝機(jī)制和公鑰加密與解密算法,包括數(shù)字簽名生成算法和驗(yàn)證算法,并給出了數(shù)字簽名與驗(yàn)證算法及其相應(yīng)的流程。并提供了相應(yīng)的流程??梢蕴娲跀?shù)字證書的PKI/CA體系。

SM9主要用于用戶的身份認(rèn)證。據(jù)新華網(wǎng)公開(kāi)報(bào)道,SM9的加密強(qiáng)度等同于3072位密鑰的RSA加密算法,于2016年3月28日發(fā)布。

算法下載地址:http://www.scctc.org.cn/templates/Download/index.aspx?nodeid=71

規(guī)范

國(guó)標(biāo)文檔中定義國(guó)密算法使用256位橢圓曲線;
原文摘抄:

SM2"使用素?cái)?shù)域256位橢圓曲線“
SM2標(biāo)準(zhǔn)中規(guī)定采用256比特的橢圓曲線域參數(shù),并采用256比特的密碼雜湊算法,并規(guī)定某些步驟中須采用SM3。

SM2密文由C1、C2、C3三部分構(gòu)成,如何對(duì)SM2密文進(jìn)行編碼在已經(jīng)公布的兩個(gè)標(biāo)準(zhǔn)中有所不同,在早期公布的《SM2橢圓曲線公鑰密碼算法 第4部分:公鑰加密算法》中,SM2密文中的三部分依次輸出,沒(méi)有采用如Tag-Length-Value形式的編碼,我們稱其為Plain編碼。在之后公布的GM/T國(guó)標(biāo)中,SM2密文采用ASN.1/DER方式編碼。

SM3是國(guó)密密碼雜湊算法標(biāo)準(zhǔn),由國(guó)家密碼管理局于2010年12月公布。SM3的輸出雜湊值長(zhǎng)度為256比特(32字節(jié)),與國(guó)際標(biāo)準(zhǔn)SHA-256等長(zhǎng)。SM3設(shè)計(jì)安全性為128比特,安全性與256比特橢圓曲線/SM2、SM4/SMS4、AES-128等同。

工具包BouncyCastle

Java標(biāo)準(zhǔn)庫(kù)提供了一系列常用的哈希算法。但如果我們要用的某種算法,Java標(biāo)準(zhǔn)庫(kù)沒(méi)有提供怎么辦,BouncyCastle就是一個(gè)提供了很多哈希算法和加密算法的第三方庫(kù)。它提供了Java標(biāo)準(zhǔn)庫(kù)沒(méi)有的一些算法。

安裝

方式一

動(dòng)態(tài)安裝
引入包,

   <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15to18</artifactId>
            <version>1.71</version>
        </dependency>

最新的包及jdk支持 可以戳 這里
使用時(shí)需要通過(guò)Security.addProvider(new BouncyCastleProvider())動(dòng)態(tài)加載到j(luò)vm

  @Test
    public void case5() throws Exception {
        // 注冊(cè)BouncyCastle:
        String key="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB";
        System.out.println(key.length());
        Security.addProvider(new BouncyCastleProvider());
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes("UTF-8"), "AES"));
        byte[] resultByte = cipher.doFinal("zw".getBytes("UTF-8"));
        System.out.println(Hex.toHexString(resultByte));
    }
方式二

靜態(tài)安裝
(1)去BouncyCastle官網(wǎng)下載provider的包,然后放入$JAVA_HOME\jre\lib\ext目錄下;
(2)修改配置文件
java8: %java_home%\jre\lib\security\java.security
java9+: %JAVA_HOME%\conf\security.
加入一行配置:
security.provider.按順序填數(shù)字=org.bouncycastle.jce.provider.BouncyCastleProvider

  @Test
    public void case5() throws Exception {
        String key="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB";
        System.out.println(key.length());
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes("UTF-8"), "AES"));
        byte[] resultByte = cipher.doFinal("zw".getBytes("UTF-8"));
     System.out.println(Hex.toHexString(resultByte));
    }

java代碼實(shí)現(xiàn)

SM2工具類

SM2KeyInfo.java

package com.tom.crypto;

/**
 * @ClassName SM2KeyInfo
 * @Description  生成密鑰info
 * @Author tom
 */
public class SM2KeyInfo {
    /**
     *
     *  BC庫(kù)使用的公鑰=64個(gè)字節(jié)+1個(gè)字節(jié)(04標(biāo)志位),BC庫(kù)使用的私鑰=32個(gè)字節(jié)
     *  SM2秘鑰的組成部分有 私鑰D 、公鑰X 、 公鑰Y , 他們都可以用長(zhǎng)度為64的16進(jìn)制的HEX串表示,
     *  SM2公鑰并不是直接由X+Y表示 , 而是額外添加了一個(gè)頭,當(dāng)啟用壓縮時(shí):公鑰=有頭+公鑰X ,即省略了公鑰Y的部分
     */
    private String publicKeyHex;
    private String privateKeyHex;
    private String pubX;
    private String pubY;

    public SM2KeyInfo() {
    }

    public String getPublicKeyHex() {
        return publicKeyHex;
    }

    public void setPublicKeyHex(String publicKeyHex) {
        this.publicKeyHex = publicKeyHex;
    }

    public String getPrivateKeyHex() {
        return privateKeyHex;
    }

    public void setPrivateKeyHex(String privateKeyHex) {
        this.privateKeyHex = privateKeyHex;
    }

    public String getPubX() {
        return pubX;
    }

    public void setPubX(String pubX) {
        this.pubX = pubX;
    }

    public String getPubY() {
        return pubY;
    }

    public void setPubY(String pubY) {
        this.pubY = pubY;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("SM2KeyInfo{");
        sb.append("publicKeyHex='").append(publicKeyHex).append('\'');
        sb.append(", privateKeyHex='").append(privateKeyHex).append('\'');
        sb.append(", pubX='").append(pubX).append('\'');
        sb.append(", pubY='").append(pubY).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

SM2Util.java

package com.tom.crypto;

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jcajce.spec.SM2ParameterSpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.ECGenParameterSpec;

/**
 * Sm2算法工具類
 * 支持公鑰加密、私鑰解密 ,私鑰加簽 公鑰解簽
 * 收集網(wǎng)上資料整理:
 * 參考bouncycastle demo
 */
public class SM2Utils {
    //橢圓曲線ECParameters ASN.1 結(jié)構(gòu),sm2P256V1代表國(guó)密SM2推薦參數(shù)定義的橢圓曲線
    private static X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
    //橢圓曲線公鑰或私鑰的基本域參數(shù)。
    private static ECParameterSpec ecDomainParameters = new ECParameterSpec(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
    //構(gòu)造domain參數(shù)
    private static ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());

    /**
     * 生成密鑰對(duì)
     *
     * @return
     */
    public static KeyPair generateECKeyPair() {
        //使用標(biāo)準(zhǔn)名稱創(chuàng)建EC參數(shù)生成的參數(shù)規(guī)范
        final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
        // 獲取一個(gè)橢圓曲線類型的密鑰對(duì)生成器
        final KeyPairGenerator kpg;
        try {
            kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
            // 使用SM2算法域參數(shù)集初始化密鑰生成器(默認(rèn)使用以最高優(yōu)先級(jí)安裝的提供者的 SecureRandom 的實(shí)現(xiàn)作為隨機(jī)源)
            // 使用SM2的算法域參數(shù)集和指定的隨機(jī)源初始化密鑰生成器
            kpg.initialize(sm2Spec, new SecureRandom());
            // 通過(guò)密鑰生成器生成密鑰對(duì)
            KeyPair keyPair = kpg.generateKeyPair();

            return keyPair;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 生成密鑰相關(guān)信息
     *
     * @return
     */
    public static SM2KeyInfo generateSM2Key() {
        SM2KeyInfo sm2KeyInfo = new SM2KeyInfo();
        KeyPair keyPair = generateECKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        if (publicKey instanceof BCECPublicKey) {
            //獲取65字節(jié)非壓縮縮的十六進(jìn)制公鑰串(0x04)
            BCECPublicKey bcecPublicKey = (BCECPublicKey) publicKey;
            ECPoint ecPoint = bcecPublicKey.getQ();
            String publicKeyHex = Hex.toHexString(ecPoint.getEncoded(false));
            String pubX = ecPoint.getXCoord().toBigInteger().toString(16);
            String pubY = ecPoint.getYCoord().toBigInteger().toString(16);
            sm2KeyInfo.setPubX(pubX);
            sm2KeyInfo.setPubY(pubY);
            sm2KeyInfo.setPublicKeyHex(publicKeyHex);
        }
        PrivateKey privateKey = keyPair.getPrivate();
        if (privateKey instanceof BCECPrivateKey) {
            //獲取32字節(jié)十六進(jìn)制私鑰串
            String privateKeyHex = ((BCECPrivateKey) privateKey).getD().toString(16);
            sm2KeyInfo.setPrivateKeyHex(privateKeyHex);
        }
        return sm2KeyInfo;

    }


    /**
     * @param publicKeyHex SM2十六進(jìn)制公鑰
     * @param data         明文數(shù)據(jù)
     * @return
     * @Description 公鑰加密
     */
    public static String encrypt(String publicKeyHex, String data) throws UnsupportedEncodingException, InvalidCipherTextException {
        //提取公鑰點(diǎn)
        ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(publicKeyHex));
        // 公鑰前面的02或者03表示是壓縮公鑰,04表示未壓縮公鑰, 04的時(shí)候,可以去掉前面的04
        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);
        SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        // 設(shè)置sm2為加密模式
        sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
        byte[] in = data.getBytes("utf-8");
        byte[] arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);
        return Hex.toHexString(arrayOfBytes);


    }

    /**
     * 加密 返回16進(jìn)制字符串
     *
     * @param pubX
     * @param pubY
     * @param data 明文
     * @return
     */
    public static String encrypt(String pubX, String pubY, String data) throws UnsupportedEncodingException, InvalidCipherTextException {
        BigInteger x = new BigInteger(pubX, 16);
        BigInteger y = new BigInteger(pubY, 16);
        //提取公鑰點(diǎn)
        ECPoint pukPoint = sm2ECParameters.getCurve().createPoint(x, y);
        // 公鑰前面的02或者03表示是壓縮公鑰,04表示未壓縮公鑰, 04的時(shí)候,可以去掉前面的04
        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);
        SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        // 設(shè)置sm2為加密模式
        sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
        byte[] in = data.getBytes("utf-8");
        byte[] arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);
        return Hex.toHexString(arrayOfBytes);
    }

    /**
     * 公鑰加密  加密模式是SM2Engine.Mode.C1C3C2
     *
     * @param publicKey SM2公鑰
     * @param data      明文數(shù)據(jù)
     * @return String
     * @Description 公鑰加密
     * @Author msx
     */
    public static String encrypt(BCECPublicKey publicKey, String data) throws UnsupportedEncodingException, InvalidCipherTextException {

        //通過(guò)公鑰對(duì)象獲取公鑰的基本域參數(shù)。
        ECParameterSpec ecParameterSpec = publicKey.getParameters();
        // 構(gòu)造ECC算法參數(shù),曲線方程、橢圓曲線G點(diǎn)、大整數(shù)N
        ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
                ecParameterSpec.getG(), ecParameterSpec.getN());
        //通過(guò)公鑰值和公鑰基本參數(shù)創(chuàng)建公鑰參數(shù)對(duì)象
        ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(publicKey.getQ(), ecDomainParameters);
        //根據(jù)加密模式實(shí)例化SM2公鑰加密引擎
        SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        //初始化加密引擎
        sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));
        //將明文字符串轉(zhuǎn)換為指定編碼的字節(jié)串
        byte[] in = data.getBytes("utf-8");
        //通過(guò)加密引擎對(duì)字節(jié)數(shù)串行加密
        byte[] arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);
        //將加密后的字節(jié)串轉(zhuǎn)換為十六進(jìn)制字符串
        return Hex.toHexString(arrayOfBytes);
    }


    /**
     * @param privateKey SM私鑰
     * @param cipherData 密文數(shù)據(jù)
     * @return
     * @Description 私鑰解密
     * @Author msx
     */
    public static String decrypt(BCECPrivateKey privateKey, String cipherData) throws UnsupportedEncodingException, InvalidCipherTextException {
        // 使用BC庫(kù)加解密時(shí)密文以04開(kāi)頭,傳入的密文前面沒(méi)有04則補(bǔ)上
        if (!cipherData.startsWith("04")) {
            cipherData = "04" + cipherData;
        }
        //將十六進(jìn)制字符串密文轉(zhuǎn)換為字節(jié)數(shù)組(需要與加密一致,加密是:加密后的字節(jié)數(shù)組轉(zhuǎn)換為了十六進(jìn)制字符串)
        byte[] cipherDataByte = Hex.decode(cipherData);
        //通過(guò)私鑰對(duì)象獲取私鑰的基本域參數(shù)。
        ECParameterSpec ecParameterSpec = privateKey.getParameters();
        ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
                ecParameterSpec.getG(), ecParameterSpec.getN());
        //通過(guò)私鑰值和私鑰鑰基本參數(shù)創(chuàng)建私鑰參數(shù)對(duì)象
        ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(privateKey.getD(),
                ecDomainParameters);
        //通過(guò)解密模式創(chuàng)建解密引擎并初始化
        SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        sm2Engine.init(false, ecPrivateKeyParameters);
        //通過(guò)解密引擎對(duì)密文字節(jié)串進(jìn)行解密
        byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
        //將解密后的字節(jié)串轉(zhuǎn)換為utf8字符編碼的字符串(需要與明文加密時(shí)字符串轉(zhuǎn)換成字節(jié)串所指定的字符編碼保持一致)
        return new String(arrayOfBytes, "utf-8");

    }


    /**
     * @param privateKeyHex SM2十六進(jìn)制私鑰
     * @param cipherData    密文數(shù)據(jù)
     * @return String
     * @Description 私鑰解密
     * @Author msx
     */
    public static String decrypt(String privateKeyHex, String cipherData) throws UnsupportedEncodingException, InvalidCipherTextException {
        // 使用BC庫(kù)加解密時(shí)密文以04開(kāi)頭,傳入的密文前面沒(méi)有04則補(bǔ)上
        if (!cipherData.startsWith("04")) {
            cipherData = "04" + cipherData;
        }
        //將十六進(jìn)制字符串密文轉(zhuǎn)換為字節(jié)數(shù)組(需要與加密一致,加密是:加密后的字節(jié)數(shù)組轉(zhuǎn)換為了十六進(jìn)制字符串)
        byte[] cipherDataByte = Hex.decode(cipherData);

        BigInteger privateKeyD = new BigInteger(privateKeyHex, 16);
        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters);
        SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        // 設(shè)置sm2為解密模式
        sm2Engine.init(false, privateKeyParameters);
        byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
        return new String(arrayOfBytes);


    }

    /**
     * @param pubKeyHex 64字節(jié)十六進(jìn)制公鑰字符串(如果公鑰字符串為65字節(jié)首個(gè)字節(jié)為0x04:表示該公鑰為非壓縮格式,操作時(shí)需要?jiǎng)h除)
     * @return BCECPublicKey SM2公鑰對(duì)象
     * @Description 公鑰字符串轉(zhuǎn)換為 BCECPublicKey 公鑰對(duì)象
     * @Author msx
     */
    public static BCECPublicKey getECPublicKeyByPublicKeyHex(String pubKeyHex) {
        //截取64字節(jié)有效的SM2公鑰(如果公鑰首個(gè)字節(jié)為0x04)
        if (pubKeyHex.length() > 128) {
            pubKeyHex = pubKeyHex.substring(pubKeyHex.length() - 128);
        }
        //將公鑰拆分為x,y分量(各32字節(jié))
        String pubX = pubKeyHex.substring(0, 64);
        String pubY = pubKeyHex.substring(pubX.length());
        //將公鑰x、y分量轉(zhuǎn)換為BigInteger類型
        BigInteger x = new BigInteger(pubX, 16);
        BigInteger y = new BigInteger(pubY, 16);
        //通過(guò)公鑰x、y分量創(chuàng)建橢圓曲線公鑰規(guī)范
        ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(sm2ECParameters.getCurve().createPoint(x, y), ecDomainParameters);
        //通過(guò)橢圓曲線公鑰規(guī)范,創(chuàng)建出橢圓曲線公鑰對(duì)象(可用于SM2加密及驗(yàn)簽)
        return new BCECPublicKey("EC", ecPublicKeySpec, BouncyCastleProvider.CONFIGURATION);
    }

    /**
     * @param privateKeyHex 32字節(jié)十六進(jìn)制私鑰字符串
     * @return BCECPrivateKey SM2私鑰對(duì)象
     * @Description 私鑰字符串轉(zhuǎn)換為 BCECPrivateKey 私鑰對(duì)象
     * @Author msx
     */
    public static BCECPrivateKey getBCECPrivateKeyByPrivateKeyHex(String privateKeyHex) {
        //將十六進(jìn)制私鑰字符串轉(zhuǎn)換為BigInteger對(duì)象
        BigInteger d = new BigInteger(privateKeyHex, 16);
        //通過(guò)私鑰和私鑰域參數(shù)集創(chuàng)建橢圓曲線私鑰規(guī)范
        ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecDomainParameters);
        //通過(guò)橢圓曲線私鑰規(guī)范,創(chuàng)建出橢圓曲線私鑰對(duì)象(可用于SM2解密和簽名)
        return new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);
    }

    /**
     * Generate an encoded SM2 signature based on the SM3 digest using the
     * passed in EC private key and input data.
     *
     * @param ecPrivate the private key for generating the signature with.
     * @param input     the input to be signed.
     * @return the encoded signature.
     */
    public static byte[] generateSM2Signature(
            PrivateKey ecPrivate, byte[] input)
            throws GeneralSecurityException {
        Signature signature = Signature.getInstance("SM3withSM2", "BC");
        signature.initSign(ecPrivate);
        signature.update(input);
        return signature.sign();
    }

    /**
     * Return true if the passed in SM3withSM2 signature verifies against
     * the passed in EC public key and input.
     *
     * @param ecPublic     the public key of the signature creator.
     * @param input        the input that was supposed to have been signed.
     * @param encSignature the encoded signature.
     * @return true if the signature verifies, false otherwise.
     */
    public static boolean verifySM2Signature(
            PublicKey ecPublic, byte[] input, byte[] encSignature)
            throws GeneralSecurityException {
        Signature signature = Signature.getInstance("SM3withSM2", "BC");
        signature.initVerify(ecPublic);
        signature.update(input);
        return signature.verify(encSignature);
    }

    /**
     * Generate an encoded SM2 signature based on the SM3 digest using the
     * passed in EC private key and input data.
     *
     * @param ecPrivate the private key for generating the signature with.
     * @param sm2Spec   the SM2 specification carrying the ID of the signer.
     * @param input     the input to be signed.
     * @return the encoded signature.
     */
    public static byte[] generateSM2Signature(
            PrivateKey ecPrivate, SM2ParameterSpec sm2Spec, byte[] input)
            throws GeneralSecurityException {
        Signature signature = Signature.getInstance("SM3withSM2", "BC");
        signature.setParameter(sm2Spec);
        signature.initSign(ecPrivate);
        signature.update(input);
        return signature.sign();
    }

    /**
     * Return true if the passed in SM3withSM2 signature verifies against
     * the passed in EC public key and input.
     *
     * @param ecPublic     the public key of the signature creator.
     * @param sm2Spec      the SM2 specification carrying the expected ID of the signer.
     * @param input        the input that was supposed to have been signed.
     * @param encSignature the encoded signature.
     * @return true if the signature verifies, false otherwise.
     */
    public static boolean verifySM2Signature(
            PublicKey ecPublic, SM2ParameterSpec sm2Spec,
            byte[] input, byte[] encSignature)
            throws GeneralSecurityException {
        Signature signature = Signature.getInstance("SM3withSM2", "BC");
        signature.setParameter(sm2Spec);
        signature.initVerify(ecPublic);
        signature.update(input);
        return signature.verify(encSignature);
    }


}

SM2UtilTest.java

package com.tom.crypto;

import org.bouncycastle.jcajce.spec.SM2ParameterSpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Assert;
import org.junit.Test;

import java.security.Security;

/**
 * @ClassName TestSM2
 * @Description
 * @Author tom
 */
public class SM2UtilTest {
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    @Test
    public void testSm2() throws Exception {
        SM2KeyInfo sm2KeyInfo = SM2Util.generateSM2Key();
        System.out.println(sm2KeyInfo);
        String publicKeyHex = sm2KeyInfo.getPublicKeyHex();
        String privateKeyHex = sm2KeyInfo.getPrivateKeyHex();
        String pubX = sm2KeyInfo.getPubX();
        String pubY = sm2KeyInfo.getPubY();
        /**
         * 公鑰加密
         */
        String plainText = "=========原文數(shù)據(jù)====zw!!!=====";
        String encryptData = SM2Util.encrypt(publicKeyHex, plainText);
        System.out.println("---->encrypt加密結(jié)果:" + encryptData);
        String encryptData2 = SM2Util.encrypt(pubX, pubY, plainText);
        System.out.println("---->encrypt加密結(jié)果:" + encryptData2);
        /**
         * 私鑰解密
         */
        String decryptData = SM2Util.decrypt(privateKeyHex, encryptData);
        Assert.assertEquals(plainText,decryptData);
        System.out.println("---->decrypt解密結(jié)果:" + decryptData);
        String decryptData2 = SM2Util.decrypt(privateKeyHex, encryptData2);
        System.out.println("---->decrypt2解密結(jié)果:" + plainText);
        Assert.assertEquals(plainText,decryptData2);


        byte[] signResult = SM2Util.generateSM2Signature(SM2Util.getBCECPrivateKeyByPrivateKeyHex(privateKeyHex), plainText.getBytes());
        String signResultHex = Hex.toHexString(signResult);
        System.out.println("---->簽名結(jié)果:" + signResultHex);
        boolean verifyResult = SM2Util.verifySM2Signature(SM2Util.getECPublicKeyByPublicKeyHex(publicKeyHex), plainText.getBytes(), Hex.decode(signResultHex));
        System.out.println("---->驗(yàn)簽結(jié)果:" + verifyResult);
        Assert.assertTrue(verifyResult);
        SM2ParameterSpec sm2Spec = new SM2ParameterSpec(
                Strings.toByteArray("zwtom@baidu.com"));

        byte[] sm2Signature = SM2Util.generateSM2Signature(
                SM2Util.getBCECPrivateKeyByPrivateKeyHex(privateKeyHex), sm2Spec,
                Strings.toByteArray(plainText));
        String sm2SignatureHex = Hex.toHexString(sm2Signature);
        System.out.println("---->簽名結(jié)果2:" + sm2SignatureHex);
        boolean verifyReuslt2 = SM2Util.verifySM2Signature(
                SM2Util.getECPublicKeyByPublicKeyHex(publicKeyHex), sm2Spec,
                Strings.toByteArray(plainText), Hex.decode(sm2SignatureHex));
        System.out.println("---->驗(yàn)簽結(jié)果:" + verifyReuslt2);
        Assert.assertTrue(verifyReuslt2);
    }
}

運(yùn)算結(jié)果:

SM2KeyInfo{publicKeyHex='04ae5070d54d6603482d0f5abb888e39f58503f4ac6bf48ce8bcf64ba10f348af801ca7b0c439cf57d884f1a77ff8350006ee5eae5deac2e186ddeb873e4b0d427', privateKeyHex='5648e255a8460aa34663ebc0fb01069a844142fdda8cb663cefe56a2e0a8af00', pubX='ae5070d54d6603482d0f5abb888e39f58503f4ac6bf48ce8bcf64ba10f348af8', pubY='1ca7b0c439cf57d884f1a77ff8350006ee5eae5deac2e186ddeb873e4b0d427'}
---->encrypt加密結(jié)果:04ecadd6f10fdf720c9c86354a9cd5e1cc6b776d42b3c158275f0685baa033c2aab125de6889027093cb6f151bdd1f2fa174f6780a17d3190c8093ad0c13a93bc3debe26fb9f45e7ecd6c207b9a918ab321a1b1939881539dd8782166aa16350671055d3ef5cad464662f0b1545adeea2f3c778b01fd0c81ad3bf7827876154d368c3fbd
---->encrypt加密結(jié)果:04ea902db9a38d92ae21064a56b990ebafc95a9374a7bacbd1e61f5c845532a5c116c30f82198164283b1e6fdaa939e1da7fc334825faeebc3b75c2c0e211fbf56e0cfd57464fc8753ae5c4992459dafe8b9a8395c3e7a4ead0ad8fa5f7fe4609a3b0db09eb4a812424d74d715ed1a5e761710533a280f3baedd5ba1d55e258a63c18c02
---->decrypt解密結(jié)果:=========原文數(shù)據(jù)====zw!!!=====
---->decrypt2解密結(jié)果:=========原文數(shù)據(jù)====zw!!!=====
---->簽名結(jié)果:3045022100dcbc6cdde483ba71f04f56e15409a9d7555bfeb52fefbf4d096bfdf0fc97fda602206a2d14db705fe7c1890dcd5bd7fd3748b5f86f0c9b97037feb65202ab5abda5b
---->驗(yàn)簽結(jié)果:true
---->簽名結(jié)果2:3045022100e791b7df8ee931cc7df4f86df3d9f6a8b08d85824e32657d5f254040c65789ae022024b679695961352435d9975fc7b277f25e220dbaba4a00c8bc83514f2c149d5f
---->驗(yàn)簽結(jié)果:true
SM3工具類

SM3Util.java

package com.tom.crypto;

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;

import java.util.Arrays;

/**
 * SM3算法工具類
 */
public class SM3Util {

    /**
     * 計(jì)算SM3摘要值
     *
     * @param srcData 原文
     * @return 摘要值,對(duì)于SM3算法來(lái)說(shuō)是32字節(jié)
     */
    public static byte[] hash(byte[] srcData) {
        SM3Digest digest = new SM3Digest();
        digest.update(srcData, 0, srcData.length);
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash, 0);
        return hash;
    }

    /**
     * 驗(yàn)證摘要
     *
     * @param srcData 原文
     * @param sm3Hash 摘要值
     * @return 返回true標(biāo)識(shí)驗(yàn)證成功,false標(biāo)識(shí)驗(yàn)證失敗
     */
    public static boolean verify(byte[] srcData, byte[] sm3Hash) {
        byte[] newHash = hash(srcData);
        if (Arrays.equals(newHash, sm3Hash)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 計(jì)算SM3 Mac值
     *
     * @param key     key值,可以是任意長(zhǎng)度的字節(jié)數(shù)組
     * @param srcData 原文
     * @return Mac值,對(duì)于HMac-SM3來(lái)說(shuō)是32字節(jié)
     */
    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;
    }
}

SM3UtilTest 工具類

package com.tom.crypto;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Assert;
import org.junit.Test;

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

public class SM3UtilTest {
    static String plainText = "=========原文數(shù)據(jù)====zw!!!=====";

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    @Test
    public void testHashAndVerify() {
        try {
            byte[] hash = SM3Util.hash(plainText.getBytes("utf-8"));
            System.out.println("SM3 hash result:\n" + Hex.toHexString(hash));
            boolean flag = SM3Util.verify(plainText.getBytes("utf-8"), hash);
            Assert.assertTrue(flag);
        } catch (Exception ex) {
            ex.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void testHmacSM3() {
        try {
            byte[] hmacKey = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
            byte[] hmac = SM3Util.hmac(hmacKey, plainText.getBytes("utf-8"));
            System.out.println("SM3 hash result:\n" + Arrays.toString(hmac));
        } catch (Exception ex) {
            ex.printStackTrace();
            Assert.fail();
        }
    }
}

參考網(wǎng)站

BouncyCastle介紹:
https://www.liaoxuefeng.com/wiki/1252599548343744/1305362418368545
BouncyCastle wiki :
https://github.com/bcgit/bc-java/wiki
BouncyCastle 官網(wǎng)
https://www.bouncycastle.org/latest_releases.html

國(guó)密局標(biāo)準(zhǔn):
https://openstd.samr.gov.cn/bzgk/gb/std_list?p.p1=0&p.p90=circulation_date&p.p91=desc&p.p2=32918
草案:
https://datatracker.ietf.org/doc/html/draft-shen-sm2-ecdsa-02

開(kāi)源密碼箱工具
http://gmssl.org/docs/quickstart.html文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-449943.html

到了這里,關(guān)于國(guó)密SM2/SM3算法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 國(guó)密算法概述、及算法的集成應(yīng)用(sm2、sm3、sm4)

    國(guó)密算法概述、及算法的集成應(yīng)用(sm2、sm3、sm4)

    由于項(xiàng)目的需求,需要集成國(guó)密加解密,于是對(duì)國(guó)密又溫故知新了一遍。同時(shí)整理了一下國(guó)密的一些算法。 本文主要從國(guó)密相關(guān)算法的簡(jiǎn)介、應(yīng)用系統(tǒng)的集成、工具類的封裝等方面入手,對(duì)國(guó)密進(jìn)行深入的學(xué)習(xí)。 為了保障商用密碼的安全性,國(guó)家密碼局制定了一系列密碼標(biāo)

    2024年02月14日
    瀏覽(29)
  • Go實(shí)現(xiàn)國(guó)密算法SM2、SM3、SM4

    SM2橢圓曲線公鑰密碼算法 Public key cryptographic algorithm SM2 based on elliptic curves 遵循的SM2標(biāo)準(zhǔn)號(hào)為: GM/T 0003.1-2012、GM/T 0003.2-2012、GM/T 0003.3-2012、GM/T 0003.4-2012、GM/T 0003.5-2012、GM/T 0009-2012、GM/T 0010-2012 依賴包: github.com/tjfoc/gmsm/sm2 SM3密碼雜湊算法 - SM3 cryptographic hash algorithm 遵循的SM

    2024年02月15日
    瀏覽(23)
  • java 國(guó)密算法工具類(支持SM2 SM3 SM4)

    前言 工具采用BC庫(kù)實(shí)現(xiàn),支持前后端加解密,前端建議使用sm-crypto 引入pom依賴 基本使用如下 國(guó)密SM2算法 國(guó)密SM3算法 國(guó)密SM4算法使用

    2024年02月13日
    瀏覽(25)
  • vue中使用國(guó)密算法SM2、SM3、SM4

    gm-crypto相關(guān)文檔:https://gitcode.net/mirrors/byte-fe/gm-crypto?utm_source=csdn_github_accelerator vue3+element ui例子:https://gitee.com/huanglgln/vue-sys-manage-el ?vue3+view ui例子:https://gitee.com/huanglgln/vue-sys-manage ?vue3+Ant Design Vue ui例子:https://gitee.com/huanglgln/vue-sys-manage-adv?

    2024年02月15日
    瀏覽(34)
  • 國(guó)密算法SM2,SM3,SM4-java實(shí)現(xiàn)原理

    國(guó)密算法SM2,SM3,SM4-java實(shí)現(xiàn)原理

    SM2是國(guó)家密碼管理局于2010年12月17日發(fā)布的橢圓曲線公鑰密碼算法,基于ECC。其簽名速度與秘鑰生成速度都快于RSA,非對(duì)稱加密,該算法已公開(kāi) SM3是中華人民共和國(guó)政府采用的一種密碼散列函數(shù)標(biāo)準(zhǔn),由國(guó)家密碼管理局于2010年12月17日發(fā)布。SM3主要用數(shù)字簽名及驗(yàn)證、消息認(rèn)

    2024年02月13日
    瀏覽(39)
  • Python實(shí)現(xiàn)國(guó)家商用密碼算法sm2/sm3/sm4/sm9(國(guó)密)

    2010 年開(kāi)始,我國(guó)國(guó)家密碼管理局就已經(jīng)開(kāi)始陸續(xù)發(fā)布了一系列國(guó)產(chǎn)加密算法,這其中就包括 SM1、SM2、SM3 、SM4、SM7、SM9、ZUC(祖沖之加密算法)等,SM 代表商密,即商業(yè)密碼,是指用于商業(yè)的、不涉及國(guó)家秘密的密碼技術(shù)。SM1 和 SM7 的算法不公開(kāi),其余算法都已成為 ISO/IEC

    2024年02月15日
    瀏覽(31)
  • 新手入門 | 掌握國(guó)密算法:新手指南: SM2 / SM3 / SM4密碼算法詳解

    在密碼學(xué)領(lǐng)域,有多種加密與簽名算法,它們?cè)谛畔踩I(lǐng)域發(fā)揮著舉足輕重的作用。如今,隨著互聯(lián)網(wǎng)的快速發(fā)展,網(wǎng)絡(luò)安全已經(jīng)成為各類信息系統(tǒng)完整性、可用性、保密性的重要保障,越來(lái)越多的國(guó)產(chǎn)密碼算法得到了廣泛的應(yīng)用與關(guān)注。在本文中,我們將重點(diǎn)介紹三個(gè)經(jīng)

    2024年02月12日
    瀏覽(35)
  • react+vue 前端國(guó)密算法sm2、sm3 、sm4的js ts實(shí)現(xiàn)

    1. 簡(jiǎn)單介紹下SM2 和 SM3 SM2 算法:是一種公鑰加密算法,它的密鑰長(zhǎng)度為 256 位,安全性較高??捎糜跀?shù)字簽名、密鑰協(xié)商等場(chǎng)景。 SM3 算法:是一種對(duì)稱加密算法,用于消息摘要和數(shù)字簽名等場(chǎng)景。它的密鑰長(zhǎng)度為 256 位,安全性較高。SM3 算法與 SM2 算法相互配合,提高了整體

    2024年01月19日
    瀏覽(33)
  • 國(guó)密SM2算法(JS加密,C#、Java解密)

    國(guó)密SM2算法(JS加密,C#、Java解密)

    常見(jiàn)的滲透測(cè)試會(huì)將網(wǎng)站登錄時(shí)密碼使用明文傳輸視為風(fēng)險(xiǎn)。推薦使用國(guó)密算法或者RSA算法對(duì)密碼進(jìn)行加密傳輸。 RSA加密(JS加密,C#、Java解密)請(qǐng)參考《RSA對(duì)稱加密(JS加密,C#、Java解密)》?????? 本文描述國(guó)密SM2算法的實(shí)現(xiàn)。 一、工作原理 前端js使用公鑰進(jìn)行加密

    2024年02月02日
    瀏覽(30)
  • 密碼算法(SM1、SM2、SM3、SM4、同態(tài)加密、密態(tài)計(jì)算、隱私計(jì)算和安全多方計(jì)算)

    密碼算法(SM1、SM2、SM3、SM4、同態(tài)加密、密態(tài)計(jì)算、隱私計(jì)算和安全多方計(jì)算)

    SM1、SM2、SM3和SM4 為了保障商用密碼的安全性,國(guó)家密碼局制定了一系列密碼標(biāo)準(zhǔn),包括:SM1(SCB2)、SM2、SM3、SM4、SM7、SM9、祖沖之密碼算法(ZUC) 等。 SM1、SM4、SM7、祖沖之密碼(ZUC)是對(duì)稱算法。 SM2、SM9是非對(duì)稱算法。 SM3是哈希算法。 SM1、SM7算法不公開(kāi),調(diào)用該算法時(shí),

    2024年02月03日
    瀏覽(26)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包