简体   繁体   中英

Swift equivalent of hash_hmac in PHP

I have been trying to create an oauth_signature in Swift4 which is to be sent and compared with the one already generated in the php backend code using hash_hmac function. I have used the below code to generate the signature, but the result I got is entirely different from the one generated by hash_hmac() in PHP.

func digestHMac256(key: String) -> String! {   

        let str = self.cString(using: String.Encoding.utf8)
        let strLen = self.lengthOfBytes(using: String.Encoding.utf8)

        let digestLen = Int(CC_SHA256_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<Any>.allocate(capacity: digestLen)

        let keyStr = key.cString(using: String.Encoding.utf8)
        let keyLen = key.lengthOfBytes(using: String.Encoding.utf8)

        let algorithm = CCHmacAlgorithm(kCCHmacAlgSHA256)

        CCHmac(algorithm, keyStr!, keyLen, str!, strLen, result)

        let data = NSData(bytesNoCopy: result, length: digestLen)

        let hash = data.base64EncodedString()

        return hash
    }

$hash_algorithm = "sha1"; 

$string_to_sign = "GET&http%3A%2F%2Fwww.mydomain.com%2Fv1%2Fhomepage&customerid%3D1247";

$secret = "cs_a6twe79rt7aa";

$signature = base64_encode( hash_hmac( $hash_algorithm, $string_to_sign, $secret, true ) );

Can anyone please help me with this? Thanks.

In PHP code you are using SHA1 and in Swift code - SHA256. These are different hashing algorithms and that's why you're getting different signatures. You should use kCCHmacAlgSHA1 instead.

Also you should avoid using cString API, it's not safe in Swift. It's better to use Data instead.

func digestHMac256(key: String) -> String! {

    guard
        let strData = self.data(using: String.Encoding.utf8),
        let keyData = key.data(using: String.Encoding.utf8) else {
            return ""
    }

    let digestLen = Int(CC_SHA256_DIGEST_LENGTH)
    let result = UnsafeMutablePointer<Any>.allocate(capacity: digestLen)

    let algorithm = CCHmacAlgorithm(kCCHmacAlgSHA256)

    strData.withUnsafeBytes { strBytes in
        keyData.withUnsafeBytes({ keyBytes in
            CCHmac(algorithm, keyBytes, keyData.count, strBytes, strData.count, result)
        })
    }

    let data = NSData(bytesNoCopy: result, length: digestLen)

    let hash = data.base64EncodedString()

    return hash
}

Also check the string which you're trying to encode. For example:

let toEncode = "GET&http%3A%2F%2Fwww.mydomain.com%2Fv1%2Fhomepage&customerid%3D1247"

let encoded = toEncode.digestHMac256(key: "cs_a6twe79rt7aa")
// dvU3NwZXqG31Sziagj3JgkUCLwTRxT3w733yRWzL7bM=
let encodedWithoutPercentEncoding = toEncode.removingPercentEncoding!.digestHMac256(key: "cs_a6twe79rt7aa")
// ZRmxmYPXZq/rLLkJsx1A/AtK7BarML7gu62+fYfzLvs=

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM