forked from monnerat/BUT2FI_R4.B.10
tp1
This commit is contained in:
parent
849f17f570
commit
2ba0a03f03
11
README.md
11
README.md
@ -1,3 +1,12 @@
|
|||||||
# BUT2FI_R4.B.10
|
# BUT2FI_R4.B.10
|
||||||
|
|
||||||
Cryptographie - Outils et algorithmes
|
Cryptographie - Outils et algorithmes
|
||||||
|
|
||||||
|
[Cours crypto](cours/crypto.pdf)
|
||||||
|
|
||||||
|
#### Semaine 1
|
||||||
|
- cm : [Chiffrements par bloc, algorithmes à clefs symétriques](cours/crypto.pdf).
|
||||||
|
- tp : [lfsr, tea, hachages](td_tp/tp1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
193
td_tp/tp1/README.md
Normal file
193
td_tp/tp1/README.md
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
# TP1
|
||||||
|
- Registre à décalage à rétroaction linéaire (lfsr),
|
||||||
|
- Chiffrement par bloc symmétrique (TEA), fonction de hachage.
|
||||||
|
|
||||||
|
## EX1
|
||||||
|
Le but est d'implanter un registre à décalage linéaire, sur un octet.
|
||||||
|
|
||||||
|
|
||||||
|
À chaque étape, le registre (un octet) $(b_7,b_6,b_5,b_4,b_3,b_2,b_1,b_0)$ est décalé à gauche, et
|
||||||
|
le bit $b_0$ est remplacé par un bit, calculé par une fonction linéaire $f$.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Vous disposez d'un [fichier](src/ex1/file.crypt) crypté avec un lfsr, en faisant
|
||||||
|
un XOR de chacun des octets avec les valeurs successives du registre. L'état
|
||||||
|
initial du registre était `0xa7`, et la fonction utilisée
|
||||||
|
|
||||||
|
|
||||||
|
\[
|
||||||
|
f(b_7,b_6,b_5,b_4,b_3,b_2,b_1,b_0) = b_7\oplus b_6\oplus b_5\oplus b_4\oplus b_3\oplus b_1
|
||||||
|
\]
|
||||||
|
|
||||||
|
Retrouver le fichier initial.
|
||||||
|
|
||||||
|
Vous pouvez utiliser la fonction interne `__builtin_parity` de `gcc`.
|
||||||
|
|
||||||
|
## Ex2
|
||||||
|
|
||||||
|
Tiny Encryption Algorithm est un algorithme de chiffrement symétrique par
|
||||||
|
bloc. les algorithmes de chiffrement sysmétrique par bloc crypte/decrypte des
|
||||||
|
**blocs** entiers, en utilisant la même clé secrète (symétrique). TEA est un
|
||||||
|
exemple simple de tels algorithmes (DES, AES, Blowfish) facile à implanter. La
|
||||||
|
plupart de ces algorithmes utilise ce que l\'on appelle un réseau de Feistel.
|
||||||
|
|
||||||
|
##### Réseau de Feistel
|
||||||
|
|
||||||
|
Désignons par $K$ la clé (un mot binaire). On décompose le bloc à
|
||||||
|
crypter en 2 moitiés $(L_0,R_0)$ On lui applique une
|
||||||
|
transformation de la forme :
|
||||||
|
|
||||||
|
\[
|
||||||
|
(L_0,R_0) \rightarrow (L_1,R_1)
|
||||||
|
\, où \,
|
||||||
|
\left\{\begin{matrix} L_1 & = & R_0 \\
|
||||||
|
R_1 & = & L_0 + f(R_0,K)
|
||||||
|
\end{matrix}\right.
|
||||||
|
\]
|
||||||
|
|
||||||
|
|
||||||
|
- La loi $+$ doit simplement être "réversible" (une loi de
|
||||||
|
groupe). Dans la pratique, il s'agit souvent d'un xor, mais pour
|
||||||
|
TEA, il s\'agit de l'addition binaire.
|
||||||
|
- La fonction $f$ n'a pas besoin d'être inversible pour que la
|
||||||
|
transformation précédente soit réversible.
|
||||||
|
|
||||||
|
Pourquoi ? Comment fait-on ?
|
||||||
|
- Le chiffrement consiste alors à itérer la transformation (appelée
|
||||||
|
round) un certain nombre de fois.
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img src="./img/feistel.png">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
##### XTEA
|
||||||
|
|
||||||
|
XTEA (cf cours) crypte des blocs de 8 octets, en utilisant une clé de 16 octets.
|
||||||
|
|
||||||
|
Un cycle (2 rounds, itéré 32 fois) de XTEA est donné par le réseau
|
||||||
|
suivant :
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
<img src="./img/xtea.png">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
En vert, il s'agit de l'addition binaire sur 32 bits, en rouge le xor.
|
||||||
|
|
||||||
|
- la clé est décomposée 4 sous-clés $K[0],K[1],K[2],K[3]$.
|
||||||
|
- chaque round utilise un multiple de $\delta = ( \sqrt{5} - 1 ) * 2^{31}$ pour rendre les rounds non symétriques.
|
||||||
|
|
||||||
|
Voici un exemple de code correspondant :
|
||||||
|
```c
|
||||||
|
void encrypt(uint32_t v[2], uint32_t const key[4])
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
|
||||||
|
for (i=0; i < 32; i++) {
|
||||||
|
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
|
||||||
|
sum += delta;
|
||||||
|
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
|
||||||
|
}
|
||||||
|
v[0]=v0; v[1]=v1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
##### Padding (bourrage)
|
||||||
|
|
||||||
|
Lorsque l'on cherche à crypter un fichier, sa taille n'est pas
|
||||||
|
toujours un multiple de la longueur des blocs chiffrés par
|
||||||
|
l'algortihme. Il existe différentes techniques dites de padding. Nous
|
||||||
|
utiliserons celle-ci :
|
||||||
|
|
||||||
|
- Si le dernier bloc à chiffer du fichier n'est pas entier, on écrit
|
||||||
|
dans son dernier octet le nombre d'octets manquants. Les octets
|
||||||
|
précédents peuvent être zéroifiés, ou remplis aléatoirement.
|
||||||
|
- Si le dernier bloc est entier, on rajoute tout un bloc pour qu'il
|
||||||
|
n'y est pas d'ambiguité.
|
||||||
|
|
||||||
|
Voici un exemple avec des blocs de taille 8 octets. Le fichier en entrée
|
||||||
|
est
|
||||||
|
```
|
||||||
|
ascii : hello word!
|
||||||
|
hex : 68 65 6c 6c 6f 20 77 6f 72 6c 64 21
|
||||||
|
```
|
||||||
|
|
||||||
|
Le dernier bloc est
|
||||||
|
```
|
||||||
|
ascii : ord!
|
||||||
|
hex : 72 6c 64 21 00 00 00 04
|
||||||
|
```
|
||||||
|
|
||||||
|
On ajoute des zéros (ou des octets aléatoires), et le dernier est le
|
||||||
|
nombre d'octets ajoutés (ici, 4). Si le dernier bloc est complet, on
|
||||||
|
rajoute tout un bloc.
|
||||||
|
|
||||||
|
```
|
||||||
|
hex : 00 00 00 00 00 00 00 00 08
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Votre travail
|
||||||
|
|
||||||
|
1. Ecrire une fonction qui decrypte un bloc.
|
||||||
|
2. Ecrire une commande **xtea** qui permet de (dé)chiffrer un fichier.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
xtea -e|-d filekey file1 file2
|
||||||
|
```
|
||||||
|
|
||||||
|
- `filekey` est le fichier ou est stocké la clé. Vous pouvez en
|
||||||
|
générer en utilisant le pseudo fichier `/dev/urandom`, et la
|
||||||
|
commande `dd`.
|
||||||
|
- l'option `-e` crypte. `file1` est alors le fichier à crypter,
|
||||||
|
`file2` le fichier crypté.
|
||||||
|
- l'option `-d` decrypte. `file1` est alors le fichier crypté, `file2`
|
||||||
|
le fichier decrypté.
|
||||||
|
3. Testez avec cette [clé](./src/ex2/key1.k), et ce [fichier
|
||||||
|
crypté](./src/ex2/fichier.crypt) sur une architecture little-endian.
|
||||||
|
|
||||||
|
4. Écrire une version de tea en mode CBC :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
xtea_cbc -e|-d iv filekey file1 file2
|
||||||
|
```
|
||||||
|
|
||||||
|
`iv` est le vecteur d'initialisation (8 octets) donné sur la ligne de commande.
|
||||||
|
|
||||||
|
**Rappel** : en mode CBC, le bloc à chiffrer subit un XOR avec le chiffré du bloc précédent. Le vecteur d'initialisation sert
|
||||||
|
pour le premier bloc.
|
||||||
|
|
||||||
|
### Ex3: une fonction de hachage cryptographique avec XTEA
|
||||||
|
|
||||||
|
Une fonction de hachage cryptographique permet de "résumer" un
|
||||||
|
fichier, message en calculant une empreinte. Une telle fonction,
|
||||||
|
mathématiquement, peut-être formalisée par
|
||||||
|
|
||||||
|
\[
|
||||||
|
\begin{matrix}
|
||||||
|
\{0,1\}^{*} & \rightarrow & \{0,1\}^n \\
|
||||||
|
m &\rightarrow & f(m) \end{matrix}
|
||||||
|
|
||||||
|
\]
|
||||||
|
|
||||||
|
$n$ est la taille de l'empreinte. Elle vaut 128 par exemple pour MD5 et SHA-1.
|
||||||
|
|
||||||
|
Grâce à XTEA, on va construire une telle fonction pour avec $n=64$.
|
||||||
|
|
||||||
|
Voici le principe.
|
||||||
|
|
||||||
|
- Le message ou fichier est décomposé en bloc de 24 octets (on bourrera
|
||||||
|
le dernier bloc suivant le pricincipe déjà vu en ajoutant des octets
|
||||||
|
avec la valeur du nombre d'octets ajoutés).
|
||||||
|
- Chaque bloc est vu comme un bloc suivi d'une clé de XTEA $x,k$
|
||||||
|
(bloc $x$ de 8 octets, clé $k$ de 16 octets). On calcule
|
||||||
|
$hash = xtea(x,k) \oplus x$.
|
||||||
|
- On combine le hash du bloc courant avec le hash du bloc précédent à
|
||||||
|
l'aide d'un xor. Le hash finale est l'empreinte.
|
||||||
|
|
||||||
|
##### Votre travail
|
||||||
|
|
||||||
|
1. Implantez le fonction prédente. Testez-là. Vérifiez que pour un message
|
||||||
|
"assez proche", l'empreinte est "vraiment" différente.
|
||||||
|
|
||||||
|
|
41
td_tp/tp1/aide.md
Normal file
41
td_tp/tp1/aide.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
### Setting a bit
|
||||||
|
|
||||||
|
Use the bitwise OR operator (|) to set a bit.
|
||||||
|
|
||||||
|
`number |= 1 << x;`
|
||||||
|
|
||||||
|
That will set bit x.
|
||||||
|
|
||||||
|
### Clearing a bit
|
||||||
|
|
||||||
|
Use the bitwise AND operator (&) to clear a bit.
|
||||||
|
|
||||||
|
`number &= ~(1 << x);`
|
||||||
|
|
||||||
|
That will clear bit x. You must invert the bit string with the bitwise NOT operator (~), then AND it.
|
||||||
|
|
||||||
|
### Toggling a bit
|
||||||
|
|
||||||
|
The XOR operator (^) can be used to toggle a bit.
|
||||||
|
|
||||||
|
`number ^= 1 << x;`
|
||||||
|
|
||||||
|
That will toggle bit x.
|
||||||
|
|
||||||
|
### Checking a bit
|
||||||
|
|
||||||
|
You didn't ask for this but I might as well add it.
|
||||||
|
|
||||||
|
To check a bit, shift the number x to the right, then bitwise AND it:
|
||||||
|
|
||||||
|
`bit = (number >> x) & 1;`
|
||||||
|
|
||||||
|
That will put the value of bit x into the variable bit.
|
||||||
|
|
||||||
|
### Changing the nth bit to x
|
||||||
|
|
||||||
|
Setting the nth bit to either 1 or 0 can be achieved with the following:
|
||||||
|
|
||||||
|
`number ^= (-x ^ number) & (1 << n);`
|
||||||
|
|
||||||
|
Bit n will be set if x is 1, and cleared if x is 0.
|
BIN
td_tp/tp1/img/TEA.png
Normal file
BIN
td_tp/tp1/img/TEA.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 26 KiB |
BIN
td_tp/tp1/img/feistel.png
Normal file
BIN
td_tp/tp1/img/feistel.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 63 KiB |
1263
td_tp/tp1/img/feistel.svg
Normal file
1263
td_tp/tp1/img/feistel.svg
Normal file
File diff suppressed because one or more lines are too long
After (image error) Size: 80 KiB |
BIN
td_tp/tp1/img/xtea.png
Normal file
BIN
td_tp/tp1/img/xtea.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 4.8 KiB |
BIN
td_tp/tp1/src/ex1/file.crypt
Normal file
BIN
td_tp/tp1/src/ex1/file.crypt
Normal file
Binary file not shown.
42
td_tp/tp1/src/ex1/lfsr.c
Normal file
42
td_tp/tp1/src/ex1/lfsr.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#define MASK_BIT_7 0x80
|
||||||
|
#define MASK_BIT_6 0x40
|
||||||
|
#define MASK_BIT_5 0x20
|
||||||
|
#define MASK_BIT_4 0x10
|
||||||
|
#define MASK_BIT_3 0x08
|
||||||
|
#define MASK_BIT_2 0x04
|
||||||
|
#define MASK_BIT_1 0x02
|
||||||
|
#define MASK_BIT_0 0x01
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char next(unsigned char lfsr)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fd_in,fd_out;
|
||||||
|
unsigned char w,buf;;
|
||||||
|
|
||||||
|
|
||||||
|
assert(argc >= 4);
|
||||||
|
fd_in = open(argv[1],O_RDONLY);
|
||||||
|
fd_out = open(argv[2],O_WRONLY|O_TRUNC|O_CREAT,0600);
|
||||||
|
w = (unsigned char)strtol(argv[3],NULL,0);
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
ssize_t nb = read(fd_in,&buf,1);
|
||||||
|
if (nb <=0)
|
||||||
|
break;
|
||||||
|
buf ^= w;
|
||||||
|
write(fd_out,&buf,1);
|
||||||
|
w=next(w);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
1
td_tp/tp1/src/ex2/key1.k
Normal file
1
td_tp/tp1/src/ex2/key1.k
Normal file
@ -0,0 +1 @@
|
|||||||
|
÷Nà{q2‘*:¬¨œÇmfU#©`í±Å?&Q3
|
11
td_tp/tp1/src/ex2/xtea.c
Normal file
11
td_tp/tp1/src/ex2/xtea.c
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
void encrypt(uint32_t v[2], uint32_t const key[4])
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
|
||||||
|
for (i=0; i < 32; i++) {
|
||||||
|
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
|
||||||
|
sum += delta;
|
||||||
|
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
|
||||||
|
}
|
||||||
|
v[0]=v0; v[1]=v1;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user