Java实现MD5和国密SM3摘要算法

一、JDK提供的默认MD5算法工具

MD5算法类型枚举

/**
 * JDK提供的默认摘要算法.
 *
 * @author linzp
 * @date 2022/2/8 16:46
 */
public enum DigestAlgorithmEnum {
    /**
     * MD5
     */
    MD5("MD5"),

    /**
     * MD2
     */
    MD2("MD2"),

    /**
     * SHA
     */
    SHA("SHA"),

    /**
     * SHA
     */
    SHA1("SHA-1"),

    /**
     * SHA2
     */
    SHA224("SHA-224"),

    /**
     * SHA2
     */
    SHA256("SHA-256"),

    /**
     * SHA5
     */
    SHA384("SHA-384"),

    /**
     * SHA5
     */
    SHA512("SHA-512");

    /**
     * 算法编码.
     */
    private String code;

    /**
     * 无参
     */
    DigestAlgorithmEnum(){}

    /**
     * 构造.
     * @param code
     */
    DigestAlgorithmEnum(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
}

MD5算法工具类

import io.sugo.cloud.data.security.enums.DigestAlgorithmEnum;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 常规摘要算法:MD5、SHA实现
 *
 * @author linzp
 * @date 2022/2/8 16:44
 */
public final class MD5Util {
    /**
     * 16进制
     */
    private static final String[] HEX_DIGITS = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

    /**
     * 私有构造
     */
    private MD5Util() {
    }

    /**
     * md5加密
     *
     * @param srcData
     * @return
     */
    public static String entrypt(DigestAlgorithmEnum digestAlgorithmEnum, byte[] srcData) {
        byte[] secretBytes = null;
        try {
            secretBytes = MessageDigest.getInstance(digestAlgorithmEnum.getCode()).digest(srcData);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("this digest algorithm is not exists!");
        }
        return byteToHexString(secretBytes);
    }

    /**
     * 转换16进制.
     *
     * @param bs
     * @return
     */
    public static String byteToHexString(byte[] bs) {
        StringBuffer sb = new StringBuffer();
        for (byte b : bs) {
            sb.append(byteToHexString(b));
        }
        return sb.toString();
    }

    /**
     * 转换16进制.
     *
     * @param b
     * @return
     */
    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n = 256 + n;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return HEX_DIGITS[d1] + HEX_DIGITS[d2];
    }
}

二、国密SM3摘要算法实现工具类

需要导入maven依赖

<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.69</version>
</dependency>

国密SM3实现摘要算法加密工具类,可实现对文件的MD5加密

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.util.encoders.Hex;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.Security;

/**
 * 国密SM3摘要算法实现工具.
 * 用于替换MD5、SHA算法
 *
 * @author linzp
 * @date 2022/2/8 10:48
 */
public final class SM3Util {

    /**
     * 私有构造器.
     */
    private SM3Util() {
    }

    // 拓展算法提供方,加载BC库.
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * SM3摘要算法逻辑
     *
     * @param srcData 待加密byte[]
     * @return
     */
    private static byte[] sm3(byte[] srcData) {
        SM3Digest sm3Digest = new SM3Digest();
        sm3Digest.update(srcData, 0, srcData.length);
        byte[] hash = new byte[sm3Digest.getDigestSize()];
        sm3Digest.doFinal(hash, 0);
        return hash;
    }

    /**
     * 摘要算法加密
     *
     * @param srcData 待加密byte[]
     * @return
     */
    public static String encrypt(byte[] srcData) {
        byte[] hash = sm3(srcData);
        String hexString = Hex.toHexString(hash);
        return hexString;
    }

    /**
     * 指定密钥进行加密.
     *
     * @param key     密钥
     * @param srcData 待加密byte[]
     * @return
     */
    private static byte[] hmacSm3(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[] hash = new byte[mac.getMacSize()];
        mac.doFinal(hash, 0);
        return hash;
    }

    /**
     * 指定密钥进行加密.
     *
     * @param key     密钥
     * @param srcData 待加密byte[]
     * @return
     */
    public static String encrypt(byte[] key, byte[] srcData) {
        byte[] hash = hmacSm3(key, srcData);
        String hexString = Hex.toHexString(hash);
        return hexString;
    }

    /**
     * 基于BC库的摘要算法加密
     *
     * @param srcData 待加密byte[]
     * @return
     * @throws Exception
     */
    private static byte[] sm3bc(byte[] srcData) throws Exception {
        MessageDigest messageDigest = MessageDigest.getInstance("SM3", "BC");
        byte[] digest = messageDigest.digest(srcData);
        return digest;
    }

    /**
     * 基于BC库的摘要算法加密
     *
     * @param srcData 待加密byte[]
     * @return
     * @throws Exception
     */
    public static String encryptBC(byte[] srcData) throws Exception {
        byte[] hash = sm3bc(srcData);
        String hexString = Hex.toHexString(hash);
        return hexString;
    }

    /**
     * 对文件进行摘要算法加密.
     *
     * @param file
     * @return
     */
    public static String encrypt(File file) {
        //TODO-linzp 如使用大文件应该对此方法进行优化,避免出现OOM
        byte[] srcData;
        FileInputStream fis = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            srcData = bos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("file not found!");
        } finally {
            closeResoruce(fis, bos);
        }
        return encrypt(srcData);
    }

    /**
     * 关闭资源.
     *
     * @param fis
     * @param bos
     */
    private static void closeResoruce(FileInputStream fis, ByteArrayOutputStream bos) {
        if (null != fis) {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (null != bos) {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林志鹏JAVA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值