deriveSignatureKeyPair() public static méthode

Derive a key pair for public key signatures from a password and salt
public static deriveSignatureKeyPair ( HiddenString $password, string $salt, string $level = self::INTERACTIVE ) : SignatureKeyPair
$password HiddenString
$salt string
$level string Security level for KDF
Résultat SignatureKeyPair
 public function testDeriveSigningKey()
 {
     $keypair = KeyFactory::deriveSignatureKeyPair('apple', "\t\n\v\f\r");
     $sign_secret = $keypair->getSecretKey();
     $sign_public = $keypair->getPublicKey();
     $this->assertTrue($sign_secret instanceof ASecretKey);
     $this->assertTrue($sign_public instanceof APublicKey);
     // Can this be used?
     $message = 'This is a test message';
     $signed = Asymmetric::sign($message, $sign_secret);
     $this->assertTrue(Asymmetric::verify($message, $sign_public, $signed));
     $this->assertEquals($sign_public->getRawKeyMaterial(), ".À>¸t\fÿ³ŽêßþŒé9" . "7}ýî¤mÉKƒëT sOº");
 }
Exemple #2
0
 /**
  * We are revoking a key.
  *
  * @param array $args
  * @throws \Exception
  * @return mixed
  */
 protected function handleKeyRevoke(array $args)
 {
     if (count($this->config['suppliers']) === 1) {
         $supplier = \count($args) > 0 ? $args[0] : \array_keys($this->config['suppliers'])[0];
     } else {
         $supplier = \count($args) > 0 ? $args[0] : $this->prompt("Please enter the name of the supplier: ");
     }
     if (!\array_key_exists($supplier, $this->config['suppliers'])) {
         echo 'Please authenticate before attempting to revoke keys.', "\n";
         echo 'Run this command: ', $this->c['yellow'], 'barge login', $this->c[''], "\n";
         exit(255);
     }
     $masterKeys = [];
     $keyList = [];
     foreach ($this->config['suppliers'][$supplier]['signing_keys'] as $key) {
         if ($key['type'] === 'master') {
             if (!empty($key['salt'])) {
                 $masterKeys[] = $key;
             } else {
                 $keyList[] = $key;
             }
         } else {
             $keyList[] = $key;
         }
     }
     if (empty($masterKeys)) {
         echo 'No usable master keys found. Make sure the salt is loaded locally.', "\n";
         exit(255);
     }
     if (empty($keyList)) {
         // If and only if you have nothing more to revoke, allow revoking the master key:
         $keyList = $masterKeys;
     }
     if (\count($masterKeys) === 1) {
         $masterKey = $masterKeys[0];
     } else {
         $masterKey = $this->selectKeyFromList('Select your master key: ', $masterKeys);
         // Add other master keys to the list
         foreach ($masterKeys as $key) {
             if ($key['public_key'] !== $masterKey['public_key']) {
                 $keyList[] = $key;
             }
         }
     }
     if (\count($keyList) === 1) {
         $revokingKey = $keyList[0];
     } else {
         $revokingKey = $this->selectKeyFromList('Select which key to revoke: ', $keyList);
     }
     $confirm_revoke = null;
     while ($confirm_revoke === null) {
         $choice = $this->prompt('Are you sure you wish to revoke this key? (y/N): ');
         switch ($choice) {
             case 'YES':
             case 'yes':
             case 'Y':
             case 'y':
                 $confirm_revoke = true;
                 break;
             case 'N':
             case 'NO':
             case 'n':
             case 'no':
             case '':
                 // Just pressing enter means "don't store it"!
                 $confirm_revoke = false;
                 break;
             default:
                 echo "\n", $this->c['yellow'], 'Invalid response. Please enter yes or no.', $this->c[''], "\n";
         }
     }
     // This is what get signed by our master key:
     $message = ['action' => 'REVOKE', 'date_revoked' => \date('Y-m-d\\TH:i:s'), 'public_key' => $revokingKey['public_key'], 'supplier' => $supplier];
     $messageToSign = \json_encode($message);
     $iter = false;
     do {
         if ($iter) {
             echo 'Incorrect password.', "\n";
         }
         $password = $this->silentPrompt('Enter the password for your master key: ');
         if (empty($password)) {
             // Okay, let's cancel.
             throw new \Exception('Aborted.');
         }
         $masterKeyPair = KeyFactory::deriveSignatureKeyPair($password, \Sodium\hex2bin($masterKey['salt']), false, KeyFactory::SENSITIVE);
         \Sodium\memzero($password);
         $masterPublicKeyString = \Sodium\bin2hex($masterKeyPair->getPublicKey()->getRawKeyMaterial());
         $iter = true;
     } while (!\hash_equals($masterKey['public_key'], $masterPublicKeyString));
     $signature = Asymmetric::sign($messageToSign, $masterKeyPair->getSecretKey());
     $response = $this->sendRevocation($supplier, $message, $signature, $masterPublicKeyString);
     if ($response['status'] === 'OK') {
         foreach ($this->config['suppliers'][$supplier]['signing_keys'] as $i => $key) {
             if ($key['public_key'] === $message['public_key']) {
                 unset($this->config['suppliers'][$supplier]['signing_keys'][$i]);
             }
         }
     }
     return $response;
 }
