/** * Returns a new set of keys for message encryption and signing. * * @param string $seed The seed to use to create repeatable keys. * @param string $hashKey The key to hash the key with. * @return array */ public static function generateKeys($seed = null, $hashKey = '') { # The keys are being generated from a seed. if ($seed !== null) { # Generate some repeatable hashes to create keys against for recovery $encrHash = Hash::hash($seed, $hashKey, Constants::BOX_SEEDBYTES); $signHash = Hash::hash($seed, $hashKey, Constants::SIGN_SEEDBYTES); # Build recoverable pre-seeded key pairs. $seeds = ['encr' => \Sodium\crypto_box_keypair($encrHash), 'sign' => \Sodium\crypto_sign_keypair($signHash)]; } else { # Build un-recoverable key pairs. $seeds = ['encr' => \Sodium\crypto_box_keypair(), 'sign' => \Sodium\crypto_sign_keypair()]; } # Return the two generated key pairs to the client. return ['encr' => ['pri' => Helpers::bin2hex(\Sodium\crypto_box_secretkey($seeds['encr'])), 'pub' => Helpers::bin2hex(\Sodium\crypto_box_publickey($seeds['encr']))], 'sign' => ['pri' => Helpers::bin2hex(\Sodium\crypto_sign_secretkey($seeds['sign'])), 'pub' => Helpers::bin2hex(\Sodium\crypto_sign_publickey($seeds['sign']))]]; }
/** * Generate a key * * @param int $type * @param &string $secret_key - Reference to optional variable to store secret key in * @return array|Key */ public static function generate($type = self::CRYPTO_SECRETBOX, &$secret_key = null) { // Set this to true to flag a key as a signing key $signing = false; /** * Are we doing public key cryptography? */ if (($type & self::ASYMMETRIC) !== 0) { /** * Are we doing encryption or digital signing? */ if (($type & self::ENCRYPTION) !== 0) { // Encryption keypair $kp = \Sodium\crypto_box_keypair(); $secret_key = \Sodium\crypto_box_secretkey($kp); $public_key = \Sodium\crypto_box_publickey($kp); } elseif (($type & self::SIGNATURE) !== 0) { // Digital signature keypair $signing = true; $kp = \Sodium\crypto_sign_keypair(); $secret_key = \Sodium\crypto_sign_secretkey($kp); $public_key = \Sodium\crypto_sign_publickey($kp); } else { throw new CryptoException\InvalidFlags('Must specify encryption or authentication'); } // Let's wipe our $kp variable \Sodium\memzero($kp); // Let's return an array with two keys return [new ASecretKey($secret_key, $signing), new APublicKey($public_key, $signing)]; } elseif ($type & self::SECRET_KEY !== 0) { /** * Are we doing encryption or authentication? */ if ($type & self::ENCRYPTION !== 0) { $secret_key = \random_bytes(\Sodium\CRYPTO_SECRETBOX_KEYBYTES); } elseif ($type & self::SIGNATURE !== 0) { $signing = true; // ...let it throw, let it throw! $secret_key = \random_bytes(\Sodium\CRYPTO_AUTH_KEYBYTES); } return new SecretKey($secret_key, $signing); } else { throw new CryptoException\InvalidFlags('Must specify symmetric-key or asymmetric-key'); } }
/** * Derive a key pair for public key signatures from a password and salt * * @param type $secret_key * @return \ParagonIE\Halite\EncryptionKeyPair */ public static function deriveSignatureKeyPair($password, $salt) { // Digital signature keypair $seed = \Sodium\crypto_pwhash_scryptsalsa208sha256(\Sodium\CRYPTO_SIGN_SEEDBYTES, $password, $salt, \Sodium\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE, \Sodium\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE); $keypair = \Sodium\crypto_sign_seed_keypair($seed); $secret_key = \Sodium\crypto_sign_secretkey($keypair); // Let's wipe our $kp variable \Sodium\memzero($keypair); return new SignatureKeyPair(new SignatureSecretKey($secret_key)); }
/** * Derive a key pair for public key signatures from a password and salt * * @param string $password * @param string $salt * @param bool $legacy Use scrypt? * * @return SignatureKeyPair * @throws CryptoException\InvalidSalt */ public static function deriveSignatureKeyPair(string $password, string $salt, bool $legacy = false) : SignatureKeyPair { if ($legacy) { if (CryptoUtil::safeStrlen($salt) !== \Sodium\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES) { throw new CryptoException\InvalidSalt('Expected ' . \Sodium\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES . ' bytes, got ' . CryptoUtil::safeStrlen($salt)); } // Digital signature keypair $seed = \Sodium\crypto_pwhash_scryptsalsa208sha256(\Sodium\CRYPTO_SIGN_SEEDBYTES, $password, $salt, \Sodium\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE, \Sodium\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE); } else { if (CryptoUtil::safeStrlen($salt) !== \Sodium\CRYPTO_PWHASH_SALTBYTES) { throw new CryptoException\InvalidSalt('Expected ' . \Sodium\CRYPTO_PWHASH_SALTBYTES . ' bytes, got ' . CryptoUtil::safeStrlen($salt)); } // Digital signature keypair $seed = \Sodium\crypto_pwhash(\Sodium\CRYPTO_SIGN_SEEDBYTES, $password, $salt, \Sodium\CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, \Sodium\CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE); } $keypair = \Sodium\crypto_sign_seed_keypair($seed); $secret_key = \Sodium\crypto_sign_secretkey($keypair); // Let's wipe our $kp variable \Sodium\memzero($keypair); return new SignatureKeyPair(new SignatureSecretKey($secret_key)); }
/** * Derive a key pair for public key signatures from a password and salt * * @param HiddenString $password * @param string $salt * @param string $level Security level for KDF * * @return SignatureKeyPair * @throws CryptoException\InvalidSalt */ public static function deriveSignatureKeyPair(HiddenString $password, string $salt, string $level = self::INTERACTIVE) : SignatureKeyPair { $kdfLimits = self::getSecurityLevels($level); // VERSION 2+ (argon2) if (Util::safeStrlen($salt) !== \Sodium\CRYPTO_PWHASH_SALTBYTES) { throw new CryptoException\InvalidSalt('Expected ' . \Sodium\CRYPTO_PWHASH_SALTBYTES . ' bytes, got ' . Util::safeStrlen($salt)); } // Digital signature keypair $seed = \Sodium\crypto_pwhash(\Sodium\CRYPTO_SIGN_SEEDBYTES, $password->getString(), $salt, $kdfLimits[0], $kdfLimits[1]); $keyPair = \Sodium\crypto_sign_seed_keypair($seed); $secretKey = \Sodium\crypto_sign_secretkey($keyPair); // Let's wipe our $kp variable \Sodium\memzero($keyPair); return new SignatureKeyPair(new SignatureSecretKey(new HiddenString($secretKey))); }