国密介绍-SM3

1  算法简介

SM3算法也是一种哈希算法,中国国家密码管理局在2010年发布,其名称是SM3密码杂凑算法,密码管理局有该算法的详细说明,可以到其网站下载《GBT 32905-2016 信息安全技术 SM3密码杂凑算法》和《GMT 0004-2012 SM3密码杂凑算法》。

算法的本质给任意长度的数据(l≤2^64)经过填充、迭代压缩后,生成固定长度的杂凑值,这个固定长度就是256比特

2 处理过程

  1. 第一步:填充。使填充后的数据的长度是512的整数倍。在数据的末尾上加一个1;然后把原始数据的长度用64比特表示,放在最后面;再看看现在的数据的长度值离512的整数还差多少个,差多少个就填多少个0在加的这个164比特的长度之间。
  2. 第二步:分组。把填充后的信息按照512比特一个分组进行分组。如果分成了n组,就是B0,B1,…,Bn−1个分组。
  3. 第三步:迭代压缩。对每一个分组都进行消息扩展,再借助寄存器得到最后的杂凑值(哈希值)。迭代压缩这里有很多中间变量和寄存器的操作,具体还是看一下算法。

3  优缺点 

  • 优点:

安全性高,虽然说安全性和SHA256相当。但个人认为应该指理论上与SHA256相当,毕竟都是哈希算法以及256位摘要。但实际应该比SHA256更高,毕竟破解不可逆算法就是靠字典库,而SHA256的字典库远大于SM3

  • 缺点:

大数据量下加密速度慢。

4 java实现:

基于BouncyCastle库实现:

package org.liuy.pki;


import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;

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

import com.sun.org.apache.xml.internal.security.utils.Base64;

/**
 * 
 * 国密SM3工具包
 * 
 * @author liuy
 *
 */
public class SM3Tools {
	
    
	 /**
     * SM3加密方式之:不提供密钥的方式 SM3加密,返回加密后长度为64位的16进制字符串
     *
     * @param src 明文
     * @return 加密字节组
     */
    public static byte[] encrypt(byte[] srcByte) {
		SM3Digest sm3 = new SM3Digest();
	    sm3.update(srcByte, 0, srcByte.length);
	    byte[] encryptByte = new byte[sm3.getDigestSize()];
	    sm3.doFinal(encryptByte, 0);
        return encryptByte;
    }
    
    /**
     * 计算文件sm3值
     * @param file
     * @return sm3Hex
     */
    public static String encryptFile(File file) throws FileNotFoundException {
    
	   try {
		   BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
		  SM3Digest sm3 = new SM3Digest();
		   int bufferSize = 16384;
	       byte [] buffer = new byte[bufferSize];
	       int sizeRead = -1;
	       while ((sizeRead = in.read(buffer)) != -1) {
			   sm3.update(buffer, 0, buffer.length);
		   }
	       in.close();
		   byte[] encryptByte = new byte[sm3.getDigestSize()];
		   sm3.doFinal(encryptByte, 0);
		   return Hex.toHexString(encryptByte);  
	   } catch (IOException e) {
		e.printStackTrace();
		  return null;
	   }
    }
    
	 /**
     * SM3散列
     *
     * @param data  数据明文
     * @return 加密后长度为64位的16进制字符串
     */
    public static String encrypt(String data) {
    		byte[] sm3Arry=	encrypt(data.getBytes());
    		return Hex.toHexString(sm3Arry);
    }

    /**
     *  hmacSM3加密: 返回Base64 hmac值
     *
     * @param srcB64  Base64数据
     * @param keyB64  Base64密钥
     * @return
     * @throws Exception
     */
    public static String hmacSM3(String srcB64, String keyB64) throws Exception {
    	byte[] srcByte = Base64.decode(srcB64);
        byte[] keyByte = Base64.decode(keyB64);
        byte[] sm3Hmac=hmacSM3(srcByte,keyByte);
        return Base64.encode(sm3Hmac);
    }
    
    /**
     * 计算hmac-sm3值
     * @param srcByte
     * @param keyByte
     * @return
     */
    public static byte[]  hmacSM3(byte[] srcByte,byte[]  keyByte) {
        KeyParameter keyParameter = new KeyParameter(keyByte);
        SM3Digest sm3 = new SM3Digest();
        HMac hMac = new HMac(sm3);
        hMac.init(keyParameter);
        hMac.update(srcByte, 0, srcByte.length);
        byte[] result = new byte[hMac.getMacSize()];
        hMac.doFinal(result, 0);
        return result;
    }


    /**
     * 利用源数据+密钥校验与密文是否一致
     *
     * @param src       源数据
     * @param key       任意长度密钥
     * @param sm3HexStr 密文
     * @return
     * @throws Exception
     */
    public static boolean VerifyHMac(byte[] srcArry, byte[] keyArry, byte[] hmacArry) throws Exception {
        byte[] newHmac = hmacSM3(srcArry, keyArry);
        return Arrays.equals(newHmac,hmacArry);  
    }

    /**
     * 校验源数据与加密数据是否一致
     *
     * @param src       源数据
     * @param sm3HexStr 16进制的加密数据
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] srcByte, String sm3HexStr) throws Exception {
    	byte[] newHashCode = encrypt(srcByte);
    	String newHashCodeHex=Hex.toHexString(newHashCode);
        if(newHashCodeHex.endsWith(sm3HexStr))
        {
        	return true;
        }
        else
        {
        	return false;
        }
    }
}

完整代码见:国密演示: SM算法用法,页面的SM3功能菜单:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值