首页 > 解决方案 > 如何将 Python HMAC 请求翻译成 Swift

问题描述

我已经在这大约 10 个小时了,无论我使用什么 HMAC 组合来快速使用,我都无法让它与 python 生成的密钥相匹配。

蟒蛇代码:

signature = hmac.new(secret.decode('hex'), msg=datastring, digestmod=hashlib.sha256).hexdigest()

SWIFT代码:

let key = SymmetricKey(data: self.secret.data(using: .utf8)!)
let hexData = HMAC<SHA256>.authenticationCode(for: datastring.data(using: .utf8)!, using: key)
let signature = Data(hexData).map { String(format: "%02hhx", $0) }.joined()

对于我在 Swift 中做错(或丢失)的任何帮助,我们将不胜感激。

标签: swiftswiftui

解决方案


基于包含密钥的十六进制表示的假设,self.secret两者String之间的差异归结为您使用:

self.secret.data(using: .utf8)!

它将只执行对基础字节的直接转换,而不是将每个字符对转换为相应的字节,如下所示:

secret.decode('hex')

在 Python 2 中执行。

据我所知,在 Swift 标准库中没有执行此转换的函数,但您可以使用以下方法进行转换:

func bytes(fromHex input: String) -> Data {
  var result = Data()
  var byte: UInt8 = 0 

  for (index, character) in input.enumerated() {
    let codeUnit = character.utf8[character.utf8.startIndex]
    var nibble: UInt8 = 0 

    switch codeUnit {
    case 0x30..<0x3a:
      nibble = codeUnit - 0x30 
    case 0x61..<0x67:
      nibble = codeUnit - 0x57
    default:
      break
    }   

    if index % 2 == 0 { 
      byte |= (nibble << 4)
    } else {
      byte |= nibble
      result.append(contentsOf: [byte])
      byte = 0 
    }   
  }

  return result
}

然后您的代码将变为:

let key = SymmetricKey(data: bytes(fromHex: self.secret))
let hexData = HMAC<SHA256>.authenticationCode(for: datastring.data(using: .utf8)!, using: key)
let signature = Data(hexData).map { String(format: "%02hhx", $0) }.joined()

推荐阅读