This commit is contained in:
parent
55f4546a9f
commit
fe21c8548d
164
school/intro-crypto/uebung/06/06.tex
Normal file
164
school/intro-crypto/uebung/06/06.tex
Normal file
@ -0,0 +1,164 @@
|
||||
\documentclass[12pt,a4paper,german]{article}
|
||||
\usepackage{url}
|
||||
%\usepackage{graphics}
|
||||
\usepackage{times}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{pifont}
|
||||
\usepackage{ngerman}
|
||||
\usepackage{float}
|
||||
\usepackage{diagbox}
|
||||
\usepackage[latin1]{inputenc}
|
||||
\usepackage{geometry}
|
||||
\usepackage{amsfonts}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{delarray}
|
||||
% \usepackage{minted}
|
||||
\usepackage{csquotes}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{epsfig}
|
||||
\usepackage{longtable}
|
||||
\usepackage{paralist}
|
||||
\geometry{left=2.0cm,textwidth=17cm,top=3.5cm,textheight=23cm}
|
||||
|
||||
\graphicspath{.}
|
||||
|
||||
%%%%%%%%%% Fill out the the definitions %%%%%%%%%
|
||||
\def \name {Valentin Brandl} %
|
||||
\def \matrikel {108018274494} %
|
||||
% \def \pname {Vorname2 Nachname2} %
|
||||
% \def \pmatrikel {Matrikelnummer2} %
|
||||
\def \gruppe {Gruppe 193} %
|
||||
\def \uebung {6} %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% DO NOT MODIFY THIS HEADER
|
||||
\newcommand{\hwsol}{
|
||||
\vspace*{-2cm}
|
||||
\noindent \matrikel \quad \name \hfill Gruppe:\gruppe \\
|
||||
% \noindent \pmatrikel \quad \pname \\
|
||||
\begin{center}{\Large \bf L\"osung f\"ur \"Ubung \# \uebung}\end{center}
|
||||
}
|
||||
|
||||
\newcommand{\cmark}{\ding{51}}%
|
||||
\newcommand{\xmark}{\ding{55}}%
|
||||
\newcommand{\csquare}{\text{\rlap{$\checkmark$}}\square}%
|
||||
|
||||
\begin{document}
|
||||
%Import header
|
||||
\hwsol
|
||||
|
||||
|
||||
\section*{Aufgabe 1}
|
||||
|
||||
\begin{enumerate}[a)]
|
||||
|
||||
\item Ein einzelner der im Paper beschriebenen FPGAs kann 400.000.000 (400 Millionen) Schlüssel pro Sekunde testen.
|
||||
|
||||
\item Der Average Case einer Schlüsselsuche eines $n$-Bit Schlüssels beträgt $2^n / 2$ und der worst-case beträgt
|
||||
$2^n$, ist also um Faktor 2 langsamer. Der average-case für DES auf einem COPACOBANA beträgt 9 Tage, der
|
||||
worst-case sind also 18 Tage.
|
||||
|
||||
\item Anzahl der Verdoppelungen nach Moore's Law: $((2019 - 2006) * 12) / 18 = 8,6667 \approx 9$
|
||||
|
||||
Average Case zum Brechen von DES in 2006: 9 Tage
|
||||
|
||||
Verbesserung nach $9$ Iterationen von Moore's Law: $9 / (2^9) = 0,0176$
|
||||
|
||||
Im average case lässt sich eine DES-Schlüsselsuche 2019 in weniger als einem Tag durchführen (weniger als einer
|
||||
halben Stunde).
|
||||
|
||||
Mit $8$ Iterationen gerechnet, kommt man auf $9 / (2^8) = 0,0351$ Tage, also knapp unter $1$ Stunde.
|
||||
|
||||
\item Eine Implementierung als FPGA ist deutlich schneller, als eine Software Implementierung auf general purpose
|
||||
Hardware zu den selben Kosten. Eine Implementierung als ASIC lässt sich nur verwenden um einen bestimmten
|
||||
Algorithmus anzugreifen, während man FPGAs neu programmieren kann, um anderen Algorithmen anzugreifen.
|
||||
|
||||
\item Ein einzelner FPGA konnte 2006 400 Millionen Schlüssel pro Sekunde testen. Unter Anwendung von 8 Iterationen
|
||||
von Moore's Law (siehe c)) ergibt sich daraus eine Leistung von $400000000 * 2^8 = 102.400.000.000$ Schlüssel
|
||||
pro Sekunde im Jahr 2019
|
||||
|
||||
Ein COPACOBANA enthält 120 FPGAs, von denen jeder $102400000000$ Schlüssel pro Sekunde testen kann. Der gesamte
|
||||
COPACOBANA kann also $120 * 102400000000 = 12288000000000$ Schlüssel pro Sekunde testen.
|
||||
|
||||
15000 COPACOBANA kommen also auf $15000 * 12.288.000.000.000 = 184.320.000.000.000.000$ Schlüssel pro Sekunde.
|
||||
|
||||
Eine Blockchiffre mit einer Schlüssellänge von 128-bit hat $2^{128}$ Mögliche Schlüssel. Eine durchschnittliche
|
||||
Schlüsselsuche muss also $2^{128} / 2$ Schlüssel testen.
|
||||
|
||||
Sei $p = 184.320.000.000.000.000 \frac{k}{s}$ (Schlüssel pro Sekunde) die Leistung des COPACOBANA Clusters und
|
||||
$r = (2^{128} / 2) k$ die Anzahl der zu testenden Schlüssel, ergibt sich die Dauer des Angriffs mit $\frac{r}{p}
|
||||
= \frac{(2^{128} / 2)}{184.320.000.000.000.000} s \approx 9.231 * 10^{20} \approx 2.564 * 10^{17} h \approx
|
||||
1.068 * 10^{16} d \approx 29271308980213 y$
|
||||
|
||||
\item Benötigte Rechenleistung $p$ (in Schlüssel pro Sekunde) um eine 128-bit Blockchiffre mit einer durchschnittlichen
|
||||
Suchzeit von 24 Stunden zu brechen:
|
||||
|
||||
$86400 = \frac{2^{128}/2}{p} \Rightarrow p = 1.969.226.660.422.097.589.487.121.570.785.695 \approx 1.969 *
|
||||
10^{30}$
|
||||
|
||||
\begin{align*}
|
||||
12288000000000 * (2^x) &> 1.969 * 10^{30} \\
|
||||
\Rightarrow x &> 57153
|
||||
\end{align*}
|
||||
|
||||
Nach $57153$ Iterationen von Moore's Law, also $57153 * 18m = 1028754m \approx 85730y$, lässt sich eine 128-bit
|
||||
Blockchiffre in weniger als 24 Stunden brechen. Das ist im Jahr $85730 + 2019 = 87749$
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
\section*{Aufgabe 2}
|
||||
|
||||
\begin{enumerate}[a)]
|
||||
|
||||
\item
|
||||
|
||||
\begin{enumerate}[1.]
|
||||
\item Ausgabe der f-Box $f_{out} = R_1 \oplus L_0$
|
||||
|
||||
\item Ausgabe der S-Boxen $s_{out} = P^{-1}(f_{out})$
|
||||
|
||||
\item Mit $s_{out}$ lässt sich der Input der S-Boxen $s_{in}$ einschränken
|
||||
|
||||
\item $k_1 = E(R_0) \oplus s_{in}$
|
||||
\end{enumerate}
|
||||
|
||||
\item Jede S-Box hat $2^6 = 64$ Mögliche Eingangswerte und $2^4 = 16$ Mögliche Ausgangswerte
|
||||
|
||||
$\Rightarrow 64/16 = 4 \Rightarrow$ ca $4^8 = 65536$ Kandidaten
|
||||
|
||||
\item Berechnungen wurden mit dem im Anhang befindlichen Code durchgeführt. Die inverse der P-Box wurde per Hand
|
||||
erstellt.
|
||||
|
||||
$s_{out_1}$ für $X_1,Y_1$: 0111 1101 1001 0101 1011 1100 1001 0000 $\Rightarrow$ 7 13 9 5 11 12 9 0
|
||||
|
||||
Mögliche Werte für $s_{in_1}$: $\{011110,000101,110110,101111\}$ $\{011010,000011,101100,100001\}$
|
||||
$\{000100,000111,100110,101011\}$ $\{010110,000111,111000,110101\}$ $\{001100, 000011, 100110,100001\}$
|
||||
$\{000000,001011,101100,100111\}$ $\{010100, 001011,111100, 110001\}$ $\{011010,011001,110000,110111\}$
|
||||
|
||||
$s_{out_2}$ für $X_2,Y_2$: 1000 0101 1101 0011 0010 0010 0110 1000 $\Rightarrow$ 8 5 13 3 2 2 6 8
|
||||
|
||||
Mögliche Werte für $s_{in_2}$: $\{001110, 011111,100110,100101\}$ $\{011100,011111,110000,111011\}$ $\{010010,
|
||||
000001,100000,100101\}$ $\{000110, 001111,110100,100001\}$ $\{000000,000101,100010,101101\}$
|
||||
$\{001010,000111,101000,100101\}$ $\{011100,011111,110100,100001\}$ $\{010000, 000111,111110,101101\}$
|
||||
|
||||
$e_{out_1} =$ 011101010011001011101000000000010000000000000000
|
||||
|
||||
$e_{out_2} =$ 101010000001001001111000000000010000000000000000
|
||||
|
||||
Weiterer Ansatz: Alle $4^8$ Permutationen von $s_{in_1}$ und $s_{in_2}$ erzeugen und die Ergebnisse $\oplus
|
||||
e_{out_1}$ bzw. $e_{out_2}$ rechnen. Die Schnittmenge aus dem ersten und zweiten Schritt bilden. Diese
|
||||
Schnittmenge enthält die Schlüsselkandidaten.
|
||||
|
||||
\item PC-2 hat $2^{56}$ mögliche Inputs und $2^{48}$ mögliche Outputs.
|
||||
|
||||
$2^{56} / 2^{48} = 1024$ Kandidaten
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
% \section*{Code}
|
||||
|
||||
% \inputminted{rust}{./school/intro-crypto/uebung/06/des/src/main.rs}
|
||||
|
||||
\end{document}
|
||||
|
BIN
school/intro-crypto/uebung/06/ches2006_copa.pdf
Normal file
BIN
school/intro-crypto/uebung/06/ches2006_copa.pdf
Normal file
Binary file not shown.
2
school/intro-crypto/uebung/06/des/.gitignore
vendored
Normal file
2
school/intro-crypto/uebung/06/des/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
**/*.rs.bk
|
4
school/intro-crypto/uebung/06/des/Cargo.lock
generated
Normal file
4
school/intro-crypto/uebung/06/des/Cargo.lock
generated
Normal file
@ -0,0 +1,4 @@
|
||||
[[package]]
|
||||
name = "des"
|
||||
version = "0.1.0"
|
||||
|
6
school/intro-crypto/uebung/06/des/Cargo.toml
Normal file
6
school/intro-crypto/uebung/06/des/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "des"
|
||||
version = "0.1.0"
|
||||
authors = ["Valentin Brandl <vbrandl@riseup.net>"]
|
||||
|
||||
[dependencies]
|
235
school/intro-crypto/uebung/06/des/src/main.rs
Normal file
235
school/intro-crypto/uebung/06/des/src/main.rs
Normal file
@ -0,0 +1,235 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
const P_1: [usize; 32] = [
|
||||
9, 17, 23, 31, 13, 28, 2, 18, 24, 16, 30, 6, 26, 20, 10, 1, 8, 14, 25, 3, 4, 29, 11, 19, 32,
|
||||
12, 22, 7, 5, 27, 15, 21,
|
||||
];
|
||||
|
||||
const P: [usize; 32] = [
|
||||
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19,
|
||||
13, 30, 6, 22, 11, 4, 25,
|
||||
];
|
||||
|
||||
const E: [usize; 48] = [
|
||||
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18,
|
||||
19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1,
|
||||
];
|
||||
|
||||
fn permutate<T: Copy + Default>(i: &[T], b: &[usize]) -> Vec<T> {
|
||||
let mut res: Vec<_> = (0..b.len()).map(|_| T::default()).collect();
|
||||
for (i, p) in i.iter().zip(b.iter()) {
|
||||
res[*p - 1] = *i;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
trait Split {
|
||||
fn split(&self) -> (u32, u32);
|
||||
}
|
||||
|
||||
impl Split for u64 {
|
||||
fn split(&self) -> (u32, u32) {
|
||||
((*self >> 32) as u32, *self as u32)
|
||||
}
|
||||
}
|
||||
|
||||
fn xor(a: &[bool], b: &[bool]) -> Vec<bool> {
|
||||
assert!(a.len() == b.len());
|
||||
a.iter().zip(b.iter()).map(|(a, b)| a ^ b).collect()
|
||||
}
|
||||
|
||||
fn to_bin<T: std::fmt::Binary>(i: T) -> Vec<bool> {
|
||||
format!("{:b}", i)
|
||||
.chars()
|
||||
.map(|c| if c == '1' { true } else { false })
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn show(b: &[bool], split: u8) {
|
||||
let mut i = 1;
|
||||
b.iter().map(|c| if *c { '1' } else { '0' }).for_each(|c| {
|
||||
print!("{}", c);
|
||||
if i % split == 0 {
|
||||
print!(" ");
|
||||
}
|
||||
i += 1;
|
||||
});
|
||||
println!();
|
||||
}
|
||||
|
||||
fn reverse_des(i: u64, o: u64) {
|
||||
let (l0, r0) = i.split();
|
||||
let (l1, r1) = o.split();
|
||||
let e_out = permutate(&to_bin(r0), &E);
|
||||
println!("e_out: ");
|
||||
show(&e_out, 100);
|
||||
let f_out = r1 ^ l0;
|
||||
let s_out = permutate(&to_bin(f_out), &P_1);
|
||||
assert!(&to_bin(f_out) == &permutate(&s_out, &P));
|
||||
println!("s_out: ");
|
||||
show(&s_out, 4);
|
||||
println!();
|
||||
}
|
||||
|
||||
fn do_it(s: &[[[bool; 6]; 4]], x: &[bool]) -> HashSet<Vec<bool>> {
|
||||
let mut set1 = HashSet::new();
|
||||
|
||||
for a in s[0].iter() {
|
||||
for b in s[1].iter() {
|
||||
for c in s[2].iter() {
|
||||
for d in s[3].iter() {
|
||||
for e in s[4].iter() {
|
||||
for f in s[5].iter() {
|
||||
for g in s[6].iter() {
|
||||
for h in s[7].iter() {
|
||||
let mut v = Vec::with_capacity(48);
|
||||
v.extend(a);
|
||||
v.extend(b);
|
||||
v.extend(c);
|
||||
v.extend(d);
|
||||
v.extend(e);
|
||||
v.extend(f);
|
||||
v.extend(g);
|
||||
v.extend(h);
|
||||
let r = xor(&v, x);
|
||||
set1.insert(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
set1
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x1: u64 = 0xF57DDDB12EAA799D;
|
||||
let y1: u64 = 0x2EAA799D332924D8;
|
||||
let x2: u64 = 0x15837977D5202437;
|
||||
let y2: u64 = 0xD5202437B5D8FC31;
|
||||
|
||||
let s_in_1 = [
|
||||
[
|
||||
[false, true, true, true, true, false],
|
||||
[false, false, false, true, false, true],
|
||||
[true, true, false, true, true, false],
|
||||
[true, false, true, true, true, true],
|
||||
],
|
||||
[
|
||||
[false, true, true, false, true, false],
|
||||
[false, false, false, false, true, true],
|
||||
[true, false, true, true, false, false],
|
||||
[true, false, false, false, false, true],
|
||||
],
|
||||
[
|
||||
[false, false, false, true, false, false],
|
||||
[false, false, false, true, true, true],
|
||||
[true, false, false, true, true, false],
|
||||
[true, false, true, false, true, true],
|
||||
],
|
||||
[
|
||||
[false, true, false, true, true, false],
|
||||
[false, false, false, true, true, true],
|
||||
[true, true, true, false, false, false],
|
||||
[true, true, false, true, false, true],
|
||||
],
|
||||
[
|
||||
[false, false, true, true, false, false],
|
||||
[false, false, false, false, true, true],
|
||||
[true, false, false, true, true, false],
|
||||
[true, false, false, false, false, true],
|
||||
],
|
||||
[
|
||||
[false, false, false, false, false, false],
|
||||
[false, false, true, false, true, true],
|
||||
[true, false, true, true, false, false],
|
||||
[true, false, false, true, true, true],
|
||||
],
|
||||
[
|
||||
[false, true, false, true, false, false],
|
||||
[false, false, true, false, true, true],
|
||||
[true, true, true, true, false, false],
|
||||
[true, true, false, false, false, true],
|
||||
],
|
||||
[
|
||||
[false, true, true, false, true, false],
|
||||
[false, true, true, false, false, true],
|
||||
[true, true, false, false, false, false],
|
||||
[true, true, false, true, true, true],
|
||||
],
|
||||
];
|
||||
let e_out_1 = [
|
||||
false, true, true, true, false, true, false, true, false, false, true, true, false, false,
|
||||
true, false, true, true, true, false, true, false, false, false, false, false, false,
|
||||
false, false, false, false, true, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false,
|
||||
];
|
||||
|
||||
let s_in_2 = [
|
||||
[
|
||||
[false, false, true, true, true, false],
|
||||
[false, true, true, true, true, true],
|
||||
[true, false, false, true, true, false],
|
||||
[true, false, false, true, false, true],
|
||||
],
|
||||
[
|
||||
[false, true, true, true, false, false],
|
||||
[false, true, true, true, true, true],
|
||||
[true, true, false, false, false, false],
|
||||
[true, true, true, false, true, true],
|
||||
],
|
||||
[
|
||||
[false, true, false, false, true, false],
|
||||
[false, false, false, false, false, true],
|
||||
[true, false, false, false, false, false],
|
||||
[true, false, false, true, false, true],
|
||||
],
|
||||
[
|
||||
[false, false, false, true, true, false],
|
||||
[false, false, true, true, true, true],
|
||||
[true, true, false, true, false, false],
|
||||
[true, false, false, false, false, true],
|
||||
],
|
||||
[
|
||||
[false, false, false, false, false, false],
|
||||
[false, false, false, true, false, true],
|
||||
[true, false, false, false, true, false],
|
||||
[true, false, true, true, false, true],
|
||||
],
|
||||
[
|
||||
[false, false, true, false, true, false],
|
||||
[false, false, false, true, true, true],
|
||||
[true, false, true, false, false, false],
|
||||
[true, false, false, true, false, true],
|
||||
],
|
||||
[
|
||||
[false, true, true, true, false, false],
|
||||
[false, true, true, true, true, true],
|
||||
[true, true, false, true, false, false],
|
||||
[true, false, false, false, false, true],
|
||||
],
|
||||
[
|
||||
[false, true, false, false, false, false],
|
||||
[false, false, false, true, true, true],
|
||||
[true, true, true, true, true, false],
|
||||
[true, false, true, true, false, true],
|
||||
],
|
||||
];
|
||||
let e_out_2 = [
|
||||
true, false, true, false, true, false, false, false, false, false, false, true, false,
|
||||
false, true, false, false, true, true, true, true, false, false, false, false, false,
|
||||
false, false, false, false, false, true, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false,
|
||||
];
|
||||
|
||||
let set1 = do_it(&s_in_1, &e_out_1);
|
||||
let set2 = do_it(&s_in_2, &e_out_2);
|
||||
|
||||
let intersection: HashSet<_> = set1.intersection(&set2).collect();
|
||||
println!("{}", intersection.len());
|
||||
|
||||
// reverse_des(x1, y1);
|
||||
// reverse_des(x2, y2);
|
||||
}
|
BIN
school/intro-crypto/uebung/06/Übung_6_EK1_WS1819.pdf
Normal file
BIN
school/intro-crypto/uebung/06/Übung_6_EK1_WS1819.pdf
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user