Я пытаюсь хешировать и подписывать пользовательские данные на iOS (14.4), отправлять их на мой сервер, а сервер проверяет хэш и подпись с помощью ранее загруженного открытого ключа (отправленного на пару ключей ...

0
grantley 28 Фев 2021 в 18:55

1 ответ

Лучший ответ

На самом деле я наткнулся на решение, проводя дополнительные исследования и экспериментируя при написании этого вопроса. Проблема, конечно, не имела ничего общего с ключами или алгоритмами, и все было связано с тем, как Apple хеширует объекты данных.

Я обнаружил аналогичную проблему, когда пытался определить, почему мои хэши не совпадали на стороне сервера с теми, которые были созданы на устройстве iOS. Пользовательские данные JSONEncoded хешируются и подписываются как объект данных base64Encoded, но мне неизвестно (и не в какой-либо документации, которую я мог обнаружить) iOS декодирует объект Data, хеширует необработанный объект и перекодирует его (поскольку это непрозрачный код возможно, это не совсем точно, но результат тот же). Поэтому при проверке хеширования пользовательских данных мне пришлось сначала base64decode кодировать объект, а затем выполнить хеширование. Я предполагал, что Apple подпишет закодированный объект как есть (чтобы не нарушить его целостность), но на самом деле, когда Apple создает дайджест перед подписанием, он хеширует декодированный необработанный объект и создает подпись на необработанном объекте.

Поэтому решение заключалось в том, чтобы снова base64decode кодировать объект перед его отправкой в ​​функцию openssl_verify.

Проверка хеша на сервере

public function is_hash_valid($payload) {

    $server_payload_hash = openssl_digest(base64_decode($payload["payload_json"]), "SHA512");
    $client_payload_hash = $payload["payload_hash"];

    if ($client_payload_hash != $server_payload_hash) {
        return false;
    }

    return true;
}

Проверка подписи на сервере

function is_signature_valid($data, $signature, $public_key) {
        
    $public_key = openssl_get_publickey($public_key);

    $ok = openssl_verify(base64_decode($data), base64_decode($signature), $public_key, "SHA512");
    if ($ok === 1) {
        return true;
    } else {
        return false;
    }
}

Обнаружив это и убедившись, что функция проверки openssl_verify и phpseclib работает правильно, я почти подумал об удалении вопроса полностью, но понял, что, если бы я обнаружил вопрос, похожий на этот, в моем исследовании, это могло бы сэкономить мне много времени. Надеюсь, это окажется полезным для всех, у кого есть подобная проблема.

2
grantley 28 Фев 2021 в 15:55