public function createScopedKey($filters, $allowedOperations)
    {
        if (!$masterKey = $this->getMasterKey()) {
            throw new RuntimeException('A master key is needed to create a scoped key');
        }

        $options = array('filters' => $filters);

        if (!empty($allowedOperations)) {
            $options['allowed_operations'] = $allowedOperations;
        }

        $apiKey = pack('H*', $masterKey);

        $opensslOptions = \OPENSSL_RAW_DATA;

        $optionsJson = json_encode($options);

        /**
         * Use the old block size and hex string input if using a legacy master key.
         * Old block size was 32 bytes and old master key was 32 hex characters in length.
         */

        if (strlen($masterKey) == 32) {
            $apiKey = $masterKey;

            // Openssl's built-in PKCS7 padding won't use the 32 bytes block size, so apply it in userland
            // and use OPENSSL zero padding (no-op as already padded)
            $opensslOptions |= \OPENSSL_ZERO_PADDING;
            $optionsJson = $this->padString($optionsJson, 32);
        }

        $cipher = 'AES-256-CBC';

        $ivLength = openssl_cipher_iv_length($cipher);
        $iv = random_bytes($ivLength);

        $encrypted = openssl_encrypt($optionsJson, $cipher, $apiKey, $opensslOptions, $iv);

        $ivHex        = bin2hex($iv);
        $encryptedHex = bin2hex($encrypted);

        $scopedKey = $ivHex . $encryptedHex;

        return $scopedKey;
    }