Exemple #3
0
 /**
  * Sign the new key with our current master key
  *
  * @param string $supplier
  * @param string $messageToSign
  * @return string[]
  * @throws \Exception
  */
 protected function signNewKeyWithMasterKey(string $supplier, string $messageToSign) : array
 {
     $master_keys = [];
     foreach ($this->config['suppliers'][$supplier]['signing_keys'] as $key) {
         if ($key['type'] === 'master' && !empty($key['salt'])) {
             $master_keys[] = $key;
         }
     }
     // This shouldn't happen, but just in case:
     if (empty($master_keys)) {
         throw new \Exception('You cannot generate another key unless you already have a master key with the salt loaded locally.');
     }
     // Select the correct master key.
     if (\count($master_keys) === 1) {
         $signingKey = $master_keys[0];
     } else {
         echo 'Select which master key to use:';
         do {
             foreach ($master_keys as $index => $key) {
                 $pk = Base64UrlSafe::encode(\Sodium\hex2bin($key['public_key']));
                 echo $index + 1, "\t", $pk, "\n";
             }
             $keyIndex = $this->prompt('Enter a number: ');
             if (empty($keyIndex)) {
                 // Okay, let's cancel.
                 throw new \Exception('Aborted.');
             }
             if ($keyIndex < 1 || $keyIndex > \count($master_keys)) {
                 $keyIndex = 0;
                 echo 'Please enter a number between 1 and ', \count($master_keys), ".\n";
             }
         } while ($keyIndex < 1);
         $signingKey = $master_keys[--$keyIndex];
     }
     $signature = '';
     $masterSalt = \Sodium\hex2bin($signingKey['salt']);
     do {
         $password = $this->silentPrompt('Enter the password for your master key: ');
         if (empty($password)) {
             // Okay, let's cancel.
             throw new \Exception('Aborted.');
         }
         $masterKeyPair = KeyFactory::deriveSignatureKeyPair($password, $masterSalt, false, KeyFactory::SENSITIVE);
         // We must verify the public key matches:
         $masterPublicKey = $masterKeyPair->getPublicKey();
         if (\hash_equals($masterPublicKey->getRawKeyMaterial(), \Sodium\hex2bin($signingKey['public_key']))) {
             $masterSecretKey = $masterKeyPair->getSecretKey();
             // Setting $signature exits the loop
             $signature = Asymmetric::sign($messageToSign, $masterSecretKey);
         } else {
             echo 'Incorrect master key passphrase!', "\n";
         }
     } while (!$signature);
     // We are returning two strings:
     return [$signature, $signingKey['public_key']];
 }
Exemple #4
0
 public function testLegacySignKeyStorage()
 {
     $sign_keypair = KeyFactory::deriveSignatureKeyPair('apple', "\t\n\v\f\r" . "", true);
     $sign_secret = $sign_keypair->getSecretKey();
     $sign_public = $sign_keypair->getPublicKey();
     $file_secret = \tempnam(__DIR__ . '/tmp', 'key');
     $file_public = \tempnam(__DIR__ . '/tmp', 'key');
     $this->assertTrue(KeyFactory::save($sign_secret, $file_secret) !== false);
     $this->assertTrue(KeyFactory::save($sign_public, $file_public) !== false);
     $load_public = KeyFactory::loadSignaturePublicKey($file_public);
     $this->assertTrue($load_public instanceof SignaturePublicKey);
     $this->assertTrue(\hash_equals($sign_public->getRawKeyMaterial(), $load_public->getRawKeyMaterial()));
     \unlink($file_secret);
     \unlink($file_public);
 }