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
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<68>ssel pro Sekunde testen.
\item Der Average Case einer Schl<68>sselsuche eines $n$-Bit Schl<68>ssels betr<74>gt $2^n / 2$ und der worst-case betr<74>gt
$2^n$, ist also um Faktor 2 langsamer. Der average-case f<>r DES auf einem COPACOBANA betr<74>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<68>sselsuche 2019 in weniger als einem Tag durchf<68>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<68>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<68>ssel
pro Sekunde im Jahr 2019
Ein COPACOBANA enth<74>lt 120 FPGAs, von denen jeder $102400000000$ Schl<68>ssel pro Sekunde testen kann. Der gesamte
COPACOBANA kann also $120 * 102400000000 = 12288000000000$ Schl<68>ssel pro Sekunde testen.
15000 COPACOBANA kommen also auf $15000 * 12.288.000.000.000 = 184.320.000.000.000.000$ Schl<68>ssel pro Sekunde.
Eine Blockchiffre mit einer Schl<68>ssell<6C>nge von 128-bit hat $2^{128}$ M<>gliche Schl<68>ssel. Eine durchschnittliche
Schl<68>sselsuche muss also $2^{128} / 2$ Schl<68>ssel testen.
Sei $p = 184.320.000.000.000.000 \frac{k}{s}$ (Schl<68>ssel pro Sekunde) die Leistung des COPACOBANA Clusters und
$r = (2^{128} / 2) k$ die Anzahl der zu testenden Schl<68>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<65>tigte Rechenleistung $p$ (in Schl<68>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<68>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<65>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<74>lt die Schl<68>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.