HMAC SHA512 с использованием CommonCrypto в Swift 3.1

Я пытаюсь зашифровать данные для отправки в API.

API требует, чтобы данные отправлялись в виде hmac_sha512 зашифрованного хэша.

Я нашел различные примеры того, как это можно было сделать для sha1 и других (не sha512), а также в более старых версиях Swift.

Ни один из примеров, которые я пробовал, не работает для swift 3.1

Любая помощь в правильном направлении будет оценена по достоинству.

Изменить:

В PHP я успешно отправляю его, используя:

    $sign = hash_hmac('sha512', $post_data, $this->secret);

Редактировать 2:

Я did add briding header, я не знаю, что делать дальше! Поскольку приведенные ниже примеры кода не работают для swift 3.1 :(

Редактировать 3:

Решено! Угадайте, я неправильно создавал заголовок бридинга! :(

P.S. Я стараюсь избегать CryptoSwift, сосредоточившись на CommonCrypto.

Приведенный ниже ответ неверен, так как он не позволяет hmac получить ключ для шифрования. Я провел исследование и, наконец, заработал. Этот пост содержит рабочий пример проекта для hmac: https://github.com/nabtron/hmacTest.


person Nabeel Khan    schedule 07.06.2017    source источник
comment
вы не можете отправлять данные в виде хэша ... вы отправляете подпись или они хотят, чтобы она была зашифрована sha512?   -  person Grady Player    schedule 07.06.2017
comment
в php я использую: $sign = hash_hmac('sha512', $post_data, $this-›secret);   -  person Nabeel Khan    schedule 07.06.2017
comment
См. ответ Swift HMAC.   -  person zaph    schedule 28.12.2017


Ответы (1)


Я думаю, что лучше всего использовать модуль Crypto, который является оболочкой для обычного шифрования. Если вы хотите использовать commonCrypto напрямую, вы должны добавить заголовок моста в проект и импортировать common crypto, используя: #import <CommonCrypto/CommonCrypto.h>

Изменить 1

Создайте класс swift и добавьте в него следующий код:

import Foundation

extension String {
    var md5: String {
        return HMAC.hash(inp: self, algo: HMACAlgo.MD5)
    }

    var sha1: String {
        return HMAC.hash(inp: self, algo: HMACAlgo.SHA1)
    }

    var sha224: String {
        return HMAC.hash(inp: self, algo: HMACAlgo.SHA224)
    }

    var sha256: String {
        return HMAC.hash(inp: self, algo: HMACAlgo.SHA256)
    }

    var sha384: String {
        return HMAC.hash(inp: self, algo: HMACAlgo.SHA384)
    }

    var sha512: String {
        return HMAC.hash(inp: self, algo: HMACAlgo.SHA512)
    }
}

public struct HMAC {

    static func hash(inp: String, algo: HMACAlgo) -> String {
        if let stringData = inp.data(using: String.Encoding.utf8, allowLossyConversion: false) {
            return hexStringFromData(input: digest(input: stringData as NSData, algo: algo))
        }
        return ""
    }

    private static func digest(input : NSData, algo: HMACAlgo) -> NSData {
        let digestLength = algo.digestLength()
        var hash = [UInt8](repeating: 0, count: digestLength)
        switch algo {
        case .MD5:
            CC_MD5(input.bytes, UInt32(input.length), &hash)
            break
        case .SHA1:
            CC_SHA1(input.bytes, UInt32(input.length), &hash)
            break
        case .SHA224:
            CC_SHA224(input.bytes, UInt32(input.length), &hash)
            break
        case .SHA256:
            CC_SHA256(input.bytes, UInt32(input.length), &hash)
            break
        case .SHA384:
            CC_SHA384(input.bytes, UInt32(input.length), &hash)
            break
        case .SHA512:
            CC_SHA512(input.bytes, UInt32(input.length), &hash)
            break
        }
        return NSData(bytes: hash, length: digestLength)
    }

    private static func hexStringFromData(input: NSData) -> String {
        var bytes = [UInt8](repeating: 0, count: input.length)
        input.getBytes(&bytes, length: input.length)

        var hexString = ""
        for byte in bytes {
            hexString += String(format:"%02x", UInt8(byte))
        }

        return hexString
    }
}

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

    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)
    }
}

затем используйте его просто stringName.sha512
этот класс расширяет класс String, который дает возможность использовать хеширование как функцию в классе строк.

person Tarek A.    schedule 07.06.2017
comment
Я добавил заголовок briding, я не знаю, что делать дальше! - person Nabeel Khan; 07.06.2017
comment
проверьте редактирование и свяжитесь со мной для помощи! - person Tarek A.; 07.06.2017
comment
выдает ошибки типа: использование неразрешенного идентификатора CC_MD5 и т.д. :( - person Nabeel Khan; 07.06.2017
comment
Решено! Угадайте, я неправильно создавал заголовок бридинга! :( - person Nabeel Khan; 07.06.2017
comment
как я могу передать ему строку и секретный ключ? как пример PHP выше? - person Nabeel Khan; 07.06.2017