Add crypto exercise
All checks were successful
the build was successful

This commit is contained in:
Valentin Brandl 2018-12-06 00:05:43 +01:00
parent 55f4546a9f
commit fe21c8548d
No known key found for this signature in database
GPG Key ID: 30D341DD34118D7D
7 changed files with 411 additions and 0 deletions

View 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}

Binary file not shown.

View File

@ -0,0 +1,2 @@
/target
**/*.rs.bk

View File

@ -0,0 +1,4 @@
[[package]]
name = "des"
version = "0.1.0"

View File

@ -0,0 +1,6 @@
[package]
name = "des"
version = "0.1.0"
authors = ["Valentin Brandl <vbrandl@riseup.net>"]
[dependencies]

View 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);
}

Binary file not shown.