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 T
Encrypt 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
plaintext
must be a mutable, statically sized Vector of length 16. It contains the text to encrypt.key
is 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 T
Decrypt 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
ciphertext
must be a mutable, statically sized Vector of length 16. It contains the data to decrypt.key
is 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
k
is 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,k
must 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
k
is 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,k
must 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 T
Encrypt a block of 16 bytes with AES, given an already expanded key schedule
Arguments
plaintext
must be a mutable, statically sized Vector of length 16. It contains the text to encrypt.key_schedule
is 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 T
Decrypt a block of 16 bytes with AES, given an already expanded key schedule.
Arguments
plaintext
must be a mutable, statically sized Vector of length 16. It contains the text to decrypt.key_schedule
is 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 T
Encrypt plaintext
using key
with SPECK.
Arguments
plaintext
is 128-bit data, split into two shares of typeT
. Each share should contain 64 bits of the plaintext.T
can be eitherUInt64
or a similar custom integer type.key
is the 128-bit key, split into two shares of typeT
. Each share should contain 64 bits of the plaintext.T
can be eitherUInt64
or a similar custom integer type.rounds
is 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 T
Decrypt ciphertext
using key
with SPECK.
Arguments
ciphertext
is 128-bit data, split into two shares of typeT
. Each share should contain 64 bits of the plaintext.T
can be eitherUInt64
or a similar custom integer type.key
is the 128-bit key, split into two shares of typeT
. Each share should contain 64 bits of the plaintext.T
can be eitherUInt64
or a similar custom integer type.rounds
is 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 T
Expand 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 T
Encrypts 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 T
Decrypts data with SPECK, given an already expanded key schedule. This schedule can be created with the function SPECK_key_expand
.