国密算法使用-SM3

1.概念

SM3: 消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位

用于替代MD5/SHA-1/SHA-2等国际算法,适用于数字签名和验证、消息认证码的生成与验证以及随机数的生成,可以满足电子认证服务系统等应用需求,于2010年12月17日发布。

它是在SHA-256基础上改进实现的一种算法,采用Merkle-Damgard结构,消息分组长度为512bit,输出的摘要值长度为256bit。


2.算法

SM3算法:SM3杂凑算法是我国自主设计的密码杂凑算法,适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。为了保证杂凑算法的安全性,其产生的杂凑值的长度不应太短,例如MD5输出128比特杂凑值,输出长度太短,影响其安全性SHA-1算法的输出长度为160比特,SM3算法的输出长度为256比特,因此SM3算法的安全性要高于MD5算法和SHA-1算法。

3.与MD5、SHA算法比较

1)、算法结构不同

在消息填充方面,几个hash算法基本相同,都是先在原始消息的最后加一位“1”,再添加k个“0”,最终要使l+1+k除以512后的余数为448,取其最小的非负整数。然后用一个64位的比特串标识原始消息的长度l。填充后的消息M正好是512位的倍数。(其中)
SM3算法的压缩函数与SHA-256的压缩函数具有相似的结构,但是SM3算法的设计更加复杂,比如压缩函数的每一轮都使用2个消息字。


2)、安全性不同

摘要函数在密码学中具有重要的地位,被广泛应用在数字签名,消息认证,数据完整性检测等领域。摘要函数通常被认为需要满足三个基本特性:碰撞稳固性,原根稳固性和第二原根稳固性。
即:

●对于任何一个给定的消息,它都很容易就能运算出散列数值。
●难以由一个已知的散列数值,去推算出原始的消息。
●在不更动散列数值的前提下,修改消息内容是不可行的。
●对于两个不同的消息,它不能给与相同的散列数值。

2005年,Wang等人给出了MD5算法和SHA-1算法的碰撞攻击方法,现今被广泛应用的MD5算法和SHA-1算法不再是安全的算法。
SM3密码摘要算法是中国国家密码管理局2010年公布的中国商用密码杂凑算法标准。SM3算法适用于商用密码应用中的数字签名和验证,是在SHA-256基础上改进实现的一种算法。SM3算法采用Merkle-Damgard结构,消息分组长度为512位,摘要值长度为256位。现今为止,SM3算法的安全性相对较高。
 

3)、效率不同

MD5、SHA1、SH2-256与SM3的对比:

在这里插入图片描述

 4.SM3在Java中加密案例

1)、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 {

    /**
     * 计算SM3摘要值
     *
     * @param srcData 原文
     * @return 摘要值,对于SM3算法来说是32字节
     */
    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 srcData 原文
     * @param sm3Hash 摘要值
     * @return 返回true标识验证成功,false标识验证失败
     */
    public static boolean verify(byte[] srcData, byte[] sm3Hash) {
        byte[] newHash = hash(srcData);
        if (Arrays.equals(newHash, sm3Hash)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 计算SM3 Mac值
     *
     * @param key     key值,可以是任意长度的字节数组
     * @param srcData 原文
     * @return Mac值,对于HMac-SM3来说是32字节
     */
    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;
    }
}

 2)、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 = "=========原文数据====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();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Genius_zhu/article/details/127120428