Skip to content

Commit a66fd23

Browse files
authored
implemented aes-ige block mode (#211)
1 parent 68c1756 commit a66fd23

13 files changed

+138
-2
lines changed

Cargo.lock

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

block-modes/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ keywords = ["crypto", "block-cipher", "ciphers"]
1212

1313
[dependencies]
1414
block-padding = "0.2"
15+
byte-tools = "0.3"
1516
cipher = "=0.3.0-pre"
1617

1718
[dev-dependencies]

block-modes/src/ige.rs

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
use crate::{
2+
traits::BlockMode,
3+
utils::{xor, Block},
4+
};
5+
use block_padding::Padding;
6+
use byte_tools::copy;
7+
use cipher::{
8+
block::{BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher},
9+
generic_array::{
10+
typenum::{Prod, UInt, UTerm, Unsigned, B0, B1, U2},
11+
ArrayLength, GenericArray,
12+
},
13+
};
14+
use core::{marker::PhantomData, ops::Mul};
15+
16+
type IgeIvBlockSize<C> = Prod<<C as BlockCipher>::BlockSize, U2>;
17+
18+
/// [Infinite Garble Extension][1] (IGE) block cipher mode instance.
19+
///
20+
/// [1]: https://www.links.org/files/openssl-ige.pdf
21+
pub struct Ige<C, P>
22+
where
23+
C: BlockCipher + NewBlockCipher + BlockEncrypt + BlockDecrypt,
24+
P: Padding,
25+
C::BlockSize: Mul<UInt<UInt<UTerm, B1>, B0>>,
26+
<C::BlockSize as Mul<UInt<UInt<UTerm, B1>, B0>>>::Output: ArrayLength<u8>,
27+
{
28+
cipher: C,
29+
iv: GenericArray<u8, IgeIvBlockSize<C>>,
30+
_p: PhantomData<P>,
31+
}
32+
33+
// Implementation derived from:
34+
// https://mgp25.com/AESIGE/
35+
36+
impl<C, P> BlockMode<C, P> for Ige<C, P>
37+
where
38+
C: BlockCipher + NewBlockCipher + BlockEncrypt + BlockDecrypt,
39+
P: Padding,
40+
C::BlockSize: Mul<UInt<UInt<UTerm, B1>, B0>>,
41+
<C::BlockSize as Mul<UInt<UInt<UTerm, B1>, B0>>>::Output: ArrayLength<u8>,
42+
{
43+
type IvSize = IgeIvBlockSize<C>;
44+
45+
fn new(cipher: C, iv: &GenericArray<u8, Self::IvSize>) -> Self {
46+
Ige {
47+
cipher,
48+
iv: iv.clone(),
49+
_p: Default::default(),
50+
}
51+
}
52+
53+
fn encrypt_blocks(&mut self, blocks: &mut [Block<C>]) {
54+
let block_size = C::BlockSize::to_usize();
55+
56+
let (mut y_prev, x_prev) = self.iv.split_at_mut(block_size);
57+
let mut x_temp = GenericArray::<u8, C::BlockSize>::default();
58+
59+
for block in blocks {
60+
copy(block, &mut x_temp);
61+
62+
xor(block, y_prev);
63+
64+
self.cipher.encrypt_block(block);
65+
66+
xor(block, x_prev);
67+
68+
copy(&x_temp, x_prev);
69+
y_prev = block;
70+
}
71+
}
72+
73+
fn decrypt_blocks(&mut self, blocks: &mut [Block<C>]) {
74+
let block_size = C::BlockSize::to_usize();
75+
76+
let (x_prev, mut y_prev) = self.iv.split_at_mut(block_size);
77+
let mut x_temp = GenericArray::<u8, C::BlockSize>::default();
78+
79+
for block in blocks {
80+
copy(block, &mut x_temp);
81+
82+
xor(block, y_prev);
83+
84+
self.cipher.decrypt_block(block);
85+
86+
xor(block, x_prev);
87+
88+
copy(&x_temp, x_prev);
89+
y_prev = block;
90+
}
91+
}
92+
}

block-modes/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ mod cbc;
9191
mod cfb;
9292
mod cfb8;
9393
mod ecb;
94+
mod ige;
9495
mod ofb;
9596
mod pcbc;
9697

@@ -103,6 +104,7 @@ pub use crate::{
103104
cfb8::Cfb8,
104105
ecb::Ecb,
105106
errors::{BlockModeError, InvalidKeyIvLength},
107+
ige::Ige,
106108
ofb::Ofb,
107109
pcbc::Pcbc,
108110
traits::BlockMode,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
��U{�R�ڎC�N�E<�V��H���ǜ��G��
32 Bytes
Binary file not shown.
16 Bytes
Binary file not shown.
32 Bytes
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
L. Let's hope Ben got it right!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mentation of IGE mode for OpenSS
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is an imple
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
�pd�����m��Kz�Hȹ�@>4g��ؓ@�;

block-modes/tests/lib.rs

+31-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
//! Test vectors generated with OpenSSL
22
33
use aes::Aes128;
4-
use block_modes::block_padding::ZeroPadding;
4+
use block_modes::block_padding::{NoPadding, ZeroPadding};
55
use block_modes::BlockMode;
6-
use block_modes::{Cbc, Ecb};
6+
use block_modes::{Cbc, Ecb, Ige};
7+
use cipher::generic_array::GenericArray;
78

89
#[test]
910
fn ecb_aes128() {
@@ -69,3 +70,31 @@ fn par_blocks() {
6970
run::<block_modes::Ofb<_, _>>();
7071
run::<block_modes::Pcbc<_, _>>();
7172
}
73+
74+
#[test]
75+
fn ige_aes256_1() {
76+
let key = GenericArray::from_slice(include_bytes!("data/ige-aes128-1.key.bin"));
77+
let iv = GenericArray::from_slice(include_bytes!("data/ige-aes128-1.iv.bin"));
78+
let plaintext = include_bytes!("data/ige-aes128-1.plaintext.bin");
79+
let ciphertext = include_bytes!("data/ige-aes128-1.ciphertext.bin");
80+
81+
let mode = Ige::<Aes128, NoPadding>::new_fix(key, iv);
82+
assert_eq!(mode.encrypt_vec(plaintext), &ciphertext[..]);
83+
84+
let mode = Ige::<Aes128, NoPadding>::new_fix(key, iv);
85+
assert_eq!(mode.decrypt_vec(ciphertext).unwrap(), &plaintext[..]);
86+
}
87+
88+
#[test]
89+
fn ige_aes256_2() {
90+
let key = GenericArray::from_slice(include_bytes!("data/ige-aes128-2.key.bin"));
91+
let iv = GenericArray::from_slice(include_bytes!("data/ige-aes128-2.iv.bin"));
92+
let plaintext = include_bytes!("data/ige-aes128-2.plaintext.bin");
93+
let ciphertext = include_bytes!("data/ige-aes128-2.ciphertext.bin");
94+
95+
let mode = Ige::<Aes128, NoPadding>::new_fix(key, iv);
96+
assert_eq!(mode.encrypt_vec(plaintext), &ciphertext[..]);
97+
98+
let mode = Ige::<Aes128, NoPadding>::new_fix(key, iv);
99+
assert_eq!(mode.decrypt_vec(ciphertext).unwrap(), &plaintext[..]);
100+
}

0 commit comments

Comments
 (0)