Использование только php для расшифровки гибрида Zend-Crypt - PullRequest
0 голосов
/ 19 ноября 2018

Я разрабатываю API, который для возврата конфиденциальных данных потребует своего рода рукопожатия, которое вернет клиенту открытый ключ для шифрования информации перед отправкой в ​​API.

Для API, которым я пользуюсь expressive zend, и для рукопожатия я использую модуль zend-crypt, а точнее гибридное шифрование.

рабочий процесс более или менее следующий:

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

Ниже приведен исходный код, который выполняет шифрование с открытым ключом:

$publicKeyStr = $request->getHeader('hello');

try {
    $publicKey = new \Zend\Crypt\PublicKey\Rsa\PublicKey(base64_decode($publicKeyStr[0]));

    $b64Key = base64_encode($this->crypto->getPublicKey());

    $hybridCrypt = new \Zend\Crypt\Hybrid();

    $serverPk = $hybridCrypt->encrypt($b64Key, $publicKey);   

    return new \Zend\Diactoros\Response\JsonResponse(array('hello'=>$serverPk));
} catch (\Zend\Crypt\PublicKey\Rsa\Exception\RuntimeException $ex) {
    return new \Zend\Diactoros\Response\EmptyResponse(\Fig\Http\Message\StatusCodeInterface::STATUS_UNAUTHORIZED);
}

Мой вопрос такой: Как мне расшифровать этот открытый ключ на клиенте, который не использует фреймворк, например, только на чистом PHP?

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

В настоящее время я выполняю интеграционное тестирование этого промежуточного программного обеспечения с использованием Codeception, и тестовый код выглядит так:

public function testPublicKeyAccess(ApiTester $I)
{
    $I->wantTo('Test if API return a valid public key');

    $I->am('Client');
    $I->amBearerAuthenticated($this->token);
    $I->haveHttpHeader('hello', base64_encode($this->publicKey));
    $I->sendGET('/handshake');


    $I->seeResponseCodeIs(200);
    $I->seeResponseContainsJson();

    $response = json_decode($I->grabResponse());

    list($encryptedKeys, $msg) = explode(';', $response->hello);
    $keysArr = explode(':', $encryptedKeys);
    $encryptedKey = base64_decode($keysArr[1]);

    // Decrypt $envKey, this works

    $envKey = '';
    openssl_private_decrypt($encryptedKey, $envKey,  $this->privateKey, OPENSSL_PKCS1_OAEP_PADDING);

    // Decrypt public key, this don't works
    $cipher = 'aes-256-cbc';
    $hmacSize = 46;
    $hmac = mb_substr($msg, 0, $hmacSize, '8bit');

    $ivSize = 32; //openssl_cipher_iv_length($cipher);
    $iv = mb_substr($msg, $hmacSize, $ivSize, '8bit'); // 64

    $cipherText = base64_decode(mb_substr($msg, $hmacSize+$ivSize, null, '8bit'));

    $serverKey = '';

    codecept_debug(var_dump($ivSize));

    openssl_open($cipherText, $serverKey, $envKey, $this->privateKey, $cipher, $ivSize);
    codecept_debug(var_dump($cipherText));
    codecept_debug(var_dump($serverKey));

    $I->assertRegExp('/-----BEGIN PUBLIC KEY-----(.*)-----END PUBLIC KEY-----/s', $serverKey);
}
...