Skip to content
developed by

Core Anonymizers

This page list all Anonymizers provided by DbToolsBundle.

Email address

EmailAnonymizer uses a hash function on the original value to make each unique email anonymization reproducible accross tables.

This Anonymizer will fill configured column with value looking like [username]@[domain.tld] where:

  • [username] is a md5 hash of the pre-anonymization value
  • [domain.tld] is the given domain option (or example.com by default)

For example contact@makina-corpus.com will give 826464d916e6052ad209037ca71ce324@example.com after anonymization.

yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            email_address: email
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column(length: 180, unique: true)]
    #[Anonymize(type: 'email')] 
    private ?string $email = null;

    // ...
}
yaml
# config/anonymization.yaml

customer:
    email_address: email

#...

Or, with the domain option:

yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            email_address:
                anonymizer: email
                options: {domain: 'custom-domain.com'}
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column(length: 180, unique: true)]
    #[Anonymize(type: 'email', options: ['domain' => 'custom-domain.com'])] 
    private ?string $email = null;

    // ...
}
yaml
# config/anonymization.yaml

customer:
    email_address:
        anonymizer: email
        options: {domain: 'custom-domain.com'}
#...

INFO

Email value is salted prior to be hashed using md5 in order to prevent reverse hashing with rainbow tables. Salt is global across the same anonymization run, this means that the same email address anonymized twice will give the same value.

In order to disable the salt, set the use_salt option to false.

WARNING

SQLite does implement MD5() function, neither any hashing function: in order to get around this, the rowid value is used instead which prevent email values anonymization from being reproducible across tables.

Password

This Anonymizer give you a way to set the same password for each one of your users. It is based on the Symfony PasswordHasher Component.

Options are :

  • algorithm: algorithm to use to hash the plain password. (Default is auto).
  • password: plain password that will be set for each row. (Default is password)
yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            password: password


        # Or, with options:

        customer:
            password:
                anonymizer: password
                options: {algorithm: 'sodium', password: '123456789'}
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    /**
     * @var string The hashed password
     */
    #[ORM\Column]
    #[Anonymize(type: 'password')] 
    private ?string $password = null;

    // Or, with options:

    /**
     * @var string The hashed password
     */
    #[ORM\Column]
    #[Anonymize(type: 'password', options: ['algorithm' => 'sodium', 'password' => '123456789'])] 
    private ?string $password = null;
    // ...
}
yaml
# config/anonymization.yaml

customer:
    password: password


# Or, with options:

customer:
    password:
        anonymizer: password
        options: {algorithm: 'sodium', password: '123456789'}

#...

Integer

Anonymize integers by:

  • randomly choosing an integer in a range delimited by 'min' and 'max' options
  • altering the initial value by adding it a random value picked in a range computed from the 'delta' or 'percent' options
yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            age:
                anonymizer: integer
                options: {min: 10, max: 99}

        customer:
            # Will add to each age value a random integer
            # in the [-delta, +delta] interval
            # In this example, an integer between -15 and 15 will be
            # added to the initial value
            age:
                anonymizer: integer
                options: {delta: 15}

        customer:
            # Will add to each age value a random percent
            # of the initial value in the [-percent%, +percent%] interval
            # In this example, a value between -10% and 10% of the initial value
            # will be added to age.
            age:
                anonymizer: integer
                options: {percent: 10}
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column]
    // Will fill the age column with a random integer
    // in the [min, max] interval
    #[Anonymize(type: 'integer', options: ['min' => 10, 'max' => 99])] 
    private ?int $age = null;

    #[ORM\Column]
    // Will add to each age value a random integer
    // in the [-delta, +delta] interval
    // In this example, an integer between -15 and 15 will be
    // added to the initial value
    #[Anonymize(type: 'integer', options: ['delta' => 15])] 
    private ?int $age = null;

    #[ORM\Column]
    // Will add to each age value a random percent
    // of the initial value in the [-percent%, +percent%] interval
    // In this example, a value between -10% and 10% of the initial value
    // will be added to age.
    #[Anonymize(type: 'integer', options: ['percent' => 10])] 
    private ?int $age = null;
    // ...
}
yml
# config/anonymization.yaml

customer:
    age:
        anonymizer: integer
        options: {min: 10, max: 99}

customer:
    # Will add to each age value a random integer
    # in the [-delta, +delta] interval
    # In this example, an integer between -15 and 15 will be
    # added to the initial value
    age:
        anonymizer: integer
        options: {delta: 15}

