使用Swift,如何使用SHA1创建OpenSSL HMAC摘要,然后使用严格的encode64进行编码

时间:2015-10-21 08:02:27

标签: ruby swift openssl hmac

我需要使用SHA1创建OpenSSL HMAC摘要的Base64严格编码表示。我在Ruby中有代码,但我需要Swift中的类似代码。有人这么容易吗?

Ruby中的代码是:

digest = OpenSSL::Digest.new('sha1')
hmac_digest = OpenSSL::HMAC.digest(digest, secret_key, canonical_string)
Base64.strict_encode64(hmac_digest)

如上所示,我的输入是2个字符串(secret_keycanonical_string),我首先创建摘要,然后对其进行编码。

那么,Swift中哪些正确的代码会为相同的输入提供相同的结果?

1 个答案:

答案 0 :(得分:1)

我创建了一个桥接标头来导入CommonCrypto.h

然后我使用以下函数扩展String:

enum HMACAlgorithm {
  case MD5, SHA1, SHA224, SHA256, SHA384, SHA512

  func toCCHmacAlgorithm() -> CCHmacAlgorithm {
    var result: Int = 0
    switch self {
    case .MD5:
        result = kCCHmacAlgMD5
    case .SHA1:
        result = kCCHmacAlgSHA1
    case .SHA224:
        result = kCCHmacAlgSHA224
    case .SHA256:
        result = kCCHmacAlgSHA256
    case .SHA384:
        result = kCCHmacAlgSHA384
    case .SHA512:
        result = kCCHmacAlgSHA512
    }
    return CCHmacAlgorithm(result)
  }

  func digestLength() -> Int {
    var result: CInt = 0
    switch self {
    case .MD5:
        result = CC_MD5_DIGEST_LENGTH
    case .SHA1:
        result = CC_SHA1_DIGEST_LENGTH
    case .SHA224:
        result = CC_SHA224_DIGEST_LENGTH
    case .SHA256:
        result = CC_SHA256_DIGEST_LENGTH
    case .SHA384:
        result = CC_SHA384_DIGEST_LENGTH
    case .SHA512:
        result = CC_SHA512_DIGEST_LENGTH
    }
    return Int(result)
  }
}

extension String {
  func hmac(algorithm: HMACAlgorithm, key: String) -> String {
    let cKey = key.cStringUsingEncoding(NSUTF8StringEncoding)
    let cData = self.cStringUsingEncoding(NSUTF8StringEncoding)

    var result = [CUnsignedChar](count: Int(algorithm.digestLength()), repeatedValue: 0)

    CCHmac(algorithm.toCCHmacAlgorithm(), cKey!, Int(strlen(cKey!)), cData!, Int(strlen(cData!)), &result)

    let hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength())))

    let hmacBase64 = hmacData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding76CharacterLineLength)

    return String(hmacBase64)
 }
}