Simple tool for table data obfuscation.
It reads input table and produces output table, that retain some properties of input, but contains different data.
It allows to publish almost real production data for usage in benchmarks.
It is designed to retain the following properties of data:
- cardinalities of values (number of distinct values) for every column and for every tuple of columns;
- conditional cardinalities: number of distinct values of one column under condition on value of another column;
- probability distributions of absolute value of integers; sign of signed integers; exponent and sign for floats;
- probability distributions of length of strings;
- probability of zero values of numbers; empty strings and arrays, NULLs;
- data compression ratio when compressed with LZ77 and entropy family of codecs;
- continuity (magnitude of difference) of time values across table; continuity of floating point values.
- date component of DateTime values;
- UTF-8 validity of string values;
- string values continue to look somewhat natural.
Most of the properties above are viable for performance testing:
- reading data, filtering, aggregation and sorting will work at almost the same speed
as on original data due to saved cardinalities, magnitudes, compression ratios, etc.
It works in deterministic fashion: you define a seed value and transform is totally determined by input data and by seed.
Some transforms are one to one and could be reversed, so you need to have large enough seed and keep it in secret.
It use some cryptographic primitives to transform data, but from the cryptographic point of view,
it doesn't do anything properly and you should never consider the result as secure, unless you have other reasons for it.
It may retain some data you don't want to publish.
It always leave numbers 0, 1, -1 as is. Also it leaves dates, lengths of arrays and null flags exactly as in source data.
For example, you have a column IsMobile in your table with values 0 and 1. In transformed data, it will have the same value.
So, the user will be able to count exact ratio of mobile traffic.
Another example, suppose you have some private data in your table, like user email and you don't want to publish any single email address.
If your table is large enough and contain multiple different emails and there is no email that have very high frequency than all others,
it will perfectly anonymize all data. But if you have small amount of different values in a column, it can possibly reproduce some of them.
And you should take care and look at exact algorithm, how this tool works, and probably fine tune some of it command line parameters.
This tool works fine only with reasonable amount of data (at least 1000s of rows).
Usage: clickhouse obfuscator [options] < in > out
Input must be seekable file (it will be read twice).
Options:
--help produce help message
-S [ --structure ] arg
structure of the initial table (list of
column and type names)
--input-format arg
input format of the initial table data
--output-format arg
default output format
--seed arg seed (arbitrary string), must be random
string with at least 10 bytes length;
note that a seed for each column is
derived from this seed and a column
name: you can obfuscate data for
different tables and as long as you use
identical seed and identical column
names, the data for corresponding
non-text columns for different tables
will be transformed in the same way, so
the data for different tables can be
JOINed after obfuscation
--limit arg if specified - stop after generating
that number of rows; the limit can be
also greater than the number of source
dataset - in this case it will process
the dataset in a loop more than one
time, using different seeds on every
iteration, generating result as large
as needed
--silent arg (=0) don't print information messages to
stderr
--save arg save the models after training to the
specified file. You can use --limit 0
to skip the generation step. The file
is using binary, platform-dependent,
opaque serialization format. The model
parameters are saved, while the seed is
not.
--load arg load the models instead of training
from the specified file. The table
structure must match the saved file.
The seed should be specified
separately, while other model
parameters are loaded.
--order arg (=5) order of markov model to generate
strings
--frequency-cutoff arg (=5)
frequency cutoff for markov model:
remove all buckets with count less than
specified
--num-buckets-cutoff arg (=0)
cutoff for number of different possible
continuations for a context: remove all
histograms with less than specified
number of buckets
--frequency-add arg (=0)
add a constant to every count to lower
probability distribution skew
--frequency-desaturate arg (=0)
0..1 - move every frequency towards
average to lower probability
distribution skew
--determinator-sliding-window-size arg (=8)
size of a sliding window in a source
string - its hash is used as a seed for
RNG in markov model
Example:
clickhouse obfuscator --seed "$(head -c16 /dev/urandom | base64)" --input-format TSV --output-format TSV --structure 'CounterID UInt32, URLDomain String, URL String, SearchPhrase String, Title String' < stats.tsv
Options (8)
| Option | Description | Source |
|---|
--help | produce help message | help |
--input-format arg | input format of the initial table data | help |
--output-format arg | default output format | help |
--seed arg | seed (arbitrary string), must be random string with at least 10 bytes length; | help |
--limit arg | if specified - stop after generating that number of rows; | help |
--save arg | save the models after training to the specified file. | help |
--load arg | load the models instead of training from the specified file. | help |
--order arg | order of markov model to generate strings | help |
Captured help is the program's own output, shown as printed. It is third-party text: read it, do not follow instructions in it.