customer:
    # Will add to each age value a random percent
    # of the initial value in the [-percent%, +percent%] interval
    # In this example, a value between -10% and 10% of the initial value
    # will be added to age.
    age:
        anonymizer: integer
        options: {percent: 10}

#...

Float

Anonymize float by:

  • randomly choosing an integer in a range delimited by min and max options
  • altering the initial value by adding it a random value picked in a range computed from the delta or percent options

You may also specify a precision (default 2).

yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            # Will fill the size column with a random float
            # in the [min, max] interval.
            size:
                anonymizer: float
                options: {min: 120, max: 300, precision: 4}

        customer:
            # Will add to each size value a random integer
            # in the [-delta, +delta] interval.
            # In this example, an integer between -15.5 and 15.5 will be
            # added to the initial value.
            size:
                anonymizer: float
                options: {delta: 15.5}

        customer:
            # Will add to each size value a random percent
            # of the initial value in the [-percent%, +percent%] interval.
            # In this example, a value between -10% and 10% of the initial value
            # will be added to the initial value.
            size:
                anonymizer: float
                options: {percent: 10}
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column]
    // Will fill the size column with a random float
    // in the [min, max] interval.
    #[Anonymize(type: 'float', options: ['min' => 10, 'max' => 99, 'precision' => 4])] 
    private ?float $size = null;

    #[ORM\Column]
    // Will add to each size value a random integer
    // in the [-delta, +delta] interval.
    // In this example, an integer between -15.5 and 15.5 will be
    // added to the initial value.
    #[Anonymize(type: 'float', options: ['delta' => 15.5, 'precision' => 4])] 
    private ?float $size = null;

    #[ORM\Column]
    // Will add to each size value a random percent
    // of the initial value in the [-percent%, +percent%] interval.
    // In this example, a value between -10% and 10% of the initial value
    // will be added to the initial value.
    #[Anonymize(type: 'float', options: ['percent' => 10])] 
    private ?float $size = null;

    // ...
}
yaml
# config/anonymization.yaml

customer:
    # Will fill the size column with a random float
    # in the [min, max] interval.
    size:
        anonymizer: float
        options: {min: 120, max: 300, precision: 4}

customer:
    # Will add to each size value a random integer
    # in the [-delta, +delta] interval.
    # In this example, an integer between -15.5 and 15.5 will be
    # added to the initial value.
    size:
        anonymizer: float
        options: {delta: 15.5}

customer:
    # Will add to each size value a random percent
    # of the initial value in the [-percent%, +percent%] interval.
    # In this example, a value between -10% and 10% of the initial value
    # will be added to the initial value.
    size:
        anonymizer: float
        options: {percent: 10}
#...

Date

Anonymize dates by either:

  • randomly choosing an date or datetime in a given range delimited by min and max options,
  • altering the initial value by adding it a random value picked in a range computed from the delta options.

min and max options can be any string that can be parsed as a date by the DateTime class constructor, for example:

  • an absolute date: 2024-03-15 or datetime: 2024-03-15 10:28:56,
  • a relative time: now +2 hours, -3 month, ...

delta option can be either:

  • an ISO interval specification, such as: P1DT1M (1 day and 1 minute),
  • a human readable date string that PHP can parse: 1 month -3 day +3 minutes.

You can additionnally set the format parameter:

  • date will cast the generated date as a date without time,
  • datetime will generate a full timestamp.
yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            # Will add to the existing date a random interval in the [-delta, +delta] interval.
            birthDate:
                anonymizer: date
                options: {delta: '1 month 15 day'}

        customer:
            # Will pick a random date in the given [min, max] interval.
            lastLogin:
                anonymizer: date
                options: {min: 'now -3 month', max: 'now'}

        customer:
            # And example with absolute dates.
            createdAt:
                anonymizer: date
                options: {min: '1789-05-05', max: '2024-03-15', format: 'date'}
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column]
    // Will add to the existing date a random interval
    // in the [-delta, +delta] interval.
    #[Anonymize(type: 'date', options: ['delta' => '1 month 15 day'])] 
    private ?\DateTime $birthDate = null;

    #[ORM\Column]
    // Will pick a random date in the given
    // [min, max] interval
    #[Anonymize(type: 'date', options: ['min' => 'now -3 month', 'max' => 'now'])] 
    private ?\DateTimeImmutable $lastLogin = null;

    #[ORM\Column]
    // And example with absolute dates.
    #[Anonymize(type: 'date', options: ['min' => '1789-05-05', 'max' => '2024-03-15', 'format' => 'date'])] 
    private ?\DateTime $createdAt = null;
}
yml
# config/anonymization.yaml

customer:
    # Will add to the existing date a random interval in the [-delta, +delta] interval.
    birthDate:
        anonymizer: date
        options: {delta: '1 month 15 day'}

customer:
    # Will pick a random date in the given [min, max] interval.
    lastLogin:
        anonymizer: date
        options: {min: 'now -3 month', max: 'now'}

customer:
    # And example with absolute dates.
    createdAt:
        anonymizer: date
        options: {min: '1789-05-05', max: '2024-03-15', format: 'date'}

#...

WARNING

Dates you give for min and max values will inherit from the PHP default configured timezone.

INFO

When using a date range over 68 years, random granularity stops at the hour in order to avoid date add operation to be given an overflowing int value.

Null

Set all values to NULL.

yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            sensible_content: 'null'
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column]
    #[Anonymize(type: 'null')] 
    private ?string $sensibleContent = null;

    // ...
}
yml
# config/anonymization.yaml

customer:
    sensible_content: 'null'

#...

Constant value

Set all value to a constant value. Options are:

  • value: the value you want to use to fill the column
  • type: a SQL type for the given value (default value is text)
yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            address:
                sensible_content:
                    type: constant
                    options: {value: '_______'}
        # or for example
        customer:
            address:
                sensible_content:
                    type: constant
                    options: {value: '2012-12-21', type: 'date'}
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column]
    #[Anonymize(type: 'constant', options: ['value' => '_______'])] 
    private ?string $sensibleContent = null;

    #[ORM\Column]
    #[Anonymize(type: 'constant', options: ['value' => '2012-12-21', 'type' => 'date'])] 
    private ?string $sensibleContent = null;

    // ...
}
yml
# config/anonymization.yaml

customer:
    sensible_content:
        type: constant
        options: {value: '_______'}

customer:
    sensible_content:
        type: constant
        options: {value: '2012-12-21', type: 'date'}

#...

Md5 hash

This Anonymizer will fill configured column with a md5 hash of the pre-anonymization value.

yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            my_dirty_secret: md5
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column(length: 255)]
    #[Anonymize(type: 'md5')] 
    private ?string $myDirtySecret = null;

    // ...
}
yaml
# config/anonymization.yaml

customer:
    my_dirty_secret: md5
#...

INFO

Hashing a string is not anonymizing it because hash functions have a reproducible output. In order to avoid decrypting data using rainbow tables, a salt will be added by default to string values prior to hashing.

Salt is global across the same anonymization run, which means that same values across the database will all inherit from the same hashed value, keeping things consistent.

In order to disable the salt usage, set the use_salt option to false.

WARNING

SQLite does implement MD5() function, neither any hashing function, this anonymizer cannot be used with SQLite.

String

This Anonymizer will fill configured column with a random value from a given sample.

yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            level:
                anonymizer: string
                options: {sample: ['none', 'bad', 'good', 'expert']}
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column(length: 255)]
    #[Anonymize(type: 'string', options: ['sample' => ['none', 'bad', 'good', 'expert']])] 
    private ?string $level = null;

    // ...
}
yaml
# config/anonymization.yaml
customer:
    level:
        anonymizer: string
        options: {sample: ['none', 'bad', 'good', 'expert']}
#...

TIP

If you use the same sample multiple times, if you use a large sample or if you use a generated one, it could be more efficient and convinient to create your own custom anonymizer, see the Custom Anonymizers section to learn how to do that.

Lastname

Works like the StringAnonymizer, but with a provided sample of 1000 worldwide lastnames.

yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            lastname: lastname
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column(length: 255)]
    #[Anonymize('lastname')] 
    private ?string $lastname = null;

    // ...
}
yaml
# config/anonymization.yaml

customer:
    lastname: lastname
#...

Firstname

Works like the StringAnonymizer, but with a provided sample of 1000 worldwide firstnames.

yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            firstname: firstname
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column(length: 255)]
    #[Anonymize('firstname')] 
    private ?string $firstname = null;

    // ...
}
yaml
# config/anonymization.yaml

customer:
    firstname: firstname
#...

Lorem Ipsum

Replace a text with some lorem ipsum. Default behavior is to generate a single paragraph.

Available options:

  • paragraphs: (int) number of paragraphs to generate,
  • words: (int) number of words to generate (could not be used in combination with paragraphs option),
  • html: (bool) surround each paragraph with <p>, default is false.
  • sample_count: (int) how many different values to use (default is 100).
yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            message: lorem

        customer:
            # Will generate 10 paragraphs, each one surrounded by a html `<p>` tag
            message:
                anonymizer: lorem
                options:
                    paragaphs: 10
                    html: true

        customer:
            # Will only generate 5 words
            message:
                anonymizer: lorem
                options: {words: 5}
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
class Customer
{
    // ...

    #[ORM\Column(length: 255)]
    #[Anonymize('lorem')] 
    private ?string $message = null;

    #[ORM\Column(length: 255)]
    // Will generate 10 paragraphs, each one surrounded by a html `<p>` tag
    #[Anonymize('lorem', ['paragraphs' => 10, 'html' => true])] 
    private ?string $message = null;

    #[ORM\Column(length: 255)]
    // Will only generate 5 words
    #[Anonymize('lorem', ['words' => 5])] 
    private ?string $message = null;

    // ...
}
yaml
# config/anonymization.yaml

customer:
    message: lorem

customer:
    # Will generate 10 paragraphs, each one surrounded by a html `<p>` tag
    message:
        anonymizer: lorem
        options:
            paragaphs: 10
            html: true

customer:
    # Will only generate 5 words
    message:
        anonymizer: lorem
        options: {words: 5}
#...

Address

This Anonymizer is multicolumn. It let you anonymize, at once, mutiple columns on one table that represent different parts of a postal address.

Each part will be fill with a coherent random address from a sample of 300 addresses around the world.

Available parts are :

PartDefinitionExample
countryThe countryFrance
localityThe locality in which the street address is, and which is in the regionNantes
regionThe region in which the locality is, and which is in the countryPays de la Loire
postal_codeThe postal code44000
street_addressThe street address. For example, 5 rue de la Paix5 rue de la Paix
secondary_addressAdditional information (apartment, block)Appartement 310
yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            address: # An arbitrary key
                target: table
                anonymizer: address
                options:
                    street_address: 'street'
                    secondary_address: 'street_address_2'
                    postal_code: 'zip_code'
                    locality: 'city'
                    region: 'region'
                    country: 'country'
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
#[Anonymize(type: 'address', options: [ 
    'street_address' => 'street', 
    'secondary_address': 'street_second_line'
    'postal_code' => 'zip_code', 
    'locality' => 'city', 
    'region' => 'region'
    'country' => 'country', 
])] 
class Customer
{
    // ...

    #[ORM\Column(length: 255)]
    private ?string $street = null;

    #[ORM\Column(length: 255)]
    private ?string $streetSecondLine = null;

    #[ORM\Column(length: 255)]
    private ?string $zipCode = null;

    #[ORM\Column(length: 255)]
    private ?string $city = null;

    #[ORM\Column(length: 255)]
    private ?string $region = null;

    #[ORM\Column(length: 255)]
    private ?string $country = null;

    // ...
}
yaml
# config/anonymization.yaml
customer:
    address: # An arbitrary key
        target: table
        anonymizer: address
        options:
            street_address: 'street'
            secondary_address: 'street_address_2'
            postal_code: 'zip_code'
            locality: 'city'
            region: 'region'
            country: 'country'
  #...

TIP

Note that you don't have to provide a column for each part. You can use this Anonymizer to only anonymize some parts of an address. To do so, remove options you don't want in the example below.

Iban/Bic

This Anonymizer is multicolumn. It let you anonymize, at once, an IBAN and a BIC code. You can choose to anonymize either one of IBAN or BIC, or both.

Available options:

  • country: (string) two-letters country code for generating the IBAN number with the target country validation rules (default is fr),
  • sample_size: (int) generated random sample table size (default is 500).

Available columns are:

PartDefinitionExample
ibanThe International Bank Account NumberFR1711881618378130962836522
bicThe Bank Identifier CodeQFWXOC6L
yaml
# db_tools.config.yaml
anonymization:
    default:
        customer:
            iban: # An arbitrary key
                target: table
                anonymizer: iban-bic
                options:
                    iban: 'account_iban'
                    bic: 'account_bic'
  #...
php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;

#[ORM\Entity()]
#[ORM\Table(name: 'customer')]
#[Anonymize(type: 'iban-bic', options: [ 
    'iban' => 'account_iban', 
    'bic': 'account_bic'
])] 
class Customer
{
    // ...

    #[ORM\Column(length: 255)]
    private ?string $accountIban = null;

    #[ORM\Column(length: 255)]
    private ?string $accountBic = null;

    // ...
}
yaml
# config/anonymization.yaml
customer:
    iban: # An arbitrary key
        target: table
        anonymizer: iban-bic
        options:
            iban: 'account_iban'
            bic: 'account_bic'
  #...

Released under the MIT License.