Ciphers
AES
Encryption and Decryption
The following two methods provide a basic interface for encrypting and decrypting. Both methods are parametrised over the underlying type for the computations.
For simply using AES, one would instantiate T as UInt8. For more advanced settings that log traces or use masking, refer to the respective chapters.
CryptoSideChannel.AES.AES_encrypt — FunctionAES_encrypt(plaintext::MVector{16,T}, key::Vector{T})::MVector{16,T} where TEncrypt a block of 16 bytes with AES.
T must behave similarly to UInt8. For instantiating T with logging or protecting types, see the article on Integer Types.
Arguments
plaintextmust be a mutable, statically sized Vector of length 16. It contains the text to encrypt.keyis a vector containing the key used for the encryption. It must be either of length 16, 24, or 32. Depending on its length, different variants of AES are dispatched:- Length 16: AES-128
- Length 24: AES-196
- Length 32: AES-256
Returns
A MVector{16,T} containing the 16-byte long encrypted block.
CryptoSideChannel.AES.AES_decrypt — FunctionAES_decrypt(ciphertext::MVector{16,T}, key::Vector{T})::MVector{16,T} where TDecrypt a block of 16 bytes with AES.
T must behave similarly to UInt8. For instantiating T with logging or protecting types, see the article on Integer Types.
Arguments
ciphertextmust be a mutable, statically sized Vector of length 16. It contains the data to decrypt.keyis a vector containing the key used for the decryption. It must be either of length 16, 24, or 32. Depending on its length, different variants of AES are dispatched:- Length 16: AES-128
- Length 24: AES-196
- Length 32: AES-256
Returns
A MVector{16,T} containing the 16-byte long decrypted block.
This module also exports methods to en-/decrypt data given as a hexadecimal string:
CryptoSideChannel.AES.AES_encrypt_hex — FunctionAES_encrypt_hex(plaintext::String, key::String)Interpret plaintext and key in hexadecimal. Return a string containing the hexadecimal encrypted block. See AES_encrypt for more details.
Example
julia> AES_encrypt_hex("00112233445566778899aabbccddeeff", "000102030405060708090a0b0c0d0e0f")
"69c4e0d86a7b0430d8cdb78070b4c55a"CryptoSideChannel.AES.AES_decrypt_hex — FunctionAES_decrypt_hex(ciphertext::String, key::String)Interpret ciphertext and key in hexadecimal. Return a string containing the hexadecimal decrypted block. See AES_decrypt for more details.
Example
julia> AES_decrypt_hex("69c4e0d86a7b0430d8cdb78070b4c55a", "000102030405060708090a0b0c0d0e0f")
"00112233445566778899aabbccddeeff"AES Internal Functions
CryptoSideChannel.AES.key_expand — Functionkey_expand(k::Vector{T})::Vector{T}Compute the AES key schedule
Arguments
kis the key for the AES algorithm. It should be a vector of type T, which must be an UInt8-like type. The key is required to be a valid key for AES-128, AES-196, or AES-256. Hence,kmust be either 16, 24, or 32 bytes long.
Returns
An vector of type T containing the whole key schedule.
CryptoSideChannel.AES.inv_key_expand — Functioninv_key_expand(k::Vector{T})Compute the AES key schedule given only the last round key. This is useful for attacks targeting the last round key, or for computing the decryption key on-the-fly.
This algorithm is currently only implemented for AES-128.
Arguments
kis the last round key used in the AES algorithm. It should be a vector of type T, which must be an UInt8-like type. The key is required to be a valid round key for AES. Hence,kmust be exactly 16 bytes long.
Returns
An vector of type T containing the whole key schedule. Most importantly, the first 16 bytes of this vector are the original AES-128 key.
Example
julia> key = hex2bytes("000102030405060708090a0b0c0d0e0f")
julia> last_round_key = AES.key_expand(key)[end-15:end]
julia> recovered_key = AES.inv_key_expand(last_round_key)[1:16]
julia> bytes2hex(recovered_key)
"000102030405060708090a0b0c0d0e0f"If multiple encryptions are performed with the same key, it is efficient to only compute the key schedule once. The key schedule can be computed with key_expand manually. Afterwards, the following two functions can be used for en-/decrypting data with AES with the already computed schedule:
CryptoSideChannel.AES.AES_encrypt_expanded — FunctionAES_encrypt_expanded(plaintext::MVector{16,T}, key::Vector{T})::MVector{16,T} where TEncrypt a block of 16 bytes with AES, given an already expanded key schedule
Arguments
plaintextmust be a mutable, statically sized Vector of length 16. It contains the text to encrypt.key_scheduleis a vector containing all round keys for the encryption. This vector can be obtained with the functionkey_expand. Based on the length of this vector, the different versions of AES are dispatched.
Returns
A MVector{16,T} containing the 16-byte long encrypted block.
CryptoSideChannel.AES.AES_decrypt_expanded — FunctionAES_decrypt_expanded(ciphertext::MVector{16,T}, key::Vector{T})::MVector{16,T} where TDecrypt a block of 16 bytes with AES, given an already expanded key schedule.
Arguments
plaintextmust be a mutable, statically sized Vector of length 16. It contains the text to decrypt.key_scheduleis a vector containing all round keys for the decryption. This vector can be obtained with the functionkey_expand. Based on the length of this vector, the different versions of AES are dispatched.
Returns
A MVector{16,T} containing the 16-byte long decrypted block.
SPECK
Encryption and Decryption
CryptoSideChannel.SPECK.SPECK_encrypt — FunctionSPECK_encrypt(plaintext::Tuple{T, T}, key::Tuple{T, T}; rounds = 32)::Tuple{T,T} where TEncrypt plaintext using key with SPECK.
Arguments
plaintextis 128-bit data, split into two shares of typeT. Each share should contain 64 bits of the plaintext.Tcan be eitherUInt64or a similar custom integer type.keyis the 128-bit key, split into two shares of typeT. Each share should contain 64 bits of the plaintext.Tcan be eitherUInt64or a similar custom integer type.roundsis the number of rounds to execute. Defaults to32, since this is the number of rounds mentioned in the original specification of SPECK.
Returns
A Tuple{T,T} containing the 128-bit encrypted data in two shares of 64 bit.
T can be a custom integer type, but note that T must behave like UInt64. This includes truncating overflows in additions at 64 bit.
Example
The example is a SPECK128 test vector from the original SPECK paper
julia> key = (0x0f0e0d0c0b0a0908, 0x0706050403020100)
julia> plaintext = (0x6c61766975716520, 0x7469206564616d20)
julia> SPECK.SPECK_encrypt(plaintext, key)
(0xa65d985179783265, 0x7860fedf5c570d18)CryptoSideChannel.SPECK.SPECK_decrypt — FunctionSPECK_decrypt(ciphertext::Tuple{T, T}, key::Tuple{T, T}; rounds = 32)::Tuple{T,T} where TDecrypt ciphertext using key with SPECK.
Arguments
ciphertextis 128-bit data, split into two shares of typeT. Each share should contain 64 bits of the plaintext.Tcan be eitherUInt64or a similar custom integer type.keyis the 128-bit key, split into two shares of typeT. Each share should contain 64 bits of the plaintext.Tcan be eitherUInt64or a similar custom integer type.roundsis the number of rounds to execute. Defaults to32, since this is the number of rounds mentioned in the original specification of SPECK.
Returns
A Tuple{T,T} containing the 128-bit encrypted data in two shares of 64 bit.
T can be a custom integer type, but note that T must behave like UInt64. This includes truncating overflows in additions at 64 bit.
Example
The example is a SPECK128 test vector from the original SPECK paper
julia> key = (0x0f0e0d0c0b0a0908, 0x0706050403020100)
julia> plaintext = (0x6c61766975716520, 0x7469206564616d20)
julia> SPECK.SPECK_decrypt(ciphertext, key)
(0x6c61766975716520, 0x7469206564616d20)Internal Functions
CryptoSideChannel.SPECK.SPECK_key_expand — FunctionSPECK_key_expand(key::Tuple{T, T}, rounds)::Vector{T} where TExpand the key according to the SPECK key schedule. The result is a vector of length rounds, containing each round key. The first round key is the second component of key.
CryptoSideChannel.SPECK.SPECK_encrypt_expanded — FunctionSPECK_encrypt_expanded(pt::Tuple{T, T}, key_schedule::Vector{T}})::Tuple{T,T} where TEncrypts data with SPECK, given an already expanded key schedule. This schedule can be created with the function SPECK_key_expand.
CryptoSideChannel.SPECK.SPECK_decrypt_expanded — FunctionSPECK_decrypt_expanded(ct::Tuple{T, T}, key_schedule::Vector{T})::Tuple{T,T} where TDecrypts data with SPECK, given an already expanded key schedule. This schedule can be created with the function SPECK_key_expand.