Android 中实现 HMAC-SHA256

按指定格式拼接原始字符串、UTF-8编码、HMAC-SHA256加密、转十六进制字符串,(兼容Java 8+,Android/后端通用),并做好异常处理和注释,直接复制就能用。

核心说明

Java中实现HMAC-SHA256需要用到javax.crypto包下的Mac类,十六进制转换需要手动实现(Java无原生直接转的方法),同时要处理字符编码加密异常,以下是完整实现。

完整Java代码(直接可用)

包含签名计算核心方法 +十六进制转换工具方法 +异常处理 +测试示例

java 复制代码
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * 设备登录签名计算工具
 * 实现的HMAC-SHA256签名逻辑,格式:dev={dev}&timestamp={timestamp}&nonce={nonce}&secret={secretKey}
 */
public class DeviceSignUtil {

    // 加密算法:HMAC-SHA256
    private static final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
    // 十六进制字符集(固定)
    private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();

    /**
     * 计算设备登录HMAC-SHA256签名
     * @param dev 设备号
     * @param timestamp 时间戳(整型)
     * @param nonce 随机串
     * @param secretKey 秘钥
     * @return 十六进制签名字符串(小写)
     * @throws NoSuchAlgorithmException 算法不存在异常(理论上不会出现)
     * @throws InvalidKeyException 秘钥无效异常
     */
    public static String calculateDeviceSignature(String dev, long timestamp, String nonce, String secretKey)
            throws NoSuchAlgorithmException, InvalidKeyException {
        // 1. 严格按格式拼接原始字符串(注意参数名拼写:nonce/secret)
        String rawStr = String.format("dev=%s&timestamp=%d&nonce=%s&secret=%s",
                dev, timestamp, nonce, secretKey);

        // 2. 将字符串和秘钥编码为UTF-8字节数组
        byte[] rawBytes = rawStr.getBytes(StandardCharsets.UTF_8);
        byte[] secretBytes = secretKey.getBytes(StandardCharsets.UTF_8);

        // 3. 初始化HMAC-SHA256加密器
        SecretKeySpec secretKeySpec = new SecretKeySpec(secretBytes, HMAC_SHA256_ALGORITHM);
        Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
        mac.init(secretKeySpec);

        // 4. 计算HMAC-SHA256并转十六进制字符串
        byte[] signBytes = mac.doFinal(rawBytes);
        return bytesToHex(signBytes);
    }

    /**
     * 字节数组转十六进制字符串(小写)
     * @param bytes 加密后的字节数组
     * @return 十六进制小写字符串
     */
    private static String bytesToHex(byte[] bytes) {
        char[] result = new char[bytes.length * 2];
        for (int i = 0; i < bytes.length; i++) {
            int val = bytes[i] & 0xFF; // 消除符号位影响
            result[i * 2] = HEX_CHARS[val >>> 4]; // 高4位
            result[i * 2 + 1] = HEX_CHARS[val & 0x0F]; // 低4位
        }
        return new String(result);
    }

    // 测试示例(可直接运行验证)
    public static void main(String[] args) {
        try {
            // 测试参数
            String dev = "DEVICE123456";
            long timestamp = 1735689600;
            String nonce = "abcdefg1234567";
            String secretKey = "myDeviceSecret123";

            // 计算签名
            String signature = calculateDeviceSignature(dev, timestamp, nonce, secretKey);
            System.out.println("设备签名结果:" + signature);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

异常处理说明

Java加密相关方法会抛出受检异常,需手动捕获/声明,主要异常:

  • NoSuchAlgorithmException:指定的HmacSHA256算法不存在(理论上不会出现,Java所有版本都支持);

  • InvalidKeyException:秘钥无效(如空秘钥),业务中需做秘钥非空校验;

  • 实际业务中建议在外层捕获异常,统一处理(如返回空签名、打印日志):

    java 复制代码
    // 业务中调用示例(捕获所有异常)
    public String getSign(String dev, long timestamp, String nonce, String secretKey) {
        try {
            return DeviceSignUtil.calculateDeviceSignature(dev, timestamp, nonce, secretKey);
        } catch (Exception e) {
            e.printStackTrace();
            return null; // 或返回空字符串,根据业务处理
        }
    }

Android端兼容说明

如果这段代码用于Android开发,无需额外依赖,直接复制即可:

  1. Android SDK 19+(4.4)完全支持StandardCharsets.UTF_8,低版本(<19)可替换为"UTF-8"字符串:

    java 复制代码
    // 低版本Android替换编码方式
    byte[] rawBytes = rawStr.getBytes("UTF-8");
    byte[] secretBytes = secretKey.getBytes("UTF-8");
  2. 无需添加额外权限,加密相关API属于Android核心库,无需在清单文件声明。

总结

  1. 核心实现:通过javax.crypto.Mac实现HMAC-SHA256,手动实现字节数组转十六进制;
  2. 关键兼容:UTF-8编码、小写十六进制输出、timestamp用long类型,保证跨语言签名一致;
  3. 直接使用:代码包含工具类、测试示例、异常处理,Android/Java后端通用,复制即可集成到项目中。
相关推荐
代码or搬砖3 小时前
ReentranLock中AQS讲解
java·开发语言·redis
DN20203 小时前
AI销售机器人的隐私痛点与破解之道
人工智能·python·机器学习·机器人·节日
rainbow68893 小时前
C++智能指针实战:从入门到精通
java·开发语言
瑞雪兆丰年兮3 小时前
[从0开始学Java|第五天]Java循环高级综合练习
java·开发语言
YIN_尹3 小时前
【MySQL】增删查改的艺术——数据库CRUD完全指南(下)
android·数据库·mysql
清铎3 小时前
项目_Agent实战
开发语言·人工智能·深度学习·算法·机器学习
BoJerry7773 小时前
数据结构——单链表(不带头)【C】
c语言·开发语言·数据结构
恬淡如雪3 小时前
Excel接口测试自动化实战
爬虫·python·excel
m0_748233173 小时前
PHP8.0新特性全解析
android