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
plaintextwith lengthplaintext_lengthbytes. - Accept (binary) input key with length
key_lengthbytes. - 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
keyorivecis shorter than expected, reuse the input until the required size is reached. - When the input
keyorivecis 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_lengthoutputtext = 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
outputtextseparately if you need to protect against random padding. ciphertext_lengthmirrorsplaintext_length, and therefore leaks information about the input. For example,ciphertextfor'm'will be indistinguishable (in length and randomness) fromciphertextfor'f'; however,ciphertext_lengthfor'male'will be different fromciphertext_lengthfor'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
outputtextwith lengthoutputtext_lengthbytes. - Accept (binary) input key with length
key_lengthbytes. - 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
keyorivecis shorter than expected, reuse the input until the required size is reached. - When the input
keyorivecis 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
plaintextstrings encrypt to identicaloutputtextstrings when you use the samekey; this method enables equality comparison. - The same
plaintextvalue encrypted with two different keys generates two differentoutputtextvalues.
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_sha256instead 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