5

Before SDK8.3 I was generating my hmac this way. Now I get an error on the CCHmac() function. Since I'm a beginner I can't figure out how to fix it. Thanks in advance for your help!

xcode warning: cannot involke 'CCHmac' with an argument list of type (UInt32, [CChar]?, UInt, [CChar]?, UInt, inout[(CUnsignedChar)]

func generateHMAC(key: String, data: String) -> String {

    let cKey = key.cStringUsingEncoding(NSUTF8StringEncoding)
    let cData = data.cStringUsingEncoding(NSUTF8StringEncoding)

    var result = [CUnsignedChar](count: Int(CC_SHA512_DIGEST_LENGTH), repeatedValue: 0)
    CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA512), cKey, strlen(cKey!), cData, strlen(cData!), &result)


    let hash = NSMutableString()
    for var i = 0; i < result.count; i++ {
        hash.appendFormat("%02hhx", result[i])
    }

    return hash as String
}
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
Jab
  • 821
  • 3
  • 13
  • 26

1 Answers1

5

The problem is that strlen returns a UInt, while CCHmac’s length arguments are Ints.

While you could do some coercion, you may as well just use the count property of the two arrays rather than calling strlen.

func generateHMAC(key: String, data: String) -> String {

    var result: [CUnsignedChar]
    if let cKey = key.cStringUsingEncoding(NSUTF8StringEncoding),
           cData = data.cStringUsingEncoding(NSUTF8StringEncoding)
    {
        let algo  = CCHmacAlgorithm(kCCHmacAlgSHA512)
        result = Array(count: Int(CC_SHA512_DIGEST_LENGTH), repeatedValue: 0)

        CCHmac(algo, cKey, cKey.count-1, cData, cData.count-1, &result)
    }
    else {
        // as @MartinR points out, this is in theory impossible 
        // but personally, I prefer doing this to using `!`
        fatalError("Nil returned when processing input strings as UTF8")
    }

    let hash = NSMutableString()
    for val in result {
        hash.appendFormat("%02hhx", val)
    }

    return hash as String
}
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
  • You are again to fast :) – But note that with `.count` you'll include the terminating zero of the string, this gives a different result compared to the original code with `strlen()`. But actually I would convert the string to `NSData` instead, compare http://stackoverflow.com/a/25762128/1187415 for a similar method. – And the conversion to UTF-8 *cannot* fail. – Martin R Apr 22 '15 at 13:58
  • 1
    And again, I make a basic error by trying to be too fast :o Thanks, fixed. – Airspeed Velocity Apr 22 '15 at 14:04
  • Still, UTF-8 can represent all Unicode strings, so I do not think that the conversion can fail at all. – Martin R Apr 22 '15 at 14:08
  • Odd then that they made it optional after auditing (it would originally have been implicitly unwrapped pre-audit? I don’t have the old headers to hand) – Airspeed Velocity Apr 22 '15 at 14:10
  • 1
    Oh ignore me I’m being stupid, there are other encodings that might fail – Airspeed Velocity Apr 22 '15 at 14:10