0

Hello i need to implement hash_hmac php method to swift and try like this:

var hexString = ""
var result: [CUnsignedChar]
if let cKey = keyStr.cString(using: String.Encoding.utf8),
    let cData = messageStr.cString(using: String.Encoding.utf8)
{
    let algo  = CCHmacAlgorithm(kCCHmacAlgSHA256)
    result = Array(repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
    CCHmac(algo, cKey, cKey.count, cData, cData.count, &result)
} else {
    fatalError("ERROR...")
}

for byte in result {
    hexString += String(format:"%2hhx", UInt8(byte))
}

print(hexString)

but this is not simulated like PHP exactly.

And i tried this code :

let secretData : Data = messageStr.data(using: .utf8)!
let signatureData : Data = keyStr.data(using: .utf8)!
let digest = UnsafeMutablePointer<UInt8>.allocate(capacity:Int(CC_SHA256_DIGEST_LENGTH))
var hmacContext = CCHmacContext()
CCHmacInit(&hmacContext, CCHmacAlgorithm(kCCHmacAlgSHA256), [UInt8](secretData), secretData.count)
CCHmacUpdate(&hmacContext, [UInt8](signatureData), [UInt8](signatureData).count)
CCHmacFinal(&hmacContext, digest)
let cryptData = Data(bytes: digest, count: Int(CC_SHA256_DIGEST_LENGTH))
macStr = cryptData.hexEncodedString()

But it does not work...

edit:

message: a3FQZHJ1Z0hnOFhpZ2xkWg==8v8Fs6LXKTJOha69tsvUew==
key: u6KuXJLIUwEUl7noY8J8H1ffDRwLC/5gjaWW1qTQ3hE=
swift output: 37987524d1a379d67b2bae0a1618296d48b7a1f058a3b5816bf8070cb2fdf2ec
php output: 30f39f78a24ae2e6037114708f97fae1f3fede8dabece012a12b6625f3329302

reza_khalafi
  • 6,230
  • 7
  • 56
  • 82
  • Check this link: https://www.jokecamp.com/blog/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/#swift – Sivajee Battina May 10 '17 at 06:25
  • 1
    php code for hash_hmac you can campier and correct https://github.com/php/php-src/blob/b7f59be9f48d0079e222e26c01cd0a067480b97e/ext/hash/hash.c – Varun Naharia May 10 '17 at 06:29
  • Which one is the php_hmac? is this? "php_hash_hmac_round" @VarunNaharia – reza_khalafi May 10 '17 at 06:43
  • I tested already and wrong for PHP mode @SivajeeBattina – reza_khalafi May 10 '17 at 06:44
  • Can you please check this link also: http://stackoverflow.com/questions/24099520/commonhmac-in-swift/24411522#24411522 – Sivajee Battina May 10 '17 at 06:46
  • Yes i checked it already, I checked whole of StackOverFlow but no one implement it... @SivajeeBattina but i think VarunNaharia answer i right. – reza_khalafi May 10 '17 at 06:54
  • 1
    @reza_khalafi please add a string that you are tried to convert and expected out come(as it is in php) and the outcome that you are getting from above code – Varun Naharia May 10 '17 at 08:07
  • message: a3FQZHJ1Z0hnOFhpZ2xkWg==8v8Fs6LXKTJOha69tsvUew== and key: u6KuXJLIUwEUl7noY8J8H1ffDRwLC/5gjaWW1qTQ3hE= in swift : 37987524d1a379d67b2bae0a1618296d48b7a1f058a3b5816bf8070cb2fdf2ec and in php : 30f39f78a24ae2e6037114708f97fae1f3fede8dabece012a12b6625f3329302 @VarunNaharia – reza_khalafi May 10 '17 at 08:16
  • can you please explain CCHmacAlgorithm it's showing error: use of unresolved identifier 'CCHmacAlgorithm' while using in playground – Varun Naharia May 10 '17 at 08:59
  • I try to simulate laravel encryption (php) AES-256-CBC and encryption is correct but mac is wrong, no error ... but when try to login with encrypted string i get error : mac is invalid. http://stackoverflow.com/questions/43817329/how-to-encryption-aes-256-cbc-in-ios-swift-3-like-larvel-encrypt-method?noredirect=1#comment74682766_43817329 @VarunNaharia – reza_khalafi May 10 '17 at 09:02
  • 1
    @VarunNaharia `a3FQZHJ1Z0hnOFhpZ2xkWg==8v8Fs6LXKTJOha69tsvUew==` is invalid Base64 encoding, it appears to be two separate encodings joined together. '=' characters are only allowed at the end of a Base64 encoding as one or two padding characters. – zaph May 10 '17 at 11:27

2 Answers2

1

I solved this problem : (Swift 3)

extension Data {

    func hexEncodedString() -> String {
        return map { String(format: "%02hhx", $0) }.joined()
    }
}

func HMAC_CREATOR(MIX_STR mixStr:String,KEY_DATA_UINT8 keyDataUint8:Array<UInt8>) -> String {
        let signatureData : Data = mixStr.data(using: .utf8)!
        let digest = UnsafeMutablePointer<UInt8>.allocate(capacity:Int(CC_SHA256_DIGEST_LENGTH))
        var hmacContext = CCHmacContext()
        CCHmacInit(&hmacContext, CCHmacAlgorithm(kCCHmacAlgSHA256), (keyDataUint8), (keyDataUint8.count))
        CCHmacUpdate(&hmacContext, [UInt8](signatureData), [UInt8](signatureData).count)
        CCHmacFinal(&hmacContext, digest)
        let macData = Data(bytes: digest, count: Int(CC_SHA256_DIGEST_LENGTH))
        return  macData.hexEncodedString()
    }
reza_khalafi
  • 6,230
  • 7
  • 56
  • 82
0

There is an error in the Swift code:

CCHmacInit(&hmacContext, CCHmacAlgorithm(kCCHmacAlgSHA256), [UInt8](secretData), secretData.count)
CCHmacUpdate(&hmacContext, [UInt8](signatureData), [UInt8](signatureData).count)

CCHmacInit takes the key.
CCHmacUpdate takes the data.
The question code has that backwards.

Note:

There is a one-shot HMAC function that is easier to use and harder to get wrong in this case:
CCHmac(CCHmacAlgorithm algorithm, const void *key, size_t keyLength, const void *data, size_t dataLength, void *macOut);

zaph
  • 111,848
  • 21
  • 189
  • 228