SM3-杂凑算法,单向散列函数(单向性,不可逆)

示例代码:

1、SM3工具类

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算法加密
     * @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数组
     * 生成对应的hash值
     * @param srcData
     * @return
     */
    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;
    }

    /**
     * 通过密钥进行加密
     * 指定密钥进行加密
     * @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;
    }

    /**
     * 判断源数据与加密数据是否一致
     * 通过验证原数组和生成的hash数组是否为同一数组,验证两者是否为同意数据
     * @param srcStr 源字符串
     * @param sm3HexString 16进制字符串
     * @return 校验结构
     */
    public static boolean verify(String srcStr,String sm3HexString) {

        boolean flag = false;
        try {
            //原字符串
            byte[] srcData  = srcStr.getBytes(ENCODING);
            //16进制转为数组
            byte[] sm3Hash = ByteUtils.fromHexString(sm3HexString);
            //通过摘要加密生成新的hash数组
            byte[] newHash = hash(srcData);
            if (Arrays.equals(newHash,sm3Hash))
                flag = true;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return flag;
    }
}

2、测试

import com.xdh.demo.sm3.Sm3Utils;

public class Sm3UtilsTest {
    public static void main(String[] args) {
        //JSON串加密
        String json = "{\"name\":\"xiatian\",\"website\":\"http://www.bai.com\"}";
        String hex = Sm3Utils.encrypt(json);
        System.out.println(hex);   //fe2547ca491088e5c5d1664b049558de896db8ceed65044bd6212f4393d2d7ce

        //单个字符串加密
        String str = "123456";
        //加密之后转为16进制字符串
        String mm = Sm3Utils.encrypt(str);
        System.out.println("加密后:" + mm);   //加密后:207cf410532f92a47dee245ce9b11ff71f578ebd763eb3bbea44ebd043d018fb

        boolean flag = Sm3Utils.verify(str,mm);
        System.out.println(flag);   //true
    }
}

 

posted @ 2021-09-13 17:02  娜梓  阅读(2224)  评论(0编辑  收藏  举报