Encryption

User password hashing

Scrypt is used as a hash function to store user passwords. Scrypt is a password-based key derivation function. The algorithm was specifically designed to make it costly to perform large-scale custom hardware attacks by requiring large amounts of memory.

passwordHash = scrypt(userID + systemID + password)

Default scrypt settings:

ScryptKeyLen  = 32
ScryptSaltLen = 16
ScryptN       = 1048576
ScryptR       = 8
ScryptP       = 1

Document encryption

Each document that is added to the system is encrypted using the ChaCha20-Poly1305 algorithm. A separate key is generated for each document.

Encrypting data in indexes

Searching through the encrypted data set requires that the data is encrypted with one key. The notion of access_group is introduced.

In practice, any group of people based on some administrative boundaries (department, department, clinic, etc.) can be combined into a group. For the access group, the encryption key is generated - 32 bytes + unique access_group_nonce - 12 bytes, which are kept secret within the group.

Encrypting text values

Text values are encrypted using the ChaCha20-Poly1305 algorithm with a fixed access_group_nonce before being saved into a public index

Example:

access_group_key: 1d07add12296f142bf730c4871d5c4eaf4652d5b0b213a1c700e2a3437a2c1e0
access_group_nonce: 76b1092c73a1d28a7c9eb7b2
message: "Hello"
auth_data: "Hello"
encrypted: 2802e22fd71907ecfca353fee2890f45fd326210d9

Using the same access_group_nonce makes it possible to search ciphertexts without decrypting them.

Limitation: you must know the exact case-sensitive value to search. To do a keyword search, you can break the phrase into separate words, encode them individually, and put them in an index.

Encryption of numeric values

To convert (encrypt) numeric values we will use the function F(x) = aX + b, where a and b are positive integers > 0.

Warning! When generating the access_group_key, you have to make sure that the first 8 bytes are not zero.

As the a and b coefficients, we take the first 8 bytes of the access_group_key (4 bytes each)

Example:

access_group_key: 1d07add12296f142bf730c4871d5c4eaf4652d5b0b213a1c700e2a3437a2c1e0
a = 0x1d07add1 // 487042513
b = 0x2296f142 // 580317506
value = 36.6
encrypted = 18406073481.8 // 36.6 * 487042513 + 580317506

This conversion scheme makes it possible to compare numbers, search through ranges, and perform arithmetic operations on the converted values, while only a member of the access group who knows the key can access the real data.

Example: You need to search for records where the temperature is > 39 C For the query we first "encrypt" the required value 39.0 * 487042513 + 580317506 = 19574975513

SELECT value FROM data_index 
WHERE type = 'temperature' AND value > 19574975513

Last updated