-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from pluto/pushing_forward
Pushing forward
- Loading branch information
Showing
5 changed files
with
168 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
use crate::utils::{Stream, Block, stream_to_block, block_to_stream}; | ||
use crate::gctr::{gctr, increment_32}; | ||
use crate::ghash::ghash; | ||
use crate::aes::aes; | ||
|
||
pub fn aes_gcm(key: Stream, plaintext: Stream, iv: [u8; 12], aad: Stream) -> (Stream, Stream) { | ||
|
||
// step 1: generate hashkey as encryption of a zero block with AES | ||
let zero_block: Block = [[0; 4]; 4]; | ||
let hashkey = block_to_stream(aes(zero_block, key)); | ||
|
||
// step 2: generate jO as iv || 0 ^{31} || 1 where || is concatenation | ||
let mut j0 = [0; 16]; | ||
for i in 0..12 { | ||
j0[i] = iv[i]; | ||
} | ||
j0[15] = 1; | ||
let j0_block = stream_to_block(j0); | ||
|
||
// step 3: Let C=GCTRK(inc32(J0), P). | ||
let C = gctr(key, increment_32(j0_block), plaintext); | ||
// Define a block, S, as follows: | ||
// A is 16 bytes, 128 bits, C is 16 bytes, 128 bits, then two 64 bit numbers is 16 bytes so 3 16 byte blocks | ||
let mut S = [[0; 16]; 3]; | ||
S[0] = aad; | ||
S[1] = C; | ||
S[2] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,]; | ||
let res = ghash(hashkey, S); | ||
// S = GHASHH (A || 0v || C || 0u || [len(A)]64 || [len(C)]64). | ||
let T = gctr(key, j0_block, res); | ||
// // fn gctr(key: Stream, initial_counter_block: Block, plaintext: Stream) -> Stream { | ||
(C, T) | ||
} | ||
|
||
#[test] | ||
fn test_aes_gcm() { | ||
let key = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
let plainText = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
let iv = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
let expected_output = [0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78]; | ||
let (ciphertext, _tag) = aes_gcm(key, plainText, iv, aad); | ||
assert(ciphertext == expected_output); | ||
} | ||
|
||
#[test] | ||
fn test_aes_gcm_2() { | ||
let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; | ||
let iv = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; | ||
let msg = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; | ||
let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
let ct = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; | ||
let (ciphertext, _tag) = aes_gcm(key, msg, iv, aad); | ||
assert(ciphertext == ct); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
|
||
|
||
use crate::utils::{stream_xor, stream_to_block, block_to_stream, Stream, Block}; | ||
use crate::aes::{aes, add_round_key}; | ||
|
||
// starting with fixed size input | ||
// TODO(WJ 2024-10-10): make this work for arbitrary length input | ||
fn gctr(key: Stream, initial_counter_block: Block, plaintext: Stream) -> Stream { | ||
let mut ciphertext: Block = [[0; 4]; 4]; | ||
let pt_blocks = [stream_to_block(plaintext)]; | ||
let mut counter_block = initial_counter_block; | ||
for block in pt_blocks { | ||
// encrypt counter block | ||
let encrypted_counter_block = aes(counter_block, key); | ||
// xor with plaintext | ||
ciphertext = add_cipher(encrypted_counter_block, block); | ||
// update counter block | ||
counter_block = increment_32(counter_block); | ||
} | ||
block_to_stream(ciphertext) | ||
} | ||
|
||
fn increment_32(counter_block: Block) -> Block { | ||
let mut stream = block_to_stream(counter_block); | ||
let mut word = [stream[12], stream[13], stream[14], stream[15]]; | ||
let incremented = increment_word(word); | ||
stream[12] = incremented[0]; | ||
stream[13] = incremented[1]; | ||
stream[14] = incremented[2]; | ||
stream[15] = incremented[3]; | ||
stream_to_block(stream) | ||
} | ||
|
||
|
||
fn add_cipher(state: Block, key: Block) -> Block { | ||
let mut new_state: Block = [[0; 4]; 4]; | ||
for i in 0..4 { | ||
for j in 0..4 { | ||
new_state[i][j] = state[i][j] ^ key[i][j]; | ||
} | ||
} | ||
new_state | ||
} | ||
|
||
/// carry adder on 4 byte words | ||
fn increment_word(word: [u8; 4]) -> [u8; 4] { | ||
let mut incremented = [word[3], word[2], word[1], word[0]]; | ||
let mut carry = 1; | ||
for i in 0..4 { | ||
if incremented[i] == 0xFF { | ||
incremented[i] = 0x00; | ||
carry = 1; | ||
} else { | ||
incremented[i] += carry; | ||
carry = 0; | ||
} | ||
} | ||
[incremented[3], incremented[2], incremented[1], incremented[0]] | ||
} | ||
#[test] | ||
fn test_increment_word() { | ||
let word = [0x00, 0x00, 0x00, 0x00]; | ||
let expected_incremented_word = [0x00, 0x00, 0x00, 0x01]; | ||
assert(increment_word(word) == expected_incremented_word); | ||
|
||
let word = [0x00, 0x00, 0x00, 0xFF]; | ||
let expected_incremented_word = [0x00, 0x00, 0x01, 0x00]; | ||
assert(increment_word(word) == expected_incremented_word); | ||
|
||
let word = [0x00, 0x00, 0xFF, 0xFF]; | ||
let expected_incremented_word = [0x00, 0x01, 0x00, 0x00]; | ||
assert(increment_word(word) == expected_incremented_word); | ||
|
||
let word = [0xFF, 0xFF, 0xFF, 0xFF]; | ||
let expected_incremented_word = [0x00, 0x00, 0x00, 0x00]; | ||
assert(increment_word(word) == expected_incremented_word); | ||
} | ||
|
||
|
||
#[test] | ||
fn test_gctr() { | ||
let key = [0xca, 0xaa, 0x3f, 0x6f, 0xd3, 0x18, 0x22, 0xed, 0x2d, 0x21, 0x25, 0xf2, 0x25, 0xb0, 0x16, 0x9f]; | ||
let initial_counter_block: Block = [[0x7f,0x48,0x12,0x00],[0x6d,0x3e,0xfa,0x00],[0x90,0x8c,0x55,0x00],[0x41,0x14,0x2a,0x02]]; | ||
let plaintext = [0x84, 0xc9, 0x07, 0xb1, 0x1a, 0xe3, 0xb7, 0x9f,0xc4, 0x45, 0x1d, 0x1b, 0xf1, 0x7f, 0x4a, 0x99]; | ||
let expected_ciphertext = [0xfd, 0xb4, 0xaa, 0xfa, 0x35, 0x19, 0xd3, 0xc0,0x55, 0xbe, 0x8b, 0x34, 0x77, 0x64, 0xea, 0x33]; | ||
let ciphertext = gctr(key, initial_counter_block, plaintext); | ||
assert(ciphertext == expected_ciphertext); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
mod utils; | ||
mod ghash; | ||
mod aes; | ||
|
||
mod gctr; | ||
mod aes_gcm; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters