Exemple #1
0
 /**
  * Execute the start command, which will start a new hangar session.
  *
  * @param array $args
  * @return bool
  * @throws \Error
  */
 public function fire(array $args = []) : bool
 {
     $file = $this->selectFile($args[0] ?? '');
     if (!isset($this->config['salt']) && \count($args) < 2) {
         throw new \Error('No salt configured or passed');
     }
     if (\count($args) > 2) {
         switch (\strtolower($args[2])) {
             case 'fast':
             case 'i':
             case 'interactive':
             case 'weak':
                 $level = KeyFactory::INTERACTIVE;
                 break;
             case 'm':
             case 'signing':
             case 'moderate':
                 $level = KeyFactory::MODERATE;
                 break;
             default:
                 $level = KeyFactory::SENSITIVE;
                 break;
         }
     } elseif (isset($this->config['keytype'])) {
         switch ($this->config['keytype']) {
             case 'fast':
             case 'i':
             case 'interactive':
             case 'weak':
                 $level = KeyFactory::INTERACTIVE;
                 break;
             case 'm':
             case 'signing':
             case 'moderate':
                 $level = KeyFactory::MODERATE;
                 break;
             default:
                 $level = KeyFactory::SENSITIVE;
                 break;
         }
     } else {
         $level = KeyFactory::SENSITIVE;
     }
     $salt = \Sodium\hex2bin($args[1] ?? $this->config['salt']);
     echo 'Generating a signature for: ', $file, "\n";
     $password = $this->silentPrompt('Enter password: '******'false' in version 2.0.0 (with Halite 3)
     $sign_kp = KeyFactory::deriveSignatureKeyPair($password, $salt, false, $level);
     if (!$sign_kp instanceof SignatureKeyPair) {
         throw new \Error('Error during key derivation');
     }
     $signature = File::sign($file, $sign_kp->getSecretKey());
     if (isset($this->history)) {
         $this->config['build_history']['signed'] = true;
     }
     \file_put_contents($file . '.sig', $signature);
     echo 'File signed: ' . $file . '.sig', "\n";
     echo 'Public key: ' . \Sodium\bin2hex($sign_kp->getPublicKey()->getRawKeyMaterial()), "\n";
     return true;
 }
Exemple #2
0
 /**
  * Common signing process. User selects key, provides password.
  *
  * @param array $manifest
  * @return SignatureSecretKey
  * @throws \Exception
  */
 protected function signPreamble(array $manifest) : SignatureSecretKey
 {
     $HTAB = \str_repeat(' ', \intdiv(self::TAB_SIZE, 2));
     $supplier_name = $manifest['supplier'];
     // Sanity checks:
     if (!\array_key_exists('suppliers', $this->config)) {
         echo 'You are not authenticated for any suppliers.', "\n";
         exit(255);
     }
     if (!\array_key_exists($supplier_name, $this->config['suppliers'])) {
         echo 'Check the supplier in the JSON file (', $supplier_name, ') for correctness.', 'Otherwise, you might need to log in.', "\n";
         exit(255);
     }
     $supplier = $this->config['suppliers'][$supplier_name];
     $numKeys = 0;
     if ($this->signWithMasterKeys) {
         $good_keys = [];
         // This should really not be used:
         $numKeys = \count($supplier['signing_keys']);
         foreach ($supplier['signing_keys'] as $k) {
             if (!empty($k['salt'])) {
                 $good_keys[] = $k;
                 ++$numKeys;
             }
         }
     } else {
         // This should be used instead:
         $good_keys = [];
         foreach ($supplier['signing_keys'] as $k) {
             if ($k['type'] === 'signing' && !empty($k['salt'])) {
                 $good_keys[] = $k;
                 ++$numKeys;
             }
         }
     }
     if ($numKeys > 1) {
         echo 'You have more than one signing key available.', "\n";
         $n = 1;
         $size = (int) \floor(\log($numKeys, 10));
         $key_associations = $HTAB . "ID\t Public Key " . \str_repeat(' ', 33) . "\t Type\n";
         foreach ($supplier['signing_keys'] as $sign_key) {
             if (!$this->signWithMasterKeys && $sign_key['type'] === 'master') {
                 continue;
             }
             $_n = \str_pad($n, $size, ' ', STR_PAD_LEFT);
             // Short format:
             $pk = Base64UrlSafe::encode(\Sodium\hex2bin($sign_key['public_key']));
             $key_associations .= $HTAB . $_n . $HTAB . $pk . $HTAB . $sign_key['type'] . "\n";
             ++$n;
         }
         // Let's ascertain the user's key selection
         do {
             echo $key_associations;
             $choice = (int) $this->prompt('Enter the ID for the key you wish to use: ');
             if ($choice < 1 || $choice > $numKeys) {
                 $choice = null;
             }
         } while (empty($choice));
         $supplierKey = $good_keys[$choice - 1];
         echo "\n";
     } else {
         $supplierKey = $good_keys[0];
     }
     // The above !empty($k['salt']) check should have rendered this check redundant:
     if (empty($supplierKey['salt'])) {
         echo 'Salt not found for this key. It is not possible to reproduce it.', "\n";
         exit(255);
     }
     // Short format:
     $pk = Base64UrlSafe::encode(\Sodium\hex2bin($supplierKey['public_key']));
     // Color coded: Master keys are red, since they take longer.
     // We don't support signing packages with a master key, but
     // this decision could be undone in the future.
     $c = $supplierKey['type'] === 'master' ? $this->c['red'] : $this->c['yellow'];
     echo 'Selected ', $supplierKey['type'], ' key: ', $c, $pk, $this->c[''], "\n";
     $password = $this->silentPrompt('Enter Password for Signing Key:');
     // Derive and split the SignatureKeyPair from your password and salt
     $salt = \Sodium\hex2bin($supplierKey['salt']);
     switch ($supplierKey['type']) {
         case 'signing':
             $type = KeyFactory::MODERATE;
             echo 'Verifying (this may take a second or two)...';
             break;
         case 'master':
             $type = KeyFactory::SENSITIVE;
             echo 'Verifying (this may take a few seconds)...';
             break;
         default:
             $type = KeyFactory::INTERACTIVE;
             echo 'Verifying...';
     }
     $keyPair = KeyFactory::deriveSignatureKeyPair($password, $salt, false, $type);
     $sign_secret = $keyPair->getSecretKey();
     $sign_public = $keyPair->getPublicKey();
     echo ' Done.', "\n";
     // We don't need this anymore.
     \Sodium\memzero($password);
     // Check that the public key we derived from the password matches the one on file
     $pubKey = \Sodium\bin2hex($sign_public->getRawKeyMaterial());
     if (!\hash_equals($supplierKey['public_key'], $pubKey)) {
         // Zero the memory ASAP
         unset($sign_secret);
         unset($sign_public);
         echo 'Invalid password for selected key', "\n";
         exit(255);
     }
     // Zero the memory ASAP
     unset($sign_public);
     return $sign_secret;
 }