Path: blob/master/src/applications/auth/sshkey/PhabricatorAuthSSHPublicKey.php
12256 views
<?php12/**3* Data structure representing a raw public key.4*/5final class PhabricatorAuthSSHPublicKey extends Phobject {67private $type;8private $body;9private $comment;1011private function __construct() {12// <internal>13}1415public static function newFromStoredKey(PhabricatorAuthSSHKey $key) {16$public_key = new PhabricatorAuthSSHPublicKey();17$public_key->type = $key->getKeyType();18$public_key->body = $key->getKeyBody();19$public_key->comment = $key->getKeyComment();2021return $public_key;22}2324public static function newFromRawKey($entire_key) {25$entire_key = trim($entire_key);26if (!strlen($entire_key)) {27throw new Exception(pht('No public key was provided.'));28}2930$parts = str_replace("\n", '', $entire_key);3132// The third field (the comment) can have spaces in it, so split this33// into a maximum of three parts.34$parts = preg_split('/\s+/', $parts, 3);3536if (preg_match('/private\s*key/i', $entire_key)) {37// Try to give the user a better error message if it looks like38// they uploaded a private key.39throw new Exception(pht('Provide a public key, not a private key!'));40}4142switch (count($parts)) {43case 1:44throw new Exception(45pht('Provided public key is not properly formatted.'));46case 2:47// Add an empty comment part.48$parts[] = '';49break;50case 3:51// This is the expected case.52break;53}5455list($type, $body, $comment) = $parts;5657$recognized_keys = array(58'ssh-dsa',59'ssh-dss',60'ssh-rsa',61'ssh-ed25519',62'ecdsa-sha2-nistp256',63'ecdsa-sha2-nistp384',64'ecdsa-sha2-nistp521',65);6667if (!in_array($type, $recognized_keys)) {68$type_list = implode(', ', $recognized_keys);69throw new Exception(70pht(71'Public key type should be one of: %s',72$type_list));73}7475$public_key = new PhabricatorAuthSSHPublicKey();76$public_key->type = $type;77$public_key->body = $body;78$public_key->comment = $comment;7980return $public_key;81}8283public function getType() {84return $this->type;85}8687public function getBody() {88return $this->body;89}9091public function getComment() {92return $this->comment;93}9495public function getHash() {96$body = $this->getBody();97$body = trim($body);98$body = rtrim($body, '=');99return PhabricatorHash::digestForIndex($body);100}101102public function getEntireKey() {103$key = $this->type.' '.$this->body;104if (strlen($this->comment)) {105$key = $key.' '.$this->comment;106}107return $key;108}109110public function toPKCS8() {111$entire_key = $this->getEntireKey();112$cache_key = $this->getPKCS8CacheKey($entire_key);113114$cache = PhabricatorCaches::getImmutableCache();115$pkcs8_key = $cache->getKey($cache_key);116if ($pkcs8_key) {117return $pkcs8_key;118}119120$tmp = new TempFile();121Filesystem::writeFile($tmp, $this->getEntireKey());122try {123list($pkcs8_key) = execx(124'ssh-keygen -e -m PKCS8 -f %s',125$tmp);126} catch (CommandException $ex) {127unset($tmp);128throw new PhutilProxyException(129pht(130'Failed to convert public key into PKCS8 format. If you are '.131'developing on OSX, you may be able to use `%s` '.132'to work around this issue. %s',133'bin/auth cache-pkcs8',134$ex->getMessage()),135$ex);136}137unset($tmp);138139$cache->setKey($cache_key, $pkcs8_key);140141return $pkcs8_key;142}143144public function forcePopulatePKCS8Cache($pkcs8_key) {145$entire_key = $this->getEntireKey();146$cache_key = $this->getPKCS8CacheKey($entire_key);147148$cache = PhabricatorCaches::getImmutableCache();149$cache->setKey($cache_key, $pkcs8_key);150}151152private function getPKCS8CacheKey($entire_key) {153return 'pkcs8:'.PhabricatorHash::digestForIndex($entire_key);154}155156}157158159