-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(ciphers): AES encryption #102
Changes from all commits
4d7a820
7ca5c8f
99ed9fb
8fa05c5
3720215
f2d5536
3d17aa9
30fb784
f0c09dc
20a2c18
1b4181f
a04aefa
7cc2262
8ec79f3
399566e
dbbe0f2
7cd117b
b5cbc80
d93a822
c7e50b5
9665d74
126b88c
7bb965a
103e9f3
8e9e2d5
cdf9ed0
add5456
e4908da
c54a7c7
3a5022b
1ee1209
ed9d66a
c3b924a
6469574
a59cab2
c1d200b
f0e38d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
# AES encryption | ||
|
||
[Advanced Encryption Standard][aes] (AES) is a symmetric-key algorithm and is a variant of the Rijndael (pronounced 'rain-dull') block cipher. AES supersedes the [Data Encryption Standard][des] (DES). | ||
|
||
## Overview | ||
|
||
AES supports a block size of 128 bits, and three different key lengths: 128, 192, and 256 bits. It manipulates _bytes_ instead of _individual bits_ or _64-bit words_, and views a 16-byte plaintext as a 2D column-major grid of bytes. | ||
|
||
AES uses [Substitution-Permutation Network (SPN)][spn] which makes use of two main properties: _confusion_ and _diffusion_. Confusion means that the input undergoes complex transformations, and diffusion means that these transformations depend equally on all bits of the input. | ||
|
||
Unlike DES, it does not use a Feistel network, and most AES calculations are done in a particular finite field. | ||
|
||
|
||
## Algorithm | ||
|
||
The core encryption algorithm consists of the following routines: | ||
- [KeyExpansion](#KeyExpansion) | ||
- [AddRoundKey](#AddRoundKey) | ||
- [SubBytes](#SubBytes) | ||
- [ShiftRows](#ShiftRows) | ||
- [MixColumns](#MixColumns) | ||
|
||
For decryption, we take the inverses of these routines: | ||
|
||
TODO | ||
|
||
### Encryption | ||
|
||
Encryption consists of rounds of the above routines, with the number of rounds being determined by the size of the key. Keys of length 128/192/256 bits require 10/12/14 rounds respectively. | ||
|
||
Round *1* is always just *AddRoundKey*. For rounds *2* to *N-1*, the algorithm uses a mix of *SubBytes*, *ShiftRows*, *MixColumns*, and *AddRoundKey*, and the last round is the same except without *MixColumns*. | ||
|
||
#### KeyExpansion | ||
|
||
The **KeyExpansion** algorithm takes a 128/192/156-bit key and turns it into 11/13/15 round keys respectively of 16 bytes each. The main trick to key expansion is the fact that if 1 bit of the encryption key is changed, it should affect the round keys for several rounds. | ||
|
||
Using different keys for each round protects against _[slide attacks]_. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we link a resource on slide attacks? Would be nice to write a test for them at some point if it's not too crazy There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes i 100% agree. An example of this would be amazing! If you don't do it in this PR (which, by no means, do you have to) can you make an issue? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Filed an issue: #120 (comment) |
||
|
||
To generate more round keys out of the original key, we do a series of word rotation and/or substitution XOR'd with round constants, depending on the round number that we are in. | ||
|
||
For round **i**, if i is a multiple of the length of the key (in words): | ||
|
||
```rust | ||
Self::rotate_word(&mut last); | ||
word = (u32::from_le_bytes(Self::sub_word(last)) | ||
^ u32::from_le_bytes(ROUND_CONSTANTS[(i / key_len) - 1])) | ||
.to_le_bytes(); | ||
``` | ||
|
||
if i + 4 is a multiple of 8: | ||
|
||
```rust | ||
word = Self::sub_word(last) | ||
``` | ||
|
||
The final step is always to XOR previous round's round key with the *(i - key_len)*-th round key: | ||
|
||
```rust | ||
let round_key = expanded_key[i - key_len] | ||
.iter() | ||
.zip(last.iter()) | ||
.map(|(w, l)| w ^ l) | ||
.collect_vec() | ||
.try_into() | ||
.unwrap(); | ||
``` | ||
|
||
#### AddRoundKey | ||
|
||
XORs a round key to the internal state. | ||
|
||
#### SubBytes | ||
|
||
Substitutes each byte in the `State` with another byte according to a [substitution box](#substitution-box). | ||
|
||
#### ShiftRow | ||
|
||
Shift i-th row of i positions, for i ranging from 0 to 3, eg. Row 0: no shift occurs, row 1: a left shift of 1 position occurs. | ||
|
||
#### MixColumns | ||
|
||
Each column of bytes is treated as a 4-term polynomial, multiplied modulo x^4 + 1 with a fixed polynomial | ||
a(x) = 3x^3 + x^2 + x + 2. This is done using matrix multiplication. | ||
|
||
More details can be found [here][mixcolumns]. | ||
|
||
|
||
### Decryption | ||
|
||
TODO | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Either address the todo or elaborate in a comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Filed an issue for decryption: #119 |
||
|
||
## Substitution Box | ||
|
||
A substitution box is a basic component of symmetric key algorithms | ||
performs substitution. It is used to obscure the relationship | ||
the key and the ciphertext as part of the *confusion* property. | ||
|
||
During substitution, a byte is interpreted as a polynomial and | ||
mapped to its multiplicative inverse in [Rijndael's finite field][Rijndael ff]: GF(2^8) = GF(2)[x]/(x^8 + x^4 + x^3 + x + 1). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Awesome! |
||
|
||
The inverse is then transformed using an affine transformation which is the sum of multiple rotations of the byte as a vector, where addition is the XOR operation. The result is an 8-bit output array which is used to substitute the original byte. | ||
|
||
## Security | ||
|
||
Fundamentally, AES is secure because all output bits depend on all input bits in some complex, pseudorandom way. The biggest threat to block ciphers is in their modes of operation, not their core algorithms. | ||
|
||
## Practical implementations | ||
|
||
In production-level AES code, fast AES software uses special techniques called table-based implementations which replaces the *SubBytes-ShiftRows-MixColumns* sequence with a combination of XORs and lookups in hardcoded tables loaded in memory during execution time. | ||
|
||
## References | ||
|
||
- [FIPS197](fips197) | ||
- [Serious Cryptography - A Practical Introduction to Modern Cryptography](seriouscrypto) | ||
|
||
[aes]: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard | ||
[des]: ../des/README.md | ||
[spn]: https://en.wikipedia.org/wiki/Substitution%E2%80%93permutation_network | ||
[slide attacks]: https://en.wikipedia.org/wiki/Slide_attack | ||
[mixcolumns]: https://en.wikipedia.org/wiki/Rijndael_MixColumns | ||
[Rijndael ff]: https://en.wikipedia.org/wiki/Finite_field_arithmetic#Rijndael's_(AES)_finite_field | ||
[fips197]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf | ||
[seriouscrypto]:https://nostarch.com/seriouscrypto |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Complete or add more detail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah, was thinking to leave decryption for a followup PR - apologies for not being clear about that, but I could also complete it within the same PR (if that's preferable)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine either way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filed an issue for decryption: #119