Swift HMAC не соответствует NodeJS HMAC, но только иногда! - PullRequest
0 голосов
/ 18 сентября 2019

Я обнаружил ОГРОМНУЮ проблему в своем коде, и я буквально понятия не имею, что вызывает это.

ТАК, когда я отправляю запросы на мой сервер, я хэширую строку, которая есть в запросе.Иногда это ввод пользователя.

Мое приложение мультиязычное, поэтому я должен поддерживать все символы "ä" и т. Д.

Так что с обычными английскими буквами / цифрами и т. Д. Этот метод хеширования работаеткак мечта.НО, когда строка, которая хэшируется и сравнивается, содержит «ä» или «ö» (не особенно те, что буквально может быть, что любой символ, не входящий в набор Base64, вызовет это), хэш не совпадает!

Это абсолютная и полная катастрофа, и я не заметил этого до сих пор.Я попробовал в основном все, что я знаю, чтобы попытаться исправить это, и поиск в Google, и мне пока не повезло.

Я генерирую хэш в Swift, вводя строку и secretToken в эту функцию и сохраняя вывод какзаголовок HTTP:

func hmac(string: String, key: String) -> String {

    var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))

    CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), key, key.count, string, string.count, &digest)

    let data = Data(digest)

    return data.map { String(format: "%02hhx", $0) }.joined()

}

Как сравнить хеш в NodeJS:

if (hashInTheRequest === crypto.createHmac('sha256', secretToken).update(stringToHash).digest('hex')) {
    //Good to go
}

Заранее спасибо!

1 Ответ

1 голос
/ 18 сентября 2019

Это может быть связано с проблемой композиции.Вы упомянули нелатинские символы, но не указали конкретных примеров, в которых у вас были проблемы.

Что такое композиция?

Цель Unicode - представлять любой символ, используемый человечеством.Однако многие символы похожи, например u, ü, û и ū.Первоначальная идея состояла в том, чтобы просто присвоить кодовую точку каждой возможной комбинации.Как можно себе представить, это не самый эффективный способ хранения вещей.Вместо этого используется «базовый» символ, а затем к нему добавляется объединительный символ.

Давайте рассмотрим пример: ü

ü можно представить как U+00FC, также известный как LATIN SMALL LETTER U WITH DIAERESIS.

ü также может быть представлен как U+0075 (u), за которым следует U+0308 (◌̈), также известный как LATIN SMALL LETTER U,затем COMBINING DIARESIS.

Почему это проблематично?

Поскольку хеш-функции не знают, что такое строка.Все, что их волнует, это байты.Таким образом, строка должна быть декодирована в строку байтов.Как было показано выше, существует несколько различных способов декодирования строки, что означает, что две разные системы могут декодировать одну и ту же логическую строку в разные байты, что приводит к разным хэшам.

Как это исправить?

Вы должны явно определить, как строка будет декодироваться на обеих платформах, чтобы гарантировать, что обе строки будут декодировать одинаково точно.

...