Mac 消息认证码算法Java实现

Mac 消息认证码算法Java实现

项目地址

算法描述:

Mac:消息认证码 Message Authentication Code,带密钥的hash函数,用于保证消息数据完整性。

常用算法:(算法名大小写不敏感)

  • HmacSHA256
  • HmacSHA512
  • HmacSHA3-256
  • HmacSHA3-512

参考:

  • https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Mac
  • https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#Mac
  • https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#HmacEx

代码实现:

package com.ysx.utils.crypto.mac;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.Arrays;
import java.util.List;

/**
 * @author youngbear
 * @email youngbear@aliyun.com
 * @date 2021/7/28 22:44
 * @blog https://blog.csdn.net/next_second
 * @github https://github.com/YoungBear
 * @description Mac 工具类
 * 参考:https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#HmacEx
 * 实践中,需要保证密钥长度必须不小于算法长度,比如HmacSHA256算法,则密钥长度需要不小于256bit
 * Mac:消息认证码 Message Authentication Code,带密钥的hash函数,用于保证消息数据完整性。
 */
public class MacUtils {

    /**
     * 常用mac算法
     * 算法名称是大小写不敏感的
     * 参考:https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Mac
     */
    private static final List<String> MAC_ALGORITHM = Arrays.asList(
            "HmacSHA256",
            "HmacSHA512",
            "HmacSHA3-256",
            "HmacSHA3-512"

    );

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

    /**
     * 计算数据的mac值
     *
     * @param secretKey     密钥
     * @param data          数据
     * @param algorithmName 算法
     * @return mac值
     * @throws NoSuchAlgorithmException 异常
     * @throws NoSuchProviderException  异常
     * @throws InvalidKeyException      异常
     */
    public static byte[] mac(byte[] secretKey, byte[] data, String algorithmName)
            throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
        SecretKey sk = new SecretKeySpec(secretKey, algorithmName);
        Mac instance = Mac.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
        instance.init(sk);
        return instance.doFinal(data);
    }

    /**
     * 生成密钥
     *
     * @param algorithmName 算法名
     * @return 密钥字节数组
     * @throws NoSuchAlgorithmException 异常
     * @throws NoSuchProviderException  异常
     */
    public static byte[] generateKey(String algorithmName)
            throws NoSuchAlgorithmException, NoSuchProviderException {
        KeyGenerator kg = KeyGenerator.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
        SecretKey sk = kg.generateKey();
        return sk.getEncoded();
    }
}

测试代码:

package com.ysx.utils.crypto.mac;

import org.bouncycastle.util.encoders.Hex;
import org.junit.Assert;
import org.junit.Test;

import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;

/**
 * @author youngbear
 * @email youngbear@aliyun.com
 * @date 2021/7/28 22:45
 * @blog https://blog.csdn.net/next_second
 * @github https://github.com/YoungBear
 * @description
 */
public class MacUtilsTest {

    // 256bit密钥
    private static final String SK_256_HEX_STRING = "19d567ea44325e4a1f3dd6806565c12b49a1ee12ff4e64ff49ed73ad89770231";
    // 512bit密钥
    private static final String SK_512_HEX_STRING = "86311e9c13e8bfa7460b3e65ee6ec980cc0cc98df0397996978bf214e4e6370b6369fe0982c0bff93162e102775118a9064b22df25c243dc2ff9c7654ae605d6";

    @Test
    public void macHmacSha256Test() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
        byte[] data = "Lindon2012".getBytes(StandardCharsets.UTF_8);
        byte[] mac = MacUtils.mac(Hex.decode(SK_256_HEX_STRING), data, "HmacSHA256");
        String excepted = "b6fc0aab65fba494114a819c3312051b4633697dce4a17ee5cec0c7d28bffe47";
        Assert.assertEquals(excepted, Hex.toHexString(mac));
    }

    @Test
    public void macHmacSha512Test() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
        byte[] data = "Lindon2012".getBytes(StandardCharsets.UTF_8);
        byte[] mac = MacUtils.mac(Hex.decode(SK_512_HEX_STRING), data, "HmacSHA512");
        String excepted = "fcb933ea55f3f658e10fbadfc6f0c30b4ccd2149ca5e1bfa05f679894a4453186b5a9129f43c0c94473ba4cca7cccd7b92688f8962e805b4cb7319ae0dd78bb2";
        Assert.assertEquals(excepted, Hex.toHexString(mac));
    }

    @Test
    public void macHmacSha3_256Test() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
        byte[] data = "Lindon2012".getBytes(StandardCharsets.UTF_8);
        byte[] mac = MacUtils.mac(Hex.decode(SK_256_HEX_STRING), data, "HmacSHA3-256");
        String excepted = "2bc501509aa28d8f54c67f7b7f085ec31b7cb5b41ba5d0c0a73dd84cae4c9597";
        Assert.assertEquals(excepted, Hex.toHexString(mac));
    }

    @Test
    public void macHmacSha3_512Test() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
        byte[] data = "Lindon2012".getBytes(StandardCharsets.UTF_8);
        byte[] mac = MacUtils.mac(Hex.decode(SK_512_HEX_STRING), data, "HmacSHA3-512");
        String excepted = "cac22721a2be5dbce4e06653cd9d77e013c2afa7042443d2431efc204c61e5dea6b11f1953b216e44e0ddcd22b2df64f3f9cb0fdefac52130c93a034026fc431";
        Assert.assertEquals(excepted, Hex.toHexString(mac));
    }

    @Test
    public void random() {
        SecureRandom secureRandom = new SecureRandom();
        byte[] key = new byte[64];
        secureRandom.nextBytes(key);
        System.out.println(Hex.toHexString(key));
    }

    @Test
    public void generateKeyTest() throws NoSuchAlgorithmException, NoSuchProviderException {
        String algorithmName = "HmacSHA256";
        System.out.println(Hex.toHexString(MacUtils.generateKey(algorithmName)));
    }
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值