Appearance
Encryption and Decryption Algorithms
This section explains the specific algorithms that are used when values 1 through 9 are specified for the ENCRYPT_KS
and DECRYPT_KS
functions. Values 4 through 9 only are supported for ENCRYPTED WITH
column constraints in CREATE TABLE
statements, using the same algorithms.
Function Parameter | Algorithm | Output Length (Encryption) | Output Length (Decryption) |
---|---|---|---|
1 | Initialize AES with a 128-bit key and encrypt (or decrypt) using Output Feedback Mode (OFB). | floor((n1 * 8 + 5) / 6) | floor((n1 * 6) / 8)) |
2 | Initialize AES with a 192-bit key and encrypt (or decrypt) using OFB. | floor((n1 * 8 + 5) / 6) | floor((n1 * 6) / 8)) |
3 | Initialize AES with a 256-bit key and encrypt (or decrypt) using OFB. | floor((n1 * 8 + 5) / 6) | floor((n1 * 6) / 8)) |
4 | Use 128-bit key deterministic encryption (or deterministic decryption). | ceil((17 + n1) / 3) * 4 | (floor(n1 / 4) * 3) - 17 |
5 | Use 192-bit key deterministic encryption (or deterministic decryption). | ceil((25 + n1) / 3) * 4 | (floor(n1 / 4) * 3) - 25 |
6 | Use 256-bit key deterministic encryption (or deterministic decryption). | ceil((33 + n1) / 3) * 4 | (floor(n1 / 4) * 3) - 33 |
7 | Use 128-bit key randomized encryption (or randomized decryption). | ceil((17 + n1) / 3) * 4 | (floor(n1 / 4) * 3) - 17 |
8 | Use 192-bit key randomized encryption (or randomized decryption). | ceil((25 + n1) / 3) * 4 | (floor(n1 / 4) * 3) - 25 |
9 | Use 256-bit key randomized encryption (or randomized decryption). | ceil((33 + n1) / 3) * 4 | (floor(n1 / 4) * 3) - 33 |
Randomized Encryption
The algorithm for randomized (non-deterministic) encryption follows these steps:
- Accept (binary) input string
plaintext
with lengthplaintext_length
bytes. - Accept (binary) input key with length
key_length
bytes. - Accept (integer) input
aes_keybits
(must be 128, 192, or 256). - Reuse/fold key to
aes_keybits
. The actual size of the key required depends on the algorithm selected. The actual size of the initialization vector for modes 4 to 9 is 128 bits.
- When the input
key
orivec
is shorter than expected, reuse the input until the required size is reached. - When the input
key
orivec
is longer than expected, fold the extra input with the required input viaXOR
.
- Generate a cryptographically random salt with
aes_keybits
(likely generated via Fortuna). ciphertext = ofb_aes(plaintext, key = (key XOR salt), iv = (salt >> (aes_keybits - 128))
ciphertext_length = plaintext_length
outputtext = version (1 byte) + salt (aes_keybits/8) + ciphertext (ciphertext_length bytes)
outputtext_length = 1 + (aes_keybits/8) + ciphertext_length
Note:
- This encryption algorithm is specifically designed to be secure against any kind of chosen plain-text attacks (including dictionary-based attacks for low-cardinality data sets).
- This algorithm is also resistant to length-extension attacks; that is, an attacker with encrypt access cannot pad a chosen (binary) string to an already encrypted value.
- Use an HMAC on the
outputtext
separately if you need to protect against random padding. ciphertext_length
mirrorsplaintext_length
, and therefore leaks information about the input. For example,ciphertext
for'm'
will be indistinguishable (in length and randomness) fromciphertext
for'f'
; however,ciphertext_length
for'male'
will be different fromciphertext_length
for'female'
. To guard against this leakage, pad all input to the same length.
Randomized Decryption
The algorithm for randomized (non-deterministic) decryption follows these steps:
- Accept (binary) input string
outputtext
with lengthoutputtext_length
bytes. - Accept (binary) input key with length
key_length
bytes. - Accept (integer) input
aes_keybits
(must 128, 192, or 256). - Reuse/fold key to
aes_keybits
. The actual size of the key required depends on the algorithm selected. The actual size of the initialization vector for modes 4 to 9 is 128 bits.
- When the input
key
orivec
is shorter than expected, reuse the input until the required size is reached. - When the input
key
orivec
is longer than expected, fold the extra input with the required input viaXOR
.
version = outputtext[0:0]
salt = outputtext[1:(aes_keybits/8)]
ciphertext = outputtext[(aes_keybits/8):(outputtext_length-1)]
plaintext = ofb_aes(ciphertext, key = (key XOR salt), iv = (salt >> (aes_keybits - 128))
plaintext_length = outputtext_length - (1 + (aes_keybits/8))
Note:
- This decryption algorithm is not susceptible to padding-oracle attacks.
- OFB enables decryption in a stream-cipher mode instead of requiring PKCS-like padding.
- An attacker who has decrypt access but not encrypt access may be able to encrypt chosen plain texts. This may be a problem if a user erroneously relies on an encryption system for message-authentication; use a proper HMAC if needed to prevent message forgery.
Deterministic Encryption
The algorithm is the same as in randomized encryption, except for the choice of salt
in step 5:
salt = hmac_sha256(key, plaintext) >> (256 - aes_keybits);
Note:
- Identical
plaintext
strings encrypt to identicaloutputtext
strings when you use the samekey
; this method enables equality comparison. - The same
plaintext
value encrypted with two different keys generates two differentoutputtext
values.
Deterministic Decryption
The algorithm for deterministic decryption works exactly the same as the algorithm for randomized decryption.
Note:
- padding-oracle attacks are not possible.
- Given that deterministic decryption uses an
hmac_sha256
instead ofsha256
, it is possible to detect and prevent random length extensions. However, for compatibility with randomized encryption, Yellowbrick decryption instead returns an undefined result.
A Warning about "Symmetric" Algorithms
Encryption algorithms 1
, 2
, and 3
are considered "symmetric." Users need to be careful about choosing these algorithms if the default initialization vector (IV) is being used, if the IV is well-known, or if the IV may have been leaked. In these scenarios, roles who have ENCRYPT
but not DECRYPT
access may be able to decipher strings by reverse engineering the bit-stream that was used to protect those strings.
For example, assume that encryption key k0
and role r0
exist in your system, that r0
is neither a superuser nor the owner of k0
, and that r0
has been granted ENCRYPT
but not DECRYPT
access on k0
.
In turn, r0
can run a query where:
cipher-text = encrypt(plain-text, k0, {1 | 2 | 3}, iv)
Although r0
cannot run an equivalent DECRYPT
query, the following property holds true for binary data:
plain-text = encrypt(encrypt(plain-text, k0, {1 | 2 | 3}, iv), k0, {1 | 2 | 3}, iv)
Therefore, if r0
happens to know the iv
in use, r0
can recover the plain-text from the cipher-text by reverse-engineering the bit-stream used to protect the plain-text string.
Parent topic:ENCRYPT_KS