我正在开发一个 API,它返回敏感数据需要某种握手,它将返回一个公钥供客户端在将信息发送到 API 之前对其进行加密。
对于 API,我使用了富有表现力的 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);
}