Ejemplo n.º 1
0
 public function testDeriveSigningKey()
 {
     list($sign_secret, $sign_public) = ASecretKey::deriveFromPassword('apple', "\t\n\v\f\r" . "", Key::CRYPTO_SIGN);
     $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->get(), "þ\t†E·õÂbÈagÖ\t" . "•§”\\æÕU–ãuˆ4");
 }
Ejemplo n.º 2
0
 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º");
 }
Ejemplo n.º 3
0
 public function testLegacyDeriveSigningKey()
 {
     $keypair = KeyFactory::deriveSignatureKeyPair('apple', "\t\n\v\f\r" . "", true);
     $sign_secret = $keypair->getSecretKey();
     $sign_public = $keypair->getPublicKey();
     $this->assertTrue($sign_secret instanceof SignatureSecretKey);
     $this->assertTrue($sign_public instanceof SignaturePublicKey);
     // 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�E���b�ag�\t" . "���\\��U��u�4");
 }
Ejemplo n.º 4
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;
 }
Ejemplo n.º 5
0
 /**
  * Unseal a (file handle)
  * 
  * @param $input
  * @param $output
  * @param \ParagonIE\Halite\Contract\CryptoKeyInterface $secretkey
  */
 public static function unsealResource($input, $output, \ParagonIE\Halite\Contract\CryptoKeyInterface $secretkey)
 {
     // Input validation
     if (!\is_resource($input)) {
         throw new \ParagonIE\Halite\Alerts\InvalidType('Expected input handle to be a resource');
     }
     if (!\is_resource($output)) {
         throw new \ParagonIE\Halite\Alerts\InvalidType('Expected output handle to be a resource');
     }
     if (!$secretkey->isSecretKey()) {
         throw new CryptoException\InvalidKey('Expected a secret key');
     }
     if (!$secretkey->isAsymmetricKey()) {
         throw new CryptoException\InvalidKey('Expected a key intended for asymmetric-key cryptography');
     }
     $secret_key = $secretkey->get();
     $public_key = \Sodium\crypto_box_publickey_from_secretkey($secret_key);
     // Parse the header, ensuring we get 4 bytes
     $header = self::readBytes($input, Halite::VERSION_TAG_LEN);
     // Load the config
     $config = self::getConfig($header, 'seal');
     // Let's grab the public key and salt
     $eph_public = self::readBytes($input, $config['PUBLICKEY_BYTES']);
     $hkdfsalt = self::readBytes($input, $config['HKDF_SALT_LEN']);
     $nonce = \Sodium\crypto_generichash($eph_public . $public_key, null, \Sodium\CRYPTO_STREAM_NONCEBYTES);
     $ephemeral = new Key($eph_public, true, false, true);
     $key = Asymmetric::getSharedSecret($secretkey, $ephemeral, true);
     list($encKey, $authKey) = self::splitKeys($key, $hkdfsalt);
     // We no longer need the original key after we split it
     unset($key);
     $mac = \hash_init('sha256', HASH_HMAC, $authKey);
     \hash_update($mac, $header);
     \hash_update($mac, $eph_public);
     \hash_update($mac, $hkdfsalt);
     // This will throw an exception if it fails.
     $old_macs = self::streamVerify($input, \hash_copy($mac), $config);
     $ret = self::streamDecrypt($input, $output, new Key($encKey), $nonce, $mac, $config, $old_macs);
     unset($encKey);
     unset($authKey);
     unset($nonce);
     unset($mac);
     unset($config);
     unset($old_macs);
     return $ret;
 }
Ejemplo n.º 6
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']];
 }
Ejemplo n.º 7
0
 /**
  * Verify the contents of a file
  * 
  * @param $input (file handle)
  * @param SignaturePublicKey $publickey
  * @param string $signature
  * @param bool $raw_binary Don't hex encode?
  * 
  * @return bool
  */
 public static function verifyStream(ReadOnlyFile $input, KeyInterface $publickey, $signature, $raw_binary = false)
 {
     if (!$publickey instanceof SignaturePublicKey) {
         throw new \ParagonIE\Halite\Alerts\InvalidKey('Argument 2: Expected an instance of SignaturePublicKey');
     }
     $csum = self::checksumStream($input, null, true);
     return AsymmetricCrypto::verify($csum, $publickey, $signature, $raw_binary);
 }
Ejemplo n.º 8
0
 /**
  * @covers Asymmetric::sign()
  * @covers Asymmetric::verify()
  */
 public function testSignFail()
 {
     $alice = KeyFactory::generateSignatureKeyPair();
     $message = 'test message';
     $signature = Asymmetric::sign($message, $alice->getSecretKey(), true);
     $this->assertFalse(Asymmetric::verify('wrongmessage', $alice->getPublicKey(), $signature, true));
     $_signature = $signature;
     // Let's flip one bit, randomly:
     $r = \Sodium\randombytes_uniform(\mb_strlen($signature, '8bit'));
     $_signature[$r] = \chr(\ord($_signature[$r]) ^ 1 << \Sodium\randombytes_uniform(8));
     $this->assertFalse(Asymmetric::verify($message, $alice->getPublicKey(), $_signature, true));
 }