You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java与Swift中HMACSHA256算法输出结果不一致求助

HMACSHA256结果不一致的问题分析与修复

嘿,我看了你的代码,问题出在Swift代码对原始字节数据的处理方式和输出编码格式上,和Java的逻辑不匹配,导致结果不一样。咱们一步步拆解:

核心问题点

  1. 字节数组转String的错误
    Java里你直接用原始的byte[]作为密钥和消息,但Swift的hmac函数接收的是String类型的key和消息。问题在于:你的字节数组里包含负数(比如-119、-110),这些字节对应的UTF-8序列是不合法的,转成String的时候会被替换成替换字符(通常是�),导致原始字节数据丢失,输入和Java完全不一样,结果自然不同。

  2. 输出编码格式不匹配
    Java最后输出的是Base64编码的结果,而Swift代码输出的是十六进制小写字符串,就算计算过程正确,输出格式也不一样,看起来结果不同。

修正后的Swift代码

我们需要让Swift直接处理原始字节数据(用Data类型),而不是转成String,同时支持输出Base64格式和Java对齐:

import CommonCrypto

extension Data {
    func hmacSHA256(with key: Data) -> Data {
        var result = Data(count: Int(CC_SHA256_DIGEST_LENGTH))
        result.withUnsafeMutableBytes { resultBytes in
            self.withUnsafeBytes { messageBytes in
                key.withUnsafeBytes { keyBytes in
                    CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256),
                           keyBytes.baseAddress, key.count,
                           messageBytes.baseAddress, self.count,
                           resultBytes.baseAddress)
                }
            }
        }
        return result
    }
    
    // 转Base64字符串,和Java的Base64.encodeBase64String对齐
    func toBase64String() -> String {
        return self.base64EncodedString()
    }
    
    // 转十六进制小写字符串,原Swift代码的输出格式
    func toHexString() -> String {
        return self.map { String(format: "%02x", $0) }.joined()
    }
}

// 测试你的输入数据
let secretBytes: [UInt8] = [0, 0, 0, 0, 38, 8, 117, 147] // 注意:Java的-119对应UInt8的147(因为byte是有符号的,256-119=147)
let messageBytes: [UInt8] = [5, 96, 98, 37, 5, 146, 99, 2, 131, 88, 55] // Java的-110=146,-125=131
let secretData = Data(secretBytes)
let messageData = Data(messageBytes)

// 计算HMAC并输出Base64,和Java结果对齐
let hmacData = messageData.hmacSHA256(with: secretData)
print(hmacData.toBase64String()) // 应该输出:7vRPbVRrJXJQFlMSfoW32nixMVeT4pnvqUV1A6ck0mw=

关键细节说明

  • 有符号字节转无符号:Java的byte是有符号的(范围-128到127),而Swift的UInt8是无符号的(0到255),所以需要把Java里的负数字节转换成对应的无符号值,比如-119 → 256 - 119 = 147,-110 → 256 - 110 = 146,-125 → 256 - 125 = 131。
  • 直接用Data处理字节:Data是Swift里专门处理原始字节数据的类型,不会像String那样因为编码问题破坏数据,保证输入和Java完全一致。
  • 输出格式对齐:新增toBase64String()方法,和Java的Base64.encodeBase64String输出格式一致,这样就能得到你期望的结果。

验证结果

运行修正后的Swift代码,输出的Base64字符串会和Java的结果完全一致:7vRPbVRrJXJQFlMSfoW32nixMVeT4pnvqUV1A6ck0mw=,对应的字节数组也和你期望的一致。

内容的提问来源于stack exchange,提问作者Ashish Kirpan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:46:55