title: CPA Angriff auf Speck author: Robin Dietrich & Marius Schwarz
Speck | Blocklänge | Schlüssellänge | Runden |
---|---|---|---|
Speck3264 | 32 Bit | 64 Bit | 22 |
Speck4872 | 48 Bit | 72 Bit | 22 |
Speck4896 | 48 Bit | 96 Bit | 23 |
Speck6496 | 64 Bit | 96 Bit | 26 |
Speck64128 | 64 Bit | 128 Bit | 27 |
Speck9696 | 96 Bit | 96 Bit | 28 |
Speck96144 | 96 Bit | 144 Bit | 29 |
Speck128128 | 128 Bit | 128 Bit | 32 |
Speck128192 | 128 Bit | 192 Bit | 33 |
Speck1281256 | 128 Bit | 256 Bit | 34 |
pt = Plaintext Bytes Pt = Plaintext as 16 Bit Words
ct = Ciphertext Bytes Ct = Ciphertext as 16 Bit Words
k = Key as Bytes K = Key as 16 Bit Words
// Key Schedule
D=K[3], C=K[2], B=K[1], A=K[0]
for i in 0..<22
rk[i]=A
ER16(B, A, i++)
rk[i]=A
ER16(C, A, i++)
rk[i]=A
ER16(D, A, i++)
// Encryption
Ct[0]=Pt[0]; Ct[1]=Pt[1];
for i in 0..<22
ER16(Ct[1], Ct[0], rk[i++])
void FuncER16(u16 *x, u16 *y, u16 k)
{
u16 tmp_x = *x;
u16 tmp_y = *y;
*x = (((tmp_x)>>(7)) | ((tmp_x)<<(16-(7)))); // ROR(7)
*x += *y;
*x = *x ^ k;
*y = (((tmp_y)<<(2)) | (tmp_y>>(16-(2)))); // ROL(2)
*y = *y ^ *x;
}
$$HammingDistance(0100101, 0010101) = 2$$
Der Unterschied zweier per XOR verknüpfter Daten, wird als Hamming-Gewicht bezeichnet:
$$HammingDistance(0100101, 0010101) = HammingWeight(0100101 \oplus 0010101)$$
def simple_speck(plaintext, key):
Ct_0 = (int(plaintext[1]) << 8) + int(plaintext[0]) # RIGHT Key
Ct_1 = (int(plaintext[3]) << 8) + int(plaintext[2]) # LEFT Key
Ct_1, Ct_0 = ER16(Ct_1, Ct_0, key) # Calculate Roundfunction
return popcount((Ct_1 << 8) + Ct_0) # Return Hamming Weight (aka Popcount)
0) Simulation anhand des Modells mit $n$ traces 1) Generieren von $n$ zufälligen Klartexten mit fixem Keybyte (+ noise) 2) Simulation aller möglichen Keybytes per Hamming Weight 3) Berechnen des PCC aller Keys über alle traces
$\rightarrow$ Das korrekte Keybyte ist: 0x68
1) Implementierung von Speck auf CW 2) Aufzeichnen von $n$ Power Traces 3) Berechnung des Software Modells 4) Berechnen der Korrelationen zwischen Modell/Powertraces
- Keybyte für Keybyte
- Rückrechnen des Rundenschlüssels
rightkey = 0x00
for guess_key in range(256):
leftkey = model( (guess_key << 8) + righkey )
for guess_key in range(256):
rightkey = model( (leftkey << 8) + guess_key )
for i in 0..<22
ER16(Ct[1], Ct[0], rk[i++])
# -------------- for one key -----------------#
x = ((x << (16 - ALPHA)) + (x >> ALPHA)) & mod_mask # x = ROR(x, 7)
x = (x + y) & mod_mask # x = ADD(x, y)
x = x ^ knownkey[0]
# -------------- for second key -----------------#
y = ((y >> (16 - BETA)) + (y << BETA)) & mod_mask # y = ROL(y, 2)
y = y ^ x # y = XOR(y, x)
x = ((x << (16 - ALPHA)) + (x >> ALPHA)) & mod_mask # x = ROR(x, 7)
x = (x + y) & mod_mask # x = ADD(x, y)
x = x ^ knownkey[1] # x = XOR(x, k)
# -------------- for third key -----------------#
# [...]
ER16()
uint16_t XOR(uint16_t a, uint16_t b, int random) {
uint8_t tmp = random ^ 0x5F;
tmp ^= (random ^ a);
tmp ^= (tmp ^ b);
tmp &= (tmp & a);
tmp &= (tmp & b);
return a ^ b;
}
Random
wird bei jeder Verschlüsslung erneut generiert$\rightarrow$ Bypass konnte nicht realisiert werden