我正在开发一个API,要返回敏感数据将需要某种握手,这将返回一个公钥,供客户端在将信息发送到API之前对其进行加密。
对于API,我使用表现力的zend并执行握手,我使用的是zend-crypt模块,更具体地说是Hybrid加密。
工作流程大致如下:
客户端应用程序将公共密钥发送到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);
}