public static function deriveEncryptionKeyPair(
        HiddenString $password,
        string $salt,
        string $level = self::INTERACTIVE,
        int $alg = SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13
    ): EncryptionKeyPair {
        $kdfLimits = self::getSecurityLevels($level, $alg);
        // VERSION 2+ (argon2)
        if (Binary::safeStrlen($salt) !== \SODIUM_CRYPTO_PWHASH_SALTBYTES) {
            // @codeCoverageIgnoreStart
            throw new InvalidSalt(
                'Expected ' . \SODIUM_CRYPTO_PWHASH_SALTBYTES . ' bytes, got ' . Binary::safeStrlen($salt)
            );
            // @codeCoverageIgnoreEnd
        }
        // Diffie Hellman key exchange key pair
        /** @var string $seed */
        $seed = @\sodium_crypto_pwhash(
            \SODIUM_CRYPTO_BOX_SEEDBYTES,
            $password->getString(),
            $salt,
            $kdfLimits[0],
            $kdfLimits[1],
            $alg
        );
        $keyPair = \sodium_crypto_box_seed_keypair($seed);
        $secretKey = \sodium_crypto_box_secretkey($keyPair);
        
        // Let's wipe our $kp variable
        \sodium_memzero($keyPair);
        return new EncryptionKeyPair(
            new EncryptionSecretKey(
                new HiddenString($secretKey)
            )
        );
    }
public static function deriveEncryptionKeyPair(
        HiddenString $password,
        string $salt,
        string $level = self::INTERACTIVE,
        int $alg = SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13
    ): EncryptionKeyPair {
        $kdfLimits = self::getSecurityLevels($level, $alg);
        // VERSION 2+ (argon2)
        if (Binary::safeStrlen($salt) !== \SODIUM_CRYPTO_PWHASH_SALTBYTES) {
            // @codeCoverageIgnoreStart
            throw new InvalidSalt(
                'Expected ' . \SODIUM_CRYPTO_PWHASH_SALTBYTES . ' bytes, got ' . Binary::safeStrlen($salt)
            );
            // @codeCoverageIgnoreEnd
        }
        // Diffie Hellman key exchange key pair
        /** @var string $seed */
        $seed = @\sodium_crypto_pwhash(
            \SODIUM_CRYPTO_BOX_SEEDBYTES,
            $password->getString(),
            $salt,
            $kdfLimits[0],
            $kdfLimits[1],
            $alg
        );
        $keyPair = \sodium_crypto_box_seed_keypair($seed);
        $secretKey = \sodium_crypto_box_secretkey($keyPair);
        
        // Let's wipe our $kp variable
        \sodium_memzero($keyPair);
        return new EncryptionKeyPair(
            new EncryptionSecretKey(
                new HiddenString($secretKey)
            )
        );
    }
public static function deriveEncryptionKeyPair ( HiddenString $ password , string $ salt , string $ level = self :: INTERACTIVE , int $ alg = SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13 ) : EncryptionKeyPair { $ kdfLimits = self :: getSecurityLevels ( $ level , $ alg ) ; // VERSION 2+ (argon2) if ( Binary :: safeStrlen ( $ salt ) !== \ SODIUM_CRYPTO_PWHASH_SALTBYTES ) { // @codeCoverageIgnoreStart throw new InvalidSalt ( 'Expected ' . \ SODIUM_CRYPTO_PWHASH_SALTBYTES . ' bytes, got ' . Binary :: safeStrlen ( $ salt ) ) ; // @codeCoverageIgnoreEnd } // Diffie Hellman key exchange key pair /** @var string $seed */ $ seed = @ \ sodium_crypto_pwhash ( \ SODIUM_CRYPTO_BOX_SEEDBYTES , $ password -> getString ( ) , $ salt , $ kdfLimits [ 0 ] , $ kdfLimits [ 1 ] , $ alg ) ; $ keyPair = \ sodium_crypto_box_seed_keypair ( $ seed ) ; $ secretKey = \ sodium_crypto_box_secretkey ( $ keyPair ) ; // Let's wipe our $kp variable \ sodium_memzero ( $ keyPair ) ; return new EncryptionKeyPair ( new EncryptionSecretKey ( new HiddenString ( $ secretKey ) ) ) ; }
Derive a key pair for public key encryption from a password and salt

@param HiddenString $password
@param string $salt
@param string $level Security level for KDF
@param int $alg      Which Argon2 variant to use?
(You can safely use the default)

@return EncryptionKeyPair

@throws InvalidKey
@throws InvalidSalt
@throws InvalidType
@throws \TypeError
Derive a key pair for public key encryption from a password and salt