1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#![no_std]
#![forbid(unsafe_code)]
pub mod cipher_modes;
use crate::cipher_modes::ECB;
const ALPHA: u32 = 8;
const BETA: u32 = 3;
const ROUNDS: usize = 32;
#[inline(always)]
fn round(x: &mut u64, y: &mut u64, k: &u64) {
*x = x.rotate_right(ALPHA).wrapping_add(*y) ^ k;
*y = y.rotate_left(BETA) ^ *x;
}
#[inline(always)]
fn inv_round(x: &mut u64, y: &mut u64, k: &u64) {
*y = (*y ^ *x).rotate_right(BETA);
*x = (*x ^ *k).wrapping_sub(*y).rotate_left(ALPHA);
}
#[inline(always)]
fn key_schedule(k1: &mut u64, k2: &mut u64) -> [u64; ROUNDS] {
let mut schedule = [0u64; ROUNDS];
for i in 0..ROUNDS as u64 {
schedule[i as usize] = *k2;
round(k1, k2, &i)
}
schedule
}
pub struct Speck([u64; ROUNDS]);
impl Speck {
pub fn new(key: &u128) -> Self {
let mut k1 = (key >> 64) as u64;
let mut k2 = *key as u64;
Speck(key_schedule(&mut k1, &mut k2))
}
pub(crate) fn encrypt(&self, plaintext: &u128) -> u128 {
let mut chunk_1 = (plaintext >> 64) as u64;
let mut chunk_2 = *plaintext as u64;
for round_key in &self.0 {
round(&mut chunk_1, &mut chunk_2, round_key);
}
chunk_2 as u128 | (chunk_1 as u128) << 64
}
pub(crate) fn decrypt(&self, ciphertext: &u128) -> u128 {
let mut chunk_1 = (ciphertext >> 64) as u64;
let mut chunk_2 = *ciphertext as u64;
for round_key in self.0.iter().rev() {
inv_round(&mut chunk_1, &mut chunk_2, round_key);
}
chunk_2 as u128 | (chunk_1 as u128) << 64
}
}
impl ECB for Speck {
fn encrypt(&self, plaintext: &u128) -> u128 {
self.encrypt(plaintext)
}
fn decrypt(&self, ciphertext: &u128) -> u128 {
self.decrypt(ciphertext)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_speck128_128_encryption_and_decryption() {
let key: u128 = 0x0f0e0d0c0b0a09080706050403020100;
let plaintext: u128 = 0x6c617669757165207469206564616d20;
let ciphertext: u128 = 0xa65d9851797832657860fedf5c570d18;
let speck = Speck::new(&key);
assert_eq!(speck.encrypt(&plaintext), ciphertext);
assert_eq!(speck.decrypt(&ciphertext), plaintext);
}
#[test]
fn test_speck_ecb_mode() {
let key: u128 = 0x0f0e0d0c0b0a09080706050403020100;
let plaintext: u128 = 0x6c617669757165207469206564616d20;
let ciphertext: u128 = 0xa65d9851797832657860fedf5c570d18;
let speck = Speck::new(&key);
assert_eq!(<Speck as ECB>::encrypt(&speck, &plaintext), ciphertext);
assert_eq!(<Speck as ECB>::decrypt(&speck, &ciphertext), plaintext);
}
}