You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

765 lines
19 KiB

11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Bjoern Schiessle <bjoern@schiessle.org>
  7. * @author Björn Schießle <bjoern@schiessle.org>
  8. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  9. * @author Clark Tomlinson <fallen013@gmail.com>
  10. * @author Julius Härtl <jus@bitgrid.net>
  11. * @author Lukas Reschke <lukas@statuscode.ch>
  12. * @author Morris Jobke <hey@morrisjobke.de>
  13. * @author Roeland Jago Douma <roeland@famdouma.nl>
  14. * @author Thomas Müller <thomas.mueller@tmit.eu>
  15. * @author Vincent Petry <vincent@nextcloud.com>
  16. *
  17. * @license AGPL-3.0
  18. *
  19. * This code is free software: you can redistribute it and/or modify
  20. * it under the terms of the GNU Affero General Public License, version 3,
  21. * as published by the Free Software Foundation.
  22. *
  23. * This program is distributed in the hope that it will be useful,
  24. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. * GNU Affero General Public License for more details.
  27. *
  28. * You should have received a copy of the GNU Affero General Public License, version 3,
  29. * along with this program. If not, see <http://www.gnu.org/licenses/>
  30. *
  31. */
  32. namespace OCA\Encryption;
  33. use OC\Encryption\Exceptions\DecryptionFailedException;
  34. use OC\Files\View;
  35. use OCA\Encryption\Crypto\Crypt;
  36. use OCA\Encryption\Crypto\Encryption;
  37. use OCA\Encryption\Exceptions\PrivateKeyMissingException;
  38. use OCA\Encryption\Exceptions\PublicKeyMissingException;
  39. use OCP\Encryption\Keys\IStorage;
  40. use OCP\IConfig;
  41. use OCP\ILogger;
  42. use OCP\IUserSession;
  43. use OCP\Lock\ILockingProvider;
  44. class KeyManager {
  45. /**
  46. * @var Session
  47. */
  48. protected $session;
  49. /**
  50. * @var IStorage
  51. */
  52. private $keyStorage;
  53. /**
  54. * @var Crypt
  55. */
  56. private $crypt;
  57. /**
  58. * @var string
  59. */
  60. private $recoveryKeyId;
  61. /**
  62. * @var string
  63. */
  64. private $publicShareKeyId;
  65. /**
  66. * @var string
  67. */
  68. private $masterKeyId;
  69. /**
  70. * @var string UserID
  71. */
  72. private $keyId;
  73. /**
  74. * @var string
  75. */
  76. private $publicKeyId = 'publicKey';
  77. /**
  78. * @var string
  79. */
  80. private $privateKeyId = 'privateKey';
  81. /**
  82. * @var string
  83. */
  84. private $shareKeyId = 'shareKey';
  85. /**
  86. * @var string
  87. */
  88. private $fileKeyId = 'fileKey';
  89. /**
  90. * @var IConfig
  91. */
  92. private $config;
  93. /**
  94. * @var ILogger
  95. */
  96. private $log;
  97. /**
  98. * @var Util
  99. */
  100. private $util;
  101. /**
  102. * @var ILockingProvider
  103. */
  104. private $lockingProvider;
  105. /**
  106. * @param IStorage $keyStorage
  107. * @param Crypt $crypt
  108. * @param IConfig $config
  109. * @param IUserSession $userSession
  110. * @param Session $session
  111. * @param ILogger $log
  112. * @param Util $util
  113. */
  114. public function __construct(
  115. IStorage $keyStorage,
  116. Crypt $crypt,
  117. IConfig $config,
  118. IUserSession $userSession,
  119. Session $session,
  120. ILogger $log,
  121. Util $util,
  122. ILockingProvider $lockingProvider
  123. ) {
  124. $this->util = $util;
  125. $this->session = $session;
  126. $this->keyStorage = $keyStorage;
  127. $this->crypt = $crypt;
  128. $this->config = $config;
  129. $this->log = $log;
  130. $this->lockingProvider = $lockingProvider;
  131. $this->recoveryKeyId = $this->config->getAppValue('encryption',
  132. 'recoveryKeyId');
  133. if (empty($this->recoveryKeyId)) {
  134. $this->recoveryKeyId = 'recoveryKey_' . substr(md5(time()), 0, 8);
  135. $this->config->setAppValue('encryption',
  136. 'recoveryKeyId',
  137. $this->recoveryKeyId);
  138. }
  139. $this->publicShareKeyId = $this->config->getAppValue('encryption',
  140. 'publicShareKeyId');
  141. if (empty($this->publicShareKeyId)) {
  142. $this->publicShareKeyId = 'pubShare_' . substr(md5(time()), 0, 8);
  143. $this->config->setAppValue('encryption', 'publicShareKeyId', $this->publicShareKeyId);
  144. }
  145. $this->masterKeyId = $this->config->getAppValue('encryption',
  146. 'masterKeyId');
  147. if (empty($this->masterKeyId)) {
  148. $this->masterKeyId = 'master_' . substr(md5(time()), 0, 8);
  149. $this->config->setAppValue('encryption', 'masterKeyId', $this->masterKeyId);
  150. }
  151. $this->keyId = $userSession->isLoggedIn() ? $userSession->getUser()->getUID() : false;
  152. $this->log = $log;
  153. }
  154. /**
  155. * check if key pair for public link shares exists, if not we create one
  156. */
  157. public function validateShareKey() {
  158. $shareKey = $this->getPublicShareKey();
  159. if (empty($shareKey)) {
  160. $this->lockingProvider->acquireLock('encryption-generateSharedKey', ILockingProvider::LOCK_EXCLUSIVE, 'Encryption: shared key generation');
  161. try {
  162. $keyPair = $this->crypt->createKeyPair();
  163. // Save public key
  164. $this->keyStorage->setSystemUserKey(
  165. $this->publicShareKeyId . '.' . $this->publicKeyId, $keyPair['publicKey'],
  166. Encryption::ID);
  167. // Encrypt private key empty passphrase
  168. $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], '');
  169. $header = $this->crypt->generateHeader();
  170. $this->setSystemPrivateKey($this->publicShareKeyId, $header . $encryptedKey);
  171. } catch (\Throwable $e) {
  172. $this->lockingProvider->releaseLock('encryption-generateSharedKey', ILockingProvider::LOCK_EXCLUSIVE);
  173. throw $e;
  174. }
  175. $this->lockingProvider->releaseLock('encryption-generateSharedKey', ILockingProvider::LOCK_EXCLUSIVE);
  176. }
  177. }
  178. /**
  179. * check if a key pair for the master key exists, if not we create one
  180. */
  181. public function validateMasterKey() {
  182. if ($this->util->isMasterKeyEnabled() === false) {
  183. return;
  184. }
  185. $publicMasterKey = $this->getPublicMasterKey();
  186. $privateMasterKey = $this->getPrivateMasterKey();
  187. if (empty($publicMasterKey) && empty($privateMasterKey)) {
  188. // There could be a race condition here if two requests would trigger
  189. // the generation the second one would enter the key generation as long
  190. // as the first one didn't write the key to the keystorage yet
  191. $this->lockingProvider->acquireLock('encryption-generateMasterKey', ILockingProvider::LOCK_EXCLUSIVE, 'Encryption: master key generation');
  192. try {
  193. $keyPair = $this->crypt->createKeyPair();
  194. // Save public key
  195. $this->keyStorage->setSystemUserKey(
  196. $this->masterKeyId . '.' . $this->publicKeyId, $keyPair['publicKey'],
  197. Encryption::ID);
  198. // Encrypt private key with system password
  199. $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $this->getMasterKeyPassword(), $this->masterKeyId);
  200. $header = $this->crypt->generateHeader();
  201. $this->setSystemPrivateKey($this->masterKeyId, $header . $encryptedKey);
  202. } catch (\Throwable $e) {
  203. $this->lockingProvider->releaseLock('encryption-generateMasterKey', ILockingProvider::LOCK_EXCLUSIVE);
  204. throw $e;
  205. }
  206. $this->lockingProvider->releaseLock('encryption-generateMasterKey', ILockingProvider::LOCK_EXCLUSIVE);
  207. } elseif (empty($publicMasterKey)) {
  208. $this->log->error('A private master key is available but the public key could not be found. This should never happen.');
  209. return;
  210. } elseif (empty($privateMasterKey)) {
  211. $this->log->error('A public master key is available but the private key could not be found. This should never happen.');
  212. return;
  213. }
  214. if (!$this->session->isPrivateKeySet()) {
  215. $masterKey = $this->getSystemPrivateKey($this->masterKeyId);
  216. $decryptedMasterKey = $this->crypt->decryptPrivateKey($masterKey, $this->getMasterKeyPassword(), $this->masterKeyId);
  217. $this->session->setPrivateKey($decryptedMasterKey);
  218. }
  219. // after the encryption key is available we are ready to go
  220. $this->session->setStatus(Session::INIT_SUCCESSFUL);
  221. }
  222. /**
  223. * @return bool
  224. */
  225. public function recoveryKeyExists() {
  226. $key = $this->getRecoveryKey();
  227. return !empty($key);
  228. }
  229. /**
  230. * get recovery key
  231. *
  232. * @return string
  233. */
  234. public function getRecoveryKey() {
  235. return $this->keyStorage->getSystemUserKey($this->recoveryKeyId . '.' . $this->publicKeyId, Encryption::ID);
  236. }
  237. /**
  238. * get recovery key ID
  239. *
  240. * @return string
  241. */
  242. public function getRecoveryKeyId() {
  243. return $this->recoveryKeyId;
  244. }
  245. /**
  246. * @param string $password
  247. * @return bool
  248. */
  249. public function checkRecoveryPassword($password) {
  250. $recoveryKey = $this->keyStorage->getSystemUserKey($this->recoveryKeyId . '.' . $this->privateKeyId, Encryption::ID);
  251. $decryptedRecoveryKey = $this->crypt->decryptPrivateKey($recoveryKey, $password);
  252. if ($decryptedRecoveryKey) {
  253. return true;
  254. }
  255. return false;
  256. }
  257. /**
  258. * @param string $uid
  259. * @param string $password
  260. * @param array $keyPair
  261. * @return bool
  262. */
  263. public function storeKeyPair($uid, $password, $keyPair) {
  264. // Save Public Key
  265. $this->setPublicKey($uid, $keyPair['publicKey']);
  266. $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $password, $uid);
  267. $header = $this->crypt->generateHeader();
  268. if ($encryptedKey) {
  269. $this->setPrivateKey($uid, $header . $encryptedKey);
  270. return true;
  271. }
  272. return false;
  273. }
  274. /**
  275. * @param string $password
  276. * @param array $keyPair
  277. * @return bool
  278. */
  279. public function setRecoveryKey($password, $keyPair) {
  280. // Save Public Key
  281. $this->keyStorage->setSystemUserKey($this->getRecoveryKeyId().
  282. '.' . $this->publicKeyId,
  283. $keyPair['publicKey'],
  284. Encryption::ID);
  285. $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $password);
  286. $header = $this->crypt->generateHeader();
  287. if ($encryptedKey) {
  288. $this->setSystemPrivateKey($this->getRecoveryKeyId(), $header . $encryptedKey);
  289. return true;
  290. }
  291. return false;
  292. }
  293. /**
  294. * @param $userId
  295. * @param $key
  296. * @return bool
  297. */
  298. public function setPublicKey($userId, $key) {
  299. return $this->keyStorage->setUserKey($userId, $this->publicKeyId, $key, Encryption::ID);
  300. }
  301. /**
  302. * @param $userId
  303. * @param string $key
  304. * @return bool
  305. */
  306. public function setPrivateKey($userId, $key) {
  307. return $this->keyStorage->setUserKey($userId,
  308. $this->privateKeyId,
  309. $key,
  310. Encryption::ID);
  311. }
  312. /**
  313. * write file key to key storage
  314. *
  315. * @param string $path
  316. * @param string $key
  317. * @return boolean
  318. */
  319. public function setFileKey($path, $key) {
  320. return $this->keyStorage->setFileKey($path, $this->fileKeyId, $key, Encryption::ID);
  321. }
  322. /**
  323. * set all file keys (the file key and the corresponding share keys)
  324. *
  325. * @param string $path
  326. * @param array $keys
  327. */
  328. public function setAllFileKeys($path, $keys) {
  329. $this->setFileKey($path, $keys['data']);
  330. foreach ($keys['keys'] as $uid => $keyFile) {
  331. $this->setShareKey($path, $uid, $keyFile);
  332. }
  333. }
  334. /**
  335. * write share key to the key storage
  336. *
  337. * @param string $path
  338. * @param string $uid
  339. * @param string $key
  340. * @return boolean
  341. */
  342. public function setShareKey($path, $uid, $key) {
  343. $keyId = $uid . '.' . $this->shareKeyId;
  344. return $this->keyStorage->setFileKey($path, $keyId, $key, Encryption::ID);
  345. }
  346. /**
  347. * Decrypt private key and store it
  348. *
  349. * @param string $uid user id
  350. * @param string $passPhrase users password
  351. * @return boolean
  352. */
  353. public function init($uid, $passPhrase) {
  354. $this->session->setStatus(Session::INIT_EXECUTED);
  355. try {
  356. if ($this->util->isMasterKeyEnabled()) {
  357. $uid = $this->getMasterKeyId();
  358. $passPhrase = $this->getMasterKeyPassword();
  359. $privateKey = $this->getSystemPrivateKey($uid);
  360. } else {
  361. $privateKey = $this->getPrivateKey($uid);
  362. }
  363. $privateKey = $this->crypt->decryptPrivateKey($privateKey, $passPhrase, $uid);
  364. } catch (PrivateKeyMissingException $e) {
  365. return false;
  366. } catch (DecryptionFailedException $e) {
  367. return false;
  368. } catch (\Exception $e) {
  369. $this->log->logException($e, [
  370. 'message' => 'Could not decrypt the private key from user "' . $uid . '"" during login. Assume password change on the user back-end.',
  371. 'level' => ILogger::WARN,
  372. 'app' => 'encryption',
  373. ]);
  374. return false;
  375. }
  376. if ($privateKey) {
  377. $this->session->setPrivateKey($privateKey);
  378. $this->session->setStatus(Session::INIT_SUCCESSFUL);
  379. return true;
  380. }
  381. return false;
  382. }
  383. /**
  384. * @param $userId
  385. * @return string
  386. * @throws PrivateKeyMissingException
  387. */
  388. public function getPrivateKey($userId) {
  389. $privateKey = $this->keyStorage->getUserKey($userId,
  390. $this->privateKeyId, Encryption::ID);
  391. if (strlen($privateKey) !== 0) {
  392. return $privateKey;
  393. }
  394. throw new PrivateKeyMissingException($userId);
  395. }
  396. /**
  397. * @param string $path
  398. * @param $uid
  399. * @return string
  400. */
  401. public function getFileKey($path, $uid) {
  402. if ($uid === '') {
  403. $uid = null;
  404. }
  405. $publicAccess = is_null($uid);
  406. $encryptedFileKey = $this->keyStorage->getFileKey($path, $this->fileKeyId, Encryption::ID);
  407. if (empty($encryptedFileKey)) {
  408. return '';
  409. }
  410. if ($this->util->isMasterKeyEnabled()) {
  411. $uid = $this->getMasterKeyId();
  412. $shareKey = $this->getShareKey($path, $uid);
  413. if ($publicAccess) {
  414. $privateKey = $this->getSystemPrivateKey($uid);
  415. $privateKey = $this->crypt->decryptPrivateKey($privateKey, $this->getMasterKeyPassword(), $uid);
  416. } else {
  417. // when logged in, the master key is already decrypted in the session
  418. $privateKey = $this->session->getPrivateKey();
  419. }
  420. } elseif ($publicAccess) {
  421. // use public share key for public links
  422. $uid = $this->getPublicShareKeyId();
  423. $shareKey = $this->getShareKey($path, $uid);
  424. $privateKey = $this->keyStorage->getSystemUserKey($this->publicShareKeyId . '.' . $this->privateKeyId, Encryption::ID);
  425. $privateKey = $this->crypt->decryptPrivateKey($privateKey);
  426. } else {
  427. $shareKey = $this->getShareKey($path, $uid);
  428. $privateKey = $this->session->getPrivateKey();
  429. }
  430. if ($encryptedFileKey && $shareKey && $privateKey) {
  431. return $this->crypt->multiKeyDecrypt($encryptedFileKey,
  432. $shareKey,
  433. $privateKey);
  434. }
  435. return '';
  436. }
  437. /**
  438. * Get the current version of a file
  439. *
  440. * @param string $path
  441. * @param View $view
  442. * @return int
  443. */
  444. public function getVersion($path, View $view) {
  445. $fileInfo = $view->getFileInfo($path);
  446. if ($fileInfo === false) {
  447. return 0;
  448. }
  449. return $fileInfo->getEncryptedVersion();
  450. }
  451. /**
  452. * Set the current version of a file
  453. *
  454. * @param string $path
  455. * @param int $version
  456. * @param View $view
  457. */
  458. public function setVersion($path, $version, View $view) {
  459. $fileInfo = $view->getFileInfo($path);
  460. if ($fileInfo !== false) {
  461. $cache = $fileInfo->getStorage()->getCache();
  462. $cache->update($fileInfo->getId(), ['encrypted' => $version, 'encryptedVersion' => $version]);
  463. }
  464. }
  465. /**
  466. * get the encrypted file key
  467. *
  468. * @param string $path
  469. * @return string
  470. */
  471. public function getEncryptedFileKey($path) {
  472. $encryptedFileKey = $this->keyStorage->getFileKey($path,
  473. $this->fileKeyId, Encryption::ID);
  474. return $encryptedFileKey;
  475. }
  476. /**
  477. * delete share key
  478. *
  479. * @param string $path
  480. * @param string $keyId
  481. * @return boolean
  482. */
  483. public function deleteShareKey($path, $keyId) {
  484. return $this->keyStorage->deleteFileKey(
  485. $path,
  486. $keyId . '.' . $this->shareKeyId,
  487. Encryption::ID);
  488. }
  489. /**
  490. * @param $path
  491. * @param $uid
  492. * @return mixed
  493. */
  494. public function getShareKey($path, $uid) {
  495. $keyId = $uid . '.' . $this->shareKeyId;
  496. return $this->keyStorage->getFileKey($path, $keyId, Encryption::ID);
  497. }
  498. /**
  499. * check if user has a private and a public key
  500. *
  501. * @param string $userId
  502. * @return bool
  503. * @throws PrivateKeyMissingException
  504. * @throws PublicKeyMissingException
  505. */
  506. public function userHasKeys($userId) {
  507. $privateKey = $publicKey = true;
  508. $exception = null;
  509. try {
  510. $this->getPrivateKey($userId);
  511. } catch (PrivateKeyMissingException $e) {
  512. $privateKey = false;
  513. $exception = $e;
  514. }
  515. try {
  516. $this->getPublicKey($userId);
  517. } catch (PublicKeyMissingException $e) {
  518. $publicKey = false;
  519. $exception = $e;
  520. }
  521. if ($privateKey && $publicKey) {
  522. return true;
  523. } elseif (!$privateKey && !$publicKey) {
  524. return false;
  525. } else {
  526. throw $exception;
  527. }
  528. }
  529. /**
  530. * @param $userId
  531. * @return mixed
  532. * @throws PublicKeyMissingException
  533. */
  534. public function getPublicKey($userId) {
  535. $publicKey = $this->keyStorage->getUserKey($userId, $this->publicKeyId, Encryption::ID);
  536. if (strlen($publicKey) !== 0) {
  537. return $publicKey;
  538. }
  539. throw new PublicKeyMissingException($userId);
  540. }
  541. public function getPublicShareKeyId() {
  542. return $this->publicShareKeyId;
  543. }
  544. /**
  545. * get public key for public link shares
  546. *
  547. * @return string
  548. */
  549. public function getPublicShareKey() {
  550. return $this->keyStorage->getSystemUserKey($this->publicShareKeyId . '.' . $this->publicKeyId, Encryption::ID);
  551. }
  552. /**
  553. * @param string $purpose
  554. * @param string $uid
  555. */
  556. public function backupUserKeys($purpose, $uid) {
  557. $this->keyStorage->backupUserKeys(Encryption::ID, $purpose, $uid);
  558. }
  559. /**
  560. * create a backup of the users private and public key and then delete it
  561. *
  562. * @param string $uid
  563. */
  564. public function deleteUserKeys($uid) {
  565. $this->deletePublicKey($uid);
  566. $this->deletePrivateKey($uid);
  567. }
  568. /**
  569. * @param $uid
  570. * @return bool
  571. */
  572. public function deletePublicKey($uid) {
  573. return $this->keyStorage->deleteUserKey($uid, $this->publicKeyId, Encryption::ID);
  574. }
  575. /**
  576. * @param string $uid
  577. * @return bool
  578. */
  579. private function deletePrivateKey($uid) {
  580. return $this->keyStorage->deleteUserKey($uid, $this->privateKeyId, Encryption::ID);
  581. }
  582. /**
  583. * @param string $path
  584. * @return bool
  585. */
  586. public function deleteAllFileKeys($path) {
  587. return $this->keyStorage->deleteAllFileKeys($path);
  588. }
  589. /**
  590. * @param array $userIds
  591. * @return array
  592. * @throws PublicKeyMissingException
  593. */
  594. public function getPublicKeys(array $userIds) {
  595. $keys = [];
  596. foreach ($userIds as $userId) {
  597. try {
  598. $keys[$userId] = $this->getPublicKey($userId);
  599. } catch (PublicKeyMissingException $e) {
  600. continue;
  601. }
  602. }
  603. return $keys;
  604. }
  605. /**
  606. * @param string $keyId
  607. * @return string returns openssl key
  608. */
  609. public function getSystemPrivateKey($keyId) {
  610. return $this->keyStorage->getSystemUserKey($keyId . '.' . $this->privateKeyId, Encryption::ID);
  611. }
  612. /**
  613. * @param string $keyId
  614. * @param string $key
  615. * @return string returns openssl key
  616. */
  617. public function setSystemPrivateKey($keyId, $key) {
  618. return $this->keyStorage->setSystemUserKey(
  619. $keyId . '.' . $this->privateKeyId,
  620. $key,
  621. Encryption::ID);
  622. }
  623. /**
  624. * add system keys such as the public share key and the recovery key
  625. *
  626. * @param array $accessList
  627. * @param array $publicKeys
  628. * @param string $uid
  629. * @return array
  630. * @throws PublicKeyMissingException
  631. */
  632. public function addSystemKeys(array $accessList, array $publicKeys, $uid) {
  633. if (!empty($accessList['public'])) {
  634. $publicShareKey = $this->getPublicShareKey();
  635. if (empty($publicShareKey)) {
  636. throw new PublicKeyMissingException($this->getPublicShareKeyId());
  637. }
  638. $publicKeys[$this->getPublicShareKeyId()] = $publicShareKey;
  639. }
  640. if ($this->recoveryKeyExists() &&
  641. $this->util->isRecoveryEnabledForUser($uid)) {
  642. $publicKeys[$this->getRecoveryKeyId()] = $this->getRecoveryKey();
  643. }
  644. return $publicKeys;
  645. }
  646. /**
  647. * get master key password
  648. *
  649. * @return string
  650. * @throws \Exception
  651. */
  652. public function getMasterKeyPassword() {
  653. $password = $this->config->getSystemValue('secret');
  654. if (empty($password)) {
  655. throw new \Exception('Can not get secret from Nextcloud instance');
  656. }
  657. return $password;
  658. }
  659. /**
  660. * return master key id
  661. *
  662. * @return string
  663. */
  664. public function getMasterKeyId() {
  665. return $this->masterKeyId;
  666. }
  667. /**
  668. * get public master key
  669. *
  670. * @return string
  671. */
  672. public function getPublicMasterKey() {
  673. return $this->keyStorage->getSystemUserKey($this->masterKeyId . '.' . $this->publicKeyId, Encryption::ID);
  674. }
  675. /**
  676. * get public master key
  677. *
  678. * @return string
  679. */
  680. public function getPrivateMasterKey() {
  681. return $this->keyStorage->getSystemUserKey($this->masterKeyId . '.' . $this->privateKeyId, Encryption::ID);
  682. }
  683. }