Add a signer class for signing
Signed-off-by: Lukas Reschke <lukas@statuscode.ch>
This commit is contained in:
parent
a32d6e481f
commit
fb91bf6a5b
|
@ -23,11 +23,23 @@ $dispatcher = \OC::$server->getEventDispatcher();
|
|||
|
||||
$dispatcher->addListener('OC\AccountManager::userUpdated', function(\Symfony\Component\EventDispatcher\GenericEvent $event) {
|
||||
$user = $event->getSubject();
|
||||
|
||||
$keyManager = new \OC\Security\IdentityProof\Manager(
|
||||
\OC::$server->getAppDataDir('identityproof'),
|
||||
\OC::$server->getCrypto()
|
||||
);
|
||||
$updateLookupServer = new \OCA\LookupServerConnector\UpdateLookupServer(
|
||||
new \OC\Accounts\AccountManager(\OC::$server->getDatabaseConnection(), \OC::$server->getEventDispatcher()),
|
||||
\OC::$server->getConfig(),
|
||||
\OC::$server->getSecureRandom(),
|
||||
\OC::$server->getHTTPClientService()
|
||||
\OC::$server->getHTTPClientService(),
|
||||
$keyManager,
|
||||
new \OC\Security\IdentityProof\Signer(
|
||||
$keyManager,
|
||||
new \OC\AppFramework\Utility\TimeFactory(),
|
||||
\OC::$server->getURLGenerator(),
|
||||
\OC::$server->getUserManager()
|
||||
)
|
||||
);
|
||||
$updateLookupServer->userUpdated($user);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org>
|
||||
* @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
|
@ -19,11 +20,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace OCA\LookupServerConnector;
|
||||
|
||||
|
||||
use OC\Accounts\AccountManager;
|
||||
use OC\Security\IdentityProof\Manager;
|
||||
use OC\Security\IdentityProof\Signer;
|
||||
use OCP\Http\Client\IClientService;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUser;
|
||||
|
@ -35,45 +36,48 @@ use OCP\Security\ISecureRandom;
|
|||
* @package OCA\LookupServerConnector
|
||||
*/
|
||||
class UpdateLookupServer {
|
||||
|
||||
/** @var AccountManager */
|
||||
private $accountManager;
|
||||
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
/** @var ISecureRandom */
|
||||
private $secureRandom;
|
||||
|
||||
/** @var IClientService */
|
||||
private $clientService;
|
||||
|
||||
/** @var Manager */
|
||||
private $keyManager;
|
||||
/** @var Signer */
|
||||
private $signer;
|
||||
/** @var string URL point to lookup server */
|
||||
private $lookupServer = 'http://192.168.56.102';
|
||||
private $lookupServer = 'http://192.168.176.105/lookup-server/server/';
|
||||
|
||||
/**
|
||||
* UpdateLookupServer constructor.
|
||||
*
|
||||
* @param AccountManager $accountManager
|
||||
* @param IConfig $config
|
||||
* @param ISecureRandom $secureRandom
|
||||
* @param IClientService $clientService
|
||||
* @param Manager $manager
|
||||
* @param Signer $signer
|
||||
*/
|
||||
public function __construct(AccountManager $accountManager,
|
||||
IConfig $config,
|
||||
ISecureRandom $secureRandom,
|
||||
IClientService $clientService) {
|
||||
IClientService $clientService,
|
||||
Manager $manager,
|
||||
Signer $signer) {
|
||||
$this->accountManager = $accountManager;
|
||||
$this->config = $config;
|
||||
$this->secureRandom = $secureRandom;
|
||||
$this->clientService = $clientService;
|
||||
$this->keyManager = $manager;
|
||||
$this->signer = $signer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IUser $user
|
||||
*/
|
||||
public function userUpdated(IUser $user) {
|
||||
$userData = $this->accountManager->getUser($user);
|
||||
$authKey = $this->config->getUserValue($user->getUID(), 'lookup_server_connector', 'authKey');
|
||||
|
||||
$publicData = [];
|
||||
|
||||
foreach ($userData as $key => $data) {
|
||||
|
@ -83,13 +87,15 @@ class UpdateLookupServer {
|
|||
}
|
||||
|
||||
if (empty($publicData) && !empty($authKey)) {
|
||||
$this->removeFromLookupServer($user, $authKey);
|
||||
$this->removeFromLookupServer($user);
|
||||
} else {
|
||||
$this->sendToLookupServer($user, $publicData, $authKey);
|
||||
$this->sendToLookupServer($user, $publicData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: FIXME. Implement removal from lookup server.
|
||||
*
|
||||
* remove user from lookup server
|
||||
*
|
||||
* @param IUser $user
|
||||
|
@ -103,56 +109,25 @@ class UpdateLookupServer {
|
|||
*
|
||||
* @param IUser $user
|
||||
* @param array $publicData
|
||||
* @param string $authKey
|
||||
*/
|
||||
protected function sendToLookupServer(IUser $user, $publicData, $authKey) {
|
||||
if (empty($authKey)) {
|
||||
$authKey = $this->secureRandom->generate(16);
|
||||
$this->sendNewRecord($user, $publicData, $authKey);
|
||||
$this->config->setUserValue($user->getUID(), 'lookup_server_connector', 'authKey', $authKey);
|
||||
} else {
|
||||
$this->updateExistingRecord($user, $publicData, $authKey);
|
||||
}
|
||||
}
|
||||
|
||||
protected function sendNewRecord(IUser $user, $publicData, $authKey) {
|
||||
$httpClient = $this->clientService->newClient();
|
||||
$response = $httpClient->post($this->lookupServer,
|
||||
[
|
||||
'body' => [
|
||||
'key' => $authKey,
|
||||
'federationid' => $publicData[$user->getCloudId()],
|
||||
protected function sendToLookupServer(IUser $user, array $publicData) {
|
||||
$dataArray = [
|
||||
'federationId' => $user->getCloudId(),
|
||||
'name' => isset($publicData[AccountManager::PROPERTY_DISPLAYNAME]) ? $publicData[AccountManager::PROPERTY_DISPLAYNAME]['value'] : '',
|
||||
'email' => isset($publicData[AccountManager::PROPERTY_EMAIL]) ? $publicData[AccountManager::PROPERTY_EMAIL]['value'] : '',
|
||||
'address' => isset($publicData[AccountManager::PROPERTY_ADDRESS]) ? $publicData[AccountManager::PROPERTY_ADDRESS]['value'] : '',
|
||||
'website' => isset($publicData[AccountManager::PROPERTY_WEBSITE]) ? $publicData[AccountManager::PROPERTY_WEBSITE]['value'] : '',
|
||||
'twitter' => isset($publicData[AccountManager::PROPERTY_TWITTER]) ? $publicData[AccountManager::PROPERTY_TWITTER]['value'] : '',
|
||||
'phone' => isset($publicData[AccountManager::PROPERTY_PHONE]) ? $publicData[AccountManager::PROPERTY_PHONE]['value'] : '',
|
||||
],
|
||||
'timeout' => 3,
|
||||
'connect_timeout' => 3,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
protected function updateExistingRecord(IUser $user, $publicData, $authKey) {
|
||||
];
|
||||
$dataArray = $this->signer->sign('lookupserver', $dataArray, $user);
|
||||
$httpClient = $this->clientService->newClient();
|
||||
$httpClient->put($this->lookupServer,
|
||||
$httpClient->post($this->lookupServer,
|
||||
[
|
||||
'body' => [
|
||||
'key' => $authKey,
|
||||
'federationid' => $publicData[$user->getCloudId()],
|
||||
'name' => isset($publicData[AccountManager::PROPERTY_DISPLAYNAME]) ? $publicData[AccountManager::PROPERTY_DISPLAYNAME]['value'] : '',
|
||||
'email' => isset($publicData[AccountManager::PROPERTY_EMAIL]) ? $publicData[AccountManager::PROPERTY_EMAIL]['value'] : '',
|
||||
'address' => isset($publicData[AccountManager::PROPERTY_ADDRESS]) ? $publicData[AccountManager::PROPERTY_ADDRESS]['value'] : '',
|
||||
'website' => isset($publicData[AccountManager::PROPERTY_WEBSITE]) ? $publicData[AccountManager::PROPERTY_WEBSITE]['value'] : '',
|
||||
'twitter' => isset($publicData[AccountManager::PROPERTY_TWITTER]) ? $publicData[AccountManager::PROPERTY_TWITTER]['value'] : '',
|
||||
'phone' => isset($publicData[AccountManager::PROPERTY_PHONE]) ? $publicData[AccountManager::PROPERTY_PHONE]['value'] : '',
|
||||
],
|
||||
'body' => $dataArray,
|
||||
'timeout' => 3,
|
||||
'connect_timeout' => 3,
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ class OCSController extends \OCP\AppFramework\OCSController {
|
|||
public function getIdentityProof($cloudId) {
|
||||
$userObject = $this->userManager->get($cloudId);
|
||||
|
||||
if($cloudId !== null) {
|
||||
if($userObject !== null) {
|
||||
$key = $this->keyManager->getKey($userObject);
|
||||
$data = [
|
||||
'public' => $key->getPublic(),
|
||||
|
@ -159,6 +159,6 @@ class OCSController extends \OCP\AppFramework\OCSController {
|
|||
return new DataResponse($data);
|
||||
}
|
||||
|
||||
return new DataResponse(101);
|
||||
return new DataResponse('User not found', 404);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,13 +42,12 @@ class Manager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Generate a key for $user
|
||||
* Note: If a key already exists it will be overwritten
|
||||
* Calls the openssl functions to generate a public and private key.
|
||||
* In a separate function for unit testing purposes.
|
||||
*
|
||||
* @param IUser $user
|
||||
* @return Key
|
||||
* @return array [$publicKey, $privateKey]
|
||||
*/
|
||||
public function generateKey(IUser $user) {
|
||||
protected function generateKeyPair() {
|
||||
$config = [
|
||||
'digest_alg' => 'sha512',
|
||||
'private_key_bits' => 2048,
|
||||
|
@ -62,10 +61,27 @@ class Manager {
|
|||
$publicKey = openssl_pkey_get_details($res);
|
||||
$publicKey = $publicKey['key'];
|
||||
|
||||
return [$publicKey, $privateKey];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a key for $user
|
||||
* Note: If a key already exists it will be overwritten
|
||||
*
|
||||
* @param IUser $user
|
||||
* @return Key
|
||||
*/
|
||||
protected function generateKey(IUser $user) {
|
||||
list($publicKey, $privateKey) = $this->generateKeyPair();
|
||||
|
||||
// Write the private and public key to the disk
|
||||
$this->appData->getFolder($user->getUID())->newFile('private')
|
||||
try {
|
||||
$this->appData->newFolder($user->getUID());
|
||||
} catch (\Exception $e) {}
|
||||
$folder = $this->appData->getFolder($user->getUID());
|
||||
$folder->newFile('private')
|
||||
->putContent($this->crypto->encrypt($privateKey));
|
||||
$this->appData->getFolder($user->getUID())->newFile('public')
|
||||
$folder->newFile('public')
|
||||
->putContent($publicKey);
|
||||
|
||||
return new Key($publicKey, $privateKey);
|
||||
|
@ -79,8 +95,11 @@ class Manager {
|
|||
*/
|
||||
public function getKey(IUser $user) {
|
||||
try {
|
||||
$privateKey = $this->crypto->decrypt($this->appData->getFolder($user->getUID())->getFile('private')->getContent());
|
||||
$publicKey = $this->appData->getFolder($user->getUID())->getFile('public')->getContent();
|
||||
$folder = $this->appData->getFolder($user->getUID());
|
||||
$privateKey = $this->crypto->decrypt(
|
||||
$folder->getFile('private')->getContent()
|
||||
);
|
||||
$publicKey = $folder->getFile('public')->getContent();
|
||||
return new Key($publicKey, $privateKey);
|
||||
} catch (\Exception $e) {
|
||||
return $this->generateKey($user);
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Security\IdentityProof;
|
||||
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
|
||||
class Signer {
|
||||
/** @var Manager */
|
||||
private $keyManager;
|
||||
/** @var ITimeFactory */
|
||||
private $timeFactory;
|
||||
/** @var IURLGenerator */
|
||||
private $urlGenerator;
|
||||
/** @var IUserManager */
|
||||
private $userManager;
|
||||
|
||||
/**
|
||||
* @param Manager $keyManager
|
||||
* @param ITimeFactory $timeFactory
|
||||
* @param IURLGenerator $urlGenerator
|
||||
* @param IUserManager $userManager
|
||||
*/
|
||||
public function __construct(Manager $keyManager,
|
||||
ITimeFactory $timeFactory,
|
||||
IURLGenerator $urlGenerator,
|
||||
IUserManager $userManager) {
|
||||
$this->keyManager = $keyManager;
|
||||
$this->timeFactory = $timeFactory;
|
||||
$this->userManager = $userManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a signed blob for $data
|
||||
*
|
||||
* @param string $type
|
||||
* @param array $data
|
||||
* @param IUser $user
|
||||
* @return array ['message', 'signature']
|
||||
*/
|
||||
public function sign($type, array $data, IUser $user) {
|
||||
$privateKey = $this->keyManager->getKey($user)->getPrivate();
|
||||
$data = [
|
||||
'data' => $data,
|
||||
'type' => $type,
|
||||
'signer' => $user->getCloudId(),
|
||||
'timestamp' => $this->timeFactory->getTime(),
|
||||
];
|
||||
openssl_sign(json_encode($data), $signature, $privateKey, OPENSSL_ALGO_SHA512);
|
||||
|
||||
return [
|
||||
'message' => $data,
|
||||
'signature' => base64_encode($signature),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
private function removeProtocolFromUrl($url) {
|
||||
if (strpos($url, 'https://') === 0) {
|
||||
return substr($url, strlen('https://'));
|
||||
} else if (strpos($url, 'http://') === 0) {
|
||||
return substr($url, strlen('http://'));
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the data is signed properly
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function verify(array $data) {
|
||||
if(isset($data['message'])
|
||||
&& isset($data['signature'])
|
||||
&& isset($data['message']['signer'])
|
||||
) {
|
||||
$server = $this->urlGenerator->getAbsoluteURL('/');
|
||||
$postfix = strlen('@' . rtrim($this->removeProtocolFromUrl($server), '/'));
|
||||
$userId = substr($data['message']['signer'], -$postfix);
|
||||
|
||||
$user = $this->userManager->get($userId);
|
||||
if($user !== null) {
|
||||
$key = $this->keyManager->getKey($user);
|
||||
return (bool)openssl_verify(
|
||||
json_encode($data['message']),
|
||||
base64_decode($data['signature']),
|
||||
$key->getPublic()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -524,12 +524,18 @@ class UsersController extends Controller {
|
|||
* @return DataResponse
|
||||
*/
|
||||
public function setUserSettings($avatarScope,
|
||||
$displayname, $displaynameScope,
|
||||
$phone, $phoneScope,
|
||||
$email, $emailScope,
|
||||
$website, $websiteScope,
|
||||
$address, $addressScope,
|
||||
$twitter, $twitterScope
|
||||
$displayname,
|
||||
$displaynameScope,
|
||||
$phone,
|
||||
$phoneScope,
|
||||
$email,
|
||||
$emailScope,
|
||||
$website,
|
||||
$websiteScope,
|
||||
$address,
|
||||
$addressScope,
|
||||
$twitter,
|
||||
$twitterScope
|
||||
) {
|
||||
|
||||
|
||||
|
|
|
@ -422,6 +422,7 @@ class AppTest extends \Test\TestCase {
|
|||
'appforgroup2',
|
||||
'dav',
|
||||
'federatedfilesharing',
|
||||
'lookup_server_connector',
|
||||
'provisioning_api',
|
||||
'twofactor_backupcodes',
|
||||
'workflowengine',
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Test\Security;
|
||||
|
||||
use OC\Security\IdentityProof\Key;
|
||||
use OC\Security\IdentityProof\Manager;
|
||||
use OCP\Files\IAppData;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
use OCP\Files\SimpleFS\ISimpleFolder;
|
||||
use OCP\IUser;
|
||||
use OCP\Security\ICrypto;
|
||||
use Test\TestCase;
|
||||
|
||||
class ManagerTest extends TestCase {
|
||||
/** @var IAppData|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $appData;
|
||||
/** @var ICrypto|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $crypto;
|
||||
/** @var Manager|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $manager;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->appData = $this->createMock(IAppData::class);
|
||||
$this->crypto = $this->createMock(ICrypto::class);
|
||||
$this->manager = $this->getMockBuilder(Manager::class)
|
||||
->setConstructorArgs([
|
||||
$this->appData,
|
||||
$this->crypto
|
||||
])
|
||||
->setMethods(['generateKeyPair'])
|
||||
->getMock();
|
||||
}
|
||||
|
||||
public function testGetKeyWithExistingKey() {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user
|
||||
->expects($this->once())
|
||||
->method('getUID')
|
||||
->willReturn('MyUid');
|
||||
$folder = $this->createMock(ISimpleFolder::class);
|
||||
$privateFile = $this->createMock(ISimpleFile::class);
|
||||
$privateFile
|
||||
->expects($this->once())
|
||||
->method('getContent')
|
||||
->willReturn('EncryptedPrivateKey');
|
||||
$publicFile = $this->createMock(ISimpleFile::class);
|
||||
$publicFile
|
||||
->expects($this->once())
|
||||
->method('getContent')
|
||||
->willReturn('MyPublicKey');
|
||||
$this->crypto
|
||||
->expects($this->once())
|
||||
->method('decrypt')
|
||||
->with('EncryptedPrivateKey')
|
||||
->willReturn('MyPrivateKey');
|
||||
$folder
|
||||
->expects($this->at(0))
|
||||
->method('getFile')
|
||||
->with('private')
|
||||
->willReturn($privateFile);
|
||||
$folder
|
||||
->expects($this->at(1))
|
||||
->method('getFile')
|
||||
->with('public')
|
||||
->willReturn($publicFile);
|
||||
$this->appData
|
||||
->expects($this->once())
|
||||
->method('getFolder')
|
||||
->with('MyUid')
|
||||
->willReturn($folder);
|
||||
|
||||
$expected = new Key('MyPublicKey', 'MyPrivateKey');
|
||||
$this->assertEquals($expected, $this->manager->getKey($user));
|
||||
}
|
||||
|
||||
public function testGetKeyWithNotExistingKey() {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user
|
||||
->expects($this->exactly(3))
|
||||
->method('getUID')
|
||||
->willReturn('MyUid');
|
||||
$this->appData
|
||||
->expects($this->at(0))
|
||||
->method('getFolder')
|
||||
->with('MyUid')
|
||||
->willThrowException(new \Exception());
|
||||
$this->manager
|
||||
->expects($this->once())
|
||||
->method('generateKeyPair')
|
||||
->willReturn(['MyNewPublicKey', 'MyNewPrivateKey']);
|
||||
$this->appData
|
||||
->expects($this->at(1))
|
||||
->method('newFolder')
|
||||
->with('MyUid');
|
||||
$folder = $this->createMock(ISimpleFolder::class);
|
||||
$this->crypto
|
||||
->expects($this->once())
|
||||
->method('encrypt')
|
||||
->with('MyNewPrivateKey')
|
||||
->willReturn('MyNewEncryptedPrivateKey');
|
||||
$privateFile = $this->createMock(ISimpleFile::class);
|
||||
$privateFile
|
||||
->expects($this->once())
|
||||
->method('putContent')
|
||||
->with('MyNewEncryptedPrivateKey');
|
||||
$publicFile = $this->createMock(ISimpleFile::class);
|
||||
$publicFile
|
||||
->expects($this->once())
|
||||
->method('putContent')
|
||||
->with('MyNewPublicKey');
|
||||
$folder
|
||||
->expects($this->at(0))
|
||||
->method('newFile')
|
||||
->with('private')
|
||||
->willReturn($privateFile);
|
||||
$folder
|
||||
->expects($this->at(1))
|
||||
->method('newFile')
|
||||
->with('public')
|
||||
->willReturn($publicFile);
|
||||
$this->appData
|
||||
->expects($this->at(2))
|
||||
->method('getFolder')
|
||||
->with('MyUid')
|
||||
->willReturn($folder);
|
||||
|
||||
|
||||
$expected = new Key('MyNewPublicKey', 'MyNewPrivateKey');
|
||||
$this->assertEquals($expected, $this->manager->getKey($user));
|
||||
}
|
||||
|
||||
public function testGenerateKeyPair() {
|
||||
$manager = new Manager(
|
||||
$this->appData,
|
||||
$this->crypto
|
||||
);
|
||||
$data = 'MyTestData';
|
||||
|
||||
list($resultPublicKey, $resultPrivateKey) = $this->invokePrivate($manager, 'generateKeyPair');
|
||||
openssl_sign($data, $signature, $resultPrivateKey);
|
||||
$details = openssl_pkey_get_details(openssl_pkey_get_public($resultPublicKey));
|
||||
|
||||
$this->assertSame(1, openssl_verify($data, $signature, $resultPublicKey));
|
||||
$this->assertSame(2048, $details['bits']);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue