---
title: "Security"
version: "5.19"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.phalcon.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Security

## Overview

:::info[NOTE]
Requires PHP's [openssl][openssl] extension to be present in the system
:::

[Phalcon\Encryption\Security][security] is a component that helps developers with common security-related tasks, such as password hashing and Cross-Site Request Forgery protection ([CSRF][wiki-csrf]).

:::info[NOTE]
By default the component uses PHP's `password_hash()` with `Phalcon\Encryption\Security::CRYPT_DEFAULT` (which maps to `Phalcon\Encryption\Security::CRYPT_BCRYPT` / `PASSWORD_BCRYPT`). Call `setDefaultHash()` to change the default algorithm.
:::

## Password Hashing

Storing passwords in plain text is a bad security practice. Anyone with access to the database will immediately have access to all user accounts thus being able to engage in unauthorized activities. To combat that, many applications use popular one-way hashing methods [md5][md5] and [sha1][sha1]. However, hardware evolves on a daily basis and as processors become faster, these algorithms are becoming vulnerable to brute-force attacks. These attacks are also known as [rainbow tables][rainbow-tables].

The security component uses [bcrypt][bcrypt] as the hashing algorithm. Thanks to the [Eksblowfish][eksblowfish] key setup algorithm, we can make the password encryption as `slow` as we want. Slow algorithms minimize the impact of brute-force attacks.

[Bcrypt][bcrypt] is an adaptive hash function based on the Blowfish symmetric block cipher cryptographic algorithm. It also introduces a security or work factor, which determines how slow the hash function will be to generate the hash. This effectively negates the use of FPGA or GPU hashing techniques.

Should hardware become faster in the future, we can increase the work factor to mitigate this. The salt is generated using pseudo-random bytes with the PHP's function [openssl_random_pseudo_bytes][openssl-random-pseudo-bytes].

This component offers a simple interface to use the algorithm:

```php
<?php

use Phalcon\Encryption\Security;

$security = new Security();

echo $security->hash('Phalcon'); 
// $2y$08$ZUFGUUk5c3VpcHFoVUFXeOYoA4NPFEP4G9gcm6rdo3jFPaNFdR2/O
```

We can now check if a value sent to us by a user through the UI of our application is identical to our hashed string:

```php
<?php

use Phalcon\Encryption\Security;

$password = $_POST['password'] ?? '';

$security = new Security();
$hashed = $security->hash('Phalcon');

echo $security->checkHash($password, $hashed); // true / false
```

The example demonstrates `checkHash()`. In production applications, we will definitely need to sanitize input, and also we need to store the hashed password in a data store such as a database. Using controllers, the above example can be shown as:

```php
<?php

use MyApp\Models\Users;
use Phalcon\Http\Request;
use Phalcon\Mvc\Controller;
use Phalcon\Encryption\Security;

/**
 * @property Request  $request
 * @property Security $security
 */
class SessionController extends Controller
{
public function loginAction()
{
    $login    = $this->request->getPost('login');
    $password = $this->request->getPost('password');

    $user = Users::findFirst(
        [
            'conditions' => 'login = :login:',
            'bind'       => [
                'login' => $login,
            ],
        ]
    );

    if (false !== $user) {
        $check = $this
            ->security
            ->checkHash($password, $user->password);

        if (true === $check) {
            // OK
        }
    } else {
        $this->security->hash(rand());
    }

    // ERROR
}

public function registerAction()
{
    $login    = $this->request->getPost('login', 'string');
    $password = $this->request->getPost('password', 'string');

    $user = new Users();

    $user->login    = $login;
    $user->password = $this->security->hash($password);

    $user->save();
}

}
```

:::danger[DANGER]
The code snippet above is incomplete and **must not be used as is for production applications**
:::

The `registerAction()` above accepts posted data from the UI. It sanitizes it with the `string` filter and then creates a new `User` model object. It then assigns the passed data to the relevant properties before saving it. Notice that for the password, we use the `hash()` method of the [Phalcon\Encryption\Security][security] component so that we do not save it as plain text in our database.

The `loginAction()` accepts posted data from the UI and then tries to find the user in the database based on the `login` field. If the user does exist, it will use the `checkHash()` method of the [Phalcon\Encryption\Security][security] component, to assess whether the supplied password hashed is the same as the one stored in the database.

:::info[NOTE]
You do not need to hash the supplied password (first parameter) when using `checkHash()` - the component will do that for you.
:::

If the password is not correct, you can then inform the user that something is wrong with the credentials. It is always a good idea not to provide specific information about your users to people who want to hack your site. So for instance our example above can produce two messages:

- User not found in the database
- Password is incorrect

Separating the error messages is not a good idea. If a hacker that is using brute force attack detects the second message, they can stop trying to guess the `login` and concentrate on the password, thus increasing their chances of gaining access. A more appropriate message for both potential error conditions could be

`Invalid Login/Password combination`

Finally, you will notice in the example that when the user is not found, we call:

```php
$this->security->hash(rand());
```

This is done to protect against timing attacks. Irrespective of whether a user exists or not, the script will take roughly the same amount of time to execute, since it is computing a hash again, even though we will never use that result.

## Work Factor

The work factor is what we also refer to as `cost`. It is a number that is passed in the `crypt()` method to hash the string. The work factor can be any number between `4` and `31`. The higher the number, the slower the algorithm will be.

The work factor can be set using the `setWorkFactor()` method or passed as an element of the second parameter to the `hash()` method.

```php 
<?php

use Phalcon\Encryption\Security;

$password = 'password1';
$security = new Security();
$hashed   = $security->hash('Phalcon', ['cost' => 31]);

echo $security->checkHash($password, $hashed); // true / false
```

The `workFactor` (or `cost`) is used when:

- We are using a legacy hash (i.e. one that does not use the `password_hash` method) and in particular the `Phalcon\Encryption\Security::CRYPT_BLOWFISH_A` or `Phalcon\Encryption\Security::CRYPT_BLOWFISH_X`.
- We are using a non-legacy hash (i.e. using `password_hash`) with the `Phalcon\Encryption\Security::CRYPT_DEFAULT` or `Phalcon\Encryption\Security::CRYPT_BCRYPT` algorithms.

## Argon2i

`Phalcon\Encryption\Security` also supports the new [Argon2i][argon2i] hashing algorithm. This algorithm is the winner of the [Password Hashing Competition][password-hashing-competition] and is considered to be the best algorithm for hashing passwords. It is also the default algorithm used by PHP's `password_hash()` method.

```php 
<?php

use Phalcon\Encryption\Security;

$password = 'password1';
$security = new Security();
$security->setDefaultHash(Security::CRYPT_ARGON2I);
$hashed   = $security->hash(
'Phalcon', 
[
    'memory_cost' => PASSWORD_ARGON2_DEFAULT_MEMORY_COST,
    'time_cost'   => PASSWORD_ARGON2_DEFAULT_TIME_COST,
    'threads'     => PASSWORD_ARGON2_DEFAULT_THREADS,
]
);

echo $security->checkHash($password, $hashed); // true / false
```

The `memory_cost`, `time_cost`, and `threads` options supplied to `hash()` are honored for the Argon2 algorithms, alongside the `cost`. Any option that is not supplied falls back to its `PASSWORD_ARGON2_DEFAULT_*` value.

## CSRF Protection

Cross-Site Request Forgery (CSRF) is another common attack against websites and applications. Forms designed to perform tasks such as user registration or adding comments are vulnerable to this attack.

The idea is to prevent the form values from being sent outside our application. To fix this, we generate a [random nonce][random-nonce] (token) in each form, add the token in the session, and then validate the token once the form posts data back to our application by comparing the stored token in the session to the one submitted by the form:

```php
<form method='post' action='session/login'>

<!-- Login and password inputs ... -->

<input type='hidden' 
       name='<?php echo $this->security->getTokenKey() ?>'
       value='<?php echo $this->security->getToken() ?>'/>

</form>
```

Then in the controller's action, you can check if the CSRF token is valid:

```php
<?php

use Phalcon\Mvc\Controller;

/**
 * @property Request  $request
 * @property Security $security
 */
class SessionController extends Controller
{
public function loginAction()
{
    if ($this->request->isPost()) {
        if ($this->security->checkToken()) {
            // OK
        }
    }
}
}
```

:::warning[WARNING]
It is important to remember that you will need to have a valid `session` service registered in your Dependency Injection container. Otherwise, the `checkToken()` will not work.
:::

Adding a [captcha][captcha] to the form is also recommended to completely avoid the risks of this attack.

### Disabling Automatic Token Rotation

By default the CSRF token is regenerated on every call to `getToken()` / `getTokenKey()` - a fresh random value is produced and persisted to the session each time a form is rendered. This implements the strict "synchronizer-token" pattern (single-use tokens are more resistant to replay attacks), but it also means that **every form render triggers a session write**.

For applications backed by paid or rate-limited session stores - DynamoDB, Redis-Cluster with per-write billing, remote network sessions - this per-request write can become a non-trivial cost on read-only pages that render a form. To address this, the `Security` component exposes an opt-in mode that suspends automatic regeneration while keeping the protection in place.

```php
<?php

use Phalcon\Encryption\Security;

$security = new Security();
$security->setDI($di);

// Opt out of per-call rotation. Existing session values are reused;
// when none exists yet, one fresh pair is minted on the first call.
$security->setAutoRefresh(false);

// All subsequent renders reuse the persisted token - no session write.
echo $security->getToken();      // e.g. "9k4Q...xZ"
echo $security->getToken();      // same value
echo $security->getTokenKey();   // same key
```

When you do want to rotate the token (after a successful login, a password change, or any other meaningful state transition), call `refreshToken()` to atomically regenerate both the key and the value and persist the new pair to the session - regardless of the `autoRefresh` flag:

```php
<?php

public function loginAction()
{
if ($this->request->isPost() && $this->security->checkToken()) {
    // authenticate the user...

    // Then rotate the CSRF token explicitly.
    $this->security->refreshToken();
}
}
```

:::note[Note]
The default (`autoRefresh = true`) is unchanged. If you do not call `setAutoRefresh(false)`, the historical one-time-use behavior is preserved exactly. The new behavior is opt-in.
:::

## Functionality

### Hash

**getDefaultHash() / setDefaultHash()**

Getter and setter for the default hash that the component will use. By default, the hash is set to `CRYPT_DEFAULT` ( `0`). The available options are:

* `CRYPT_BLOWFISH_A`
* `CRYPT_BLOWFISH_X`
* `CRYPT_BLOWFISH_Y` (deprecated)
* `CRYPT_MD5` (deprecated)
* `CRYPT_SHA256`
* `CRYPT_SHA512`
* `CRYPT_DEFAULT`

:::warning[DEPRECATED]
`CRYPT_STD_DES`, `CRYPT_EXT_DES`, `CRYPT_BLOWFISH`, and `CRYPT_BLOWFISH_Y` are deprecated and will be removed in a future major version. They were never implemented and resolve to bcrypt. `CRYPT_MD5` is also deprecated as a weak legacy algorithm. Any `defaultHash` value that is not explicitly handled resolves to bcrypt.
:::

**hash()**

Hashes a string or password and returns the hashed string back. The second parameter is optional and allows you to set temporarily a specific `workFactor` or pass that overrides the default one.

**checkHash()**

Accepts a string (usually the password), an already hashed string (the hashed password), and an optional minimum password length. It checks them both and returns `true` if they are identical and `false` otherwise.

**isLegacyHash()**

Returns `true` if the provided hash is a legacy hash (i.e., not produced by PHP's `password_hash()`), such as an older [bcrypt][bcrypt] variant.

### HMAC

**computeHmac()**

Generates a keyed hash value using the HMAC method. It uses PHP's [hash_hmac][hash-hmac] method internally, therefore all the parameters it accepts are the same as the [hash_hmac][hash-hmac].

### Random

**`getRandom()`**

Returns a [Phalcon\Encryption\Security\Random][security-random] object, which is a secure random number generator instance. The component is explained in detail below.

**`getRandomBytes()` / `setRandomBytes()`**

Getter and setter methods to specify the number of bytes to be generated by the openssl pseudo-random generator. It defaults to `16`.

**`getSaltBytes()`**

Generates a pseudo-random string to be used as a salt for passwords. It uses the `getRandomBytes()` value for the length of the string. It can however be overridden by the passed numeric parameter.

### Token

**`getToken()`**

Generates a pseudo-random token value to be used as input value in a CSRF check.

**`getTokenKey()`**

Generates a pseudo-random token key to be used as input's name in a CSRF check.

**`getRequestToken()`**

Returns the value of the CSRF token for the current request.

**`checkToken()`**

Check if the CSRF token sent in the request is the same as the current in session. The first parameter is the token key and the second one is the token value. It also accepts a third boolean parameter `destroyIfValid` which, if set to `true` will destroy the token if the method returns `true`.

**`getSessionToken()`**

Returns the value of the CSRF token in the session

**`destroyToken()`**

Removes the value of the CSRF token and key from the session

**`setAutoRefresh()`**

Toggles automatic regeneration of the CSRF token on every call to `getToken()` / `getTokenKey()`. Defaults to `true` ( rotate on every call - the historical behavior). When set to `false`, existing session values are reused without writing, and a new token is only minted when none is present in the session or when `refreshToken()` is called explicitly. See [Disabling Automatic Token Rotation](#disabling-automatic-token-rotation).

**`refreshToken()`**

Forces the regeneration of the CSRF token and key, writing the new values to the session even when `autoRefresh` has been disabled via `setAutoRefresh(false)`. Useful after a successful login or any other state change where rotating the token is appropriate.

## Random

The [Phalcon\Encryption\Security\Random][security-random] class makes it straightforward to generate lots of types of random data to be used in salts, new user passwords, session keys, complicated keys, encryption systems, etc. This class partially borrows [SecureRandom][secure-random] library from Ruby.

It supports the following secure random number generators:

* `random_bytes`
* `libsodium`
* `openssl`, `libressl`
* `/dev/urandom`

To utilize the above you will need to ensure that the generators are available in your system. For instance to use `openssl` your PHP installation needs to support it.

```php
<?php

use Phalcon\Encryption\Security\Random;

$random = new Random();

echo $random->hex(10);       // a29f470508d5ccb8e289
echo $random->base62();      // z0RkwHfh8ErDM1xw
echo $random->base64(16);    // SvdhPcIHDZFad838Bb0Swg==
echo $random->base64Safe();  // PcV6jGbJ6vfVw7hfKIFDGA
echo $random->uuid();        // db082997-2572-4e2c-a046-5eefe97b1235
echo $random->number(256);   // 84
echo $random->base58();      // 4kUgL2pdQMSCQtjE
```

**`base58()`**

Generates a random `base58` string. If the `$len` parameter is not specified, `16` is assumed. It may be larger in the future. The result may contain alphanumeric characters except `0` (zero), `O` (capital `o`), `I` (capital `i`), and `l` (lowercase `L`).

It is similar to `base64()` but has been modified to avoid both non-alphanumeric characters and letters which might look ambiguous when printed.

```php
<?php

use Phalcon\Encryption\Security\Random;

$random = new Random();

echo $random->base58(); // 4kUgL2pdQMSCQtjE
```

**`base62()`**

Generates a random `base62` string. If the `$len` parameter is not specified, `16` is assumed. It may be larger in the future. It is similar to `base58()` but has been modified to provide the largest value that can safely be used in URLs without needing to take extra characters into consideration because it is `[A-Za-z0-9]`

```php
<?php

use Phalcon\Encryption\Security\Random;

$random = new Random();

echo $random->base62(); // z0RkwHfh8ErDM1xw
```

**`base64()`**

Generates a random `base64` string. If the `$len` parameter is not specified, `16` is assumed. It may be larger in the future. The length of the result string is usually greater than `$len`. The size formula is:

`4 * ($len / 3)` rounded up to a multiple of 4.

```php
<?php

use Phalcon\Encryption\Security\Random;

$random = new Random();

echo $random->base64(12); // 3rcq39QzGK9fUqh8
```

**`base64Safe()`**

Generates a URL-safe random `base64` string. If the `$len` parameter is not specified, `16` is assumed. It may be larger in the future. The length of the result string is usually greater than `$len`.

By default, padding is not generated because `=` may be used as a URL delimiter. The result may contain `A-Z`, `a-z`, `0-9`, `-`, and `_`. `=` is also used if `$padding` is `true`. See [RFC 3548][rfc-3548] for the definition of URL-safe `base64`.

```php
<?php

use Phalcon\Encryption\Security\Random;

$random = new Random();

echo $random->base64Safe(); // GD8JojhzSTrqX7Q8J6uug
```

**`bytes()`**

Generates a random binary string and accepts as input an integer representing the length in bytes to be returned. If `$len` is not specified, `16` is assumed. It may be larger in the future. The result may contain any byte: `x00` - `xFF`.

```php
<?php

use Phalcon\Encryption\Security\Random;

$random = new Random();

$bytes = $random->bytes();
var_dump(bin2hex($bytes));
// Possible output: string(32) "00f6c04b144b41fad6a59111c126e1ee"
```

**`hex()`**

Generates a random hex string. If `$len` is not specified, 16 is assumed. It may be larger in the future. The length of the result string is usually greater than `$len`.

```php
<?php

use Phalcon\Encryption\Security\Random;

$random = new Random();

echo $random->hex(10); // a29f470508d5ccb8e289
```

**`number()`**

Generates a random number between `0` and `$len`. Returns an integer: `0 <= result <= $len`.

```php
<?php

use Phalcon\Encryption\Security\Random;

$random = new Random();

echo $random->number(16); // 8
```

**`uuid()`**

Generates a v4 random UUID (Universally Unique IDentifier). The version 4 UUID is purely random (except the version). It doesn't contain meaningful information such as MAC address, time, etc. See [RFC 4122][rfc-4122] for details of UUID.

This algorithm sets the version number (4 bits) as well as two reserved bits. All other bits (the remaining 122 bits) are set using a random or pseudorandom data source. Version 4 UUIDs have the form `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx` where x is any hexadecimal digit and `y` is one of `8`, `9`, `A`, or `B` (e.g., `f47ac10b-58cc-4372-a567-0e02b2c3d479`).

```php
<?php

use Phalcon\Encryption\Security\Random;

$random = new Random();

echo $random->uuid(); // 1378c906-64bb-4f81-a8d6-4ae1bfcdec22
```

## UUID

[Phalcon\Encryption\Security\Uuid][security-uuid] is a factory that generates UUIDs (Universally Unique Identifiers) for versions 1 through 7 as defined by [RFC 4122][rfc-4122] and [RFC 9562][rfc-9562]. Each version adapter is instantiated once and cached for reuse.

### Namespace Constants

[Phalcon\Encryption\Security\Uuid\UuidInterface][security-uuid-interface] defines the four standard RFC 4122 namespace UUIDs as constants:

| Constant         | Value                                  | Use                       |
|------------------|----------------------------------------|---------------------------|
| `NAMESPACE_DNS`  | `6ba7b810-9dad-11d1-80b4-00c04fd430c8` | DNS names                 |
| `NAMESPACE_URL`  | `6ba7b811-9dad-11d1-80b4-00c04fd430c8` | URLs                      |
| `NAMESPACE_OID`  | `6ba7b812-9dad-11d1-80b4-00c04fd430c8` | ISO OIDs                  |
| `NAMESPACE_X500` | `6ba7b814-9dad-11d1-80b4-00c04fd430c8` | X.500 distinguished names |

### Methods

```php
public function v1(): string
```

Generates a version 1 (time-based) UUID using a 60-bit UUID timestamp and a random node/clock-sequence.

```php
public function v3(string $namespaceName, string $name): string
```

Generates a version 3 (name-based MD5) UUID. The same namespace + name pair always produces the same UUID.

```php
public function v4(): string
```

Generates a version 4 (random) UUID.

```php
public function v5(string $namespaceName, string $name): string
```

Generates a version 5 (name-based SHA-1) UUID. The same namespace + name pair always produces the same UUID.

```php
public function v6(): string
```

Generates a version 6 (reordered time-based) UUID. Fields are reordered so that UUIDs sort lexicographically in chronological order.

```php
public function v7(): string
```

Generates a version 7 (Unix timestamp + random) UUID per RFC 9562. Monotonically increasing within the same millisecond window.

### Examples

```php
<?php

use Phalcon\Encryption\Security\Uuid;
use Phalcon\Encryption\Security\Uuid\UuidInterface;

$uuid = new Uuid();

// Version 1 - time-based
echo $uuid->v1(); // e.g. 6ba7b810-9dad-11d1-80b4-00c04fd430c8

// Version 3 - name-based MD5 (deterministic)
echo $uuid->v3(UuidInterface::NAMESPACE_DNS, 'phalcon.io');
// always: aeb94720-3f71-35d3-9b9c-c0c7a6f55e1c

// Version 4 - random
echo $uuid->v4(); // e.g. f47ac10b-58cc-4372-a567-0e02b2c3d479

// Version 5 - name-based SHA-1 (deterministic)
echo $uuid->v5(UuidInterface::NAMESPACE_URL, 'https://phalcon.io');
// always produces the same UUID for the same input

// Version 6 - reordered time-based (lexicographically sortable)
echo $uuid->v6();

// Version 7 - Unix ms timestamp + random (lexicographically sortable)
echo $uuid->v7();
```

Because each adapter is instantiated lazily and cached, repeated calls to the same `v*()` method reuse the same adapter instance.

```php
<?php

use Phalcon\Encryption\Security\Uuid;

$uuid = new Uuid();

// The v4 adapter is created once and reused
$id1 = $uuid->v4();
$id2 = $uuid->v4();
```

### Contracts

The UUID interfaces extend canonical contracts in the `Phalcon\Contracts\Encryption\Security\Uuid` namespace. New code should type-hint the contracts. The `*Interface` types remain as deprecated aliases and will be removed in a future major version.

| Deprecated interface                                      | Contract                                                   |
|-----------------------------------------------------------|------------------------------------------------------------|
| `Phalcon\Encryption\Security\Uuid\UuidInterface`          | `Phalcon\Contracts\Encryption\Security\Uuid\Uuid`          |
| `Phalcon\Encryption\Security\Uuid\TimeBasedUuidInterface` | `Phalcon\Contracts\Encryption\Security\Uuid\TimeBasedUuid` |
| `Phalcon\Encryption\Security\Uuid\NodeProviderInterface`  | `Phalcon\Contracts\Encryption\Security\Uuid\NodeProvider`  |

## Dependency Injection

If you use the [Phalcon\Di\FactoryDefault][factorydefault] container, the [Phalcon\Encryption\Security][security] is already registered for you. However, you might want to override the default registration in order to set your own `workFactor()`. Alternatively, if you are not using the [Phalcon\Di\FactoryDefault][factorydefault] and instead are using the [Phalcon\Di\Di][di] the registration is the same. By doing so, you will be able to access your configuration object from controllers, models, views, and any component that implements `Injectable`.

An example of the registration of the service as well as accessing it is below:

```php
<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Encryption\Security;

// Create a container
$container = new FactoryDefault();

$container->set(
'security',
function () {
    $security = new Security();

    $security->setWorkFactor(12);

    return $security;
},
true
);
```

In the above example, the `setWorkFactor()` sets the password hashing factor to 12 rounds.

The component is now available in your controllers using the `security` key

```php
<?php

use Phalcon\Mvc\Controller;
use Phalcon\Encryption\Security;

/**
 * @property Security $security
 */
class MyController extends Controller
{
private function getHash(string $password): string
{
    return $this->security->hash($password);
}
}
```

Also in your views (Volt syntax)

```twig
{{ security.getToken() }}
```

## Exceptions

Any exceptions thrown in the Security component will be of type [Phalcon\Encryption\Security\Exception][security-exception]. You can use this exception to selectively catch exceptions thrown only from this component. Exceptions can be raised if the hashing algorithm is unknown, if the `session` service is not present in the Di container etc.

```php
<?php

use Phalcon\Encryption\Security\Exception;
use Phalcon\Mvc\Controller;

class IndexController extends Controller
{
public function index()
{
    try {
        $this->security->hash('123');
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }
}
}
```

### Granular Exceptions

The component raises granular subclasses of `Phalcon\Encryption\Security\Exception` so callers can catch a specific failure mode. Existing `catch (Phalcon\Encryption\Security\Exception $e)` blocks continue to work unchanged.

| Class                                                         | Parent                                  | Thrown when                                                                       |
|---------------------------------------------------------------|-----------------------------------------|-----------------------------------------------------------------------------------|
| `Phalcon\Encryption\Security\Exceptions\InvalidRandomInput`   | `Phalcon\Encryption\Security\Exception` | `getRandomBytes()` is called with a non-positive byte count.                      |
| `Phalcon\Encryption\Security\Exceptions\UnknownHashAlgorithm` | `Phalcon\Encryption\Security\Exception` | A hashing algorithm is selected that is not registered in the security component. |

[argon2i]: https://argon2.online
[bcrypt]: https://en.wikipedia.org/wiki/Bcrypt
[captcha]: https://en.wikipedia.org/wiki/ReCAPTCHA
[di]: /5.19/di/
[eksblowfish]: https://en.wikipedia.org/wiki/Bcrypt#Algorithm
[factorydefault]: /5.19/api/phalcon_di/#difactorydefault
[hash-equals]: https://www.php.net/manual/en/function.hash-equals.php
[hash-hmac]: https://www.php.net/manual/en/function.hash-hmac.php
[md5]: https://php.net/manual/en/function.md5.php
[openssl]: https://php.net/manual/en/book.openssl.php
[openssl-random-pseudo-bytes]: https://php.net/manual/en/function.openssl-random-pseudo-bytes.php
[password-hashing-competition]: https://password-hashing.net
[rainbow-tables]: https://en.wikipedia.org/wiki/Rainbow_table
[random-nonce]: https://en.wikipedia.org/wiki/Cryptographic_nonce
[rfc-3548]: https://www.ietf.org/rfc/rfc3548.txt
[rfc-4122]: https://www.ietf.org/rfc/rfc4122.txt
[rfc-9562]: https://www.rfc-editor.org/rfc/rfc9562
[secure-random]: https://ruby-doc.org/stdlib-2.2.2/libdoc/securerandom/rdoc/SecureRandom.html
[security]: /5.19/api/phalcon_encryption/#encryptionsecurity
[security-exception]: /5.19/api/phalcon_encryption/#encryptionsecurityexception
[security-random]: /5.19/api/phalcon_encryption/#encryptionsecurityrandom
[security-uuid]: /5.19/api/phalcon_encryption/#encryptionsecurityuuid
[security-uuid-interface]: /5.19/api/phalcon_encryption/#encryptionsecurityuuiduuidinterface
[sha1]: https://php.net/manual/en/function.sha1.php
[wiki-csrf]: https://en.wikipedia.org/wiki/Cross-site_request_forgery

Source: https://docs.phalcon.io/5.19/encryption-security/index.mdx
