# Security practical labs
## Lab 1
### Tarefa 1
```
k=23
OLA
+ kkk
------
LIX
```
### Q1
:::success
**LIX**
:::
### Tarefa 2
```
k=10
LOXPSMKOYWKSYB
- kkkkkkkkkkkkkk
------------------
BENFICAEOMAIOR
```
Texto limpo: BENFICAEOMAIOR
### Tarefa 3
O MAR SALGADO, QUANTO DO TEU SAL SAO LAGRIMAS DE PORTUGAL!
### Q2
:::success
**$25$**
:::
Pois `k=0` é a própria plaintext message.
### Q3
$\frac{25}{2}=12.5$, logo pelo menos
:::success
**$13$ tentativas**
:::
### Q4
:::success
**Cyphertext-only attack (COA)**
:::
Pois podemos apenas observar o criptograma e tentando colocar letras mais comuns do alfabeto.
### Tarefa 4
Criptograma:TCZMAHPLTCYHAOXAQOTNTU
### Q5
$26*26*26*26=$
:::success
**$456976$**
:::
### Q6
:::success
* Chaves com letras todas iguais.
* Chaves com uma só letra.
:::
### Tarefa 5
```
Plaintext message: ISTO * *****
Cyphertext: JUWP G IBELM
Cypherkey: K, com K=<.>
JUWP G IBELM
- <.>< . ><.><
------------------
ISTO * *****
JUWP G IBELM
- ISTO * *****
------------------
ABCA * *****
Visto que a chave tem apenas 3 letras, K=ABC, logo:
JUWP G IBELM
- ABCA B CABCA
------------------
ISTO E FACIL
```
### Q7
:::success
**Known-plaintext attack (KPA)**
:::
Pois temos um par (parcial) de plaintext-message e cyphertext.
### Tarefa 6
```c=
//includes
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<stdlib.h>
//definitions
#define ALPHABET_SIZE 26
#define WORD_SIZE 12
//functions
ssize_t getKeyOfAlphabet(char letter,char* alphabet,size_t alphabetSize){
for(size_t i=0;i<alphabetSize;i++){
if(alphabet[i]==letter){
return i;
}
}
return -1;
}
void encrypt(char *in,char *out,size_t size,char *normalAlphabet,char*substitutedAlphabet){
if(strlen(in)!=strlen(out)){
perror("Invalid sizes for words! Must be the same");
exit(-1);
}
for(size_t i=0;i<size-1;i++){
ssize_t temp=substitutedAlphabet[getKeyOfAlphabet(in[i],normalAlphabet,ALPHABET_SIZE)];
if(temp==-1){
perror("There was an error encrypting");
exit(-1);
}
out[i]=temp;
}
}
void decrypt(char *in,char *out,size_t size,char *normalAlphabet,char*substitutedAlphabet){
if(strlen(in)!=strlen(out)){
perror("Invalid sizes for words! Must be the same");
exit(-1);
}
for(size_t i=0;i<size-1;i++){
ssize_t temp=normalAlphabet[getKeyOfAlphabet(in[i],substitutedAlphabet,ALPHABET_SIZE)];
if(temp==-1){
perror("There was an error encrypting");
exit(-1);
}
out[i]=temp;
}
}
void showMenu(void){
printf("What do you want to do?\n");
printf("1-Encrypt\n");
printf("2-Decrypt\n");
printf("0-Exit\n");
}
int main(void){
char NORMAL_ALPHABET[ALPHABET_SIZE] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
char SUBSTITUTED_ALPHABET[ALPHABET_SIZE] = {'S','Q','T','U','H','J','I','B','Y','K','A','V','L','C','W','E','Z','N','R','M','X','G','F','P','D','O'};
char plaintext[WORD_SIZE] = "OLACOMOESTA";
char cyphertext[WORD_SIZE] = "XXXXXXXXXXX";
char plaintext2[WORD_SIZE] = "XXXXXXXXXXX";
char cyphertext2[WORD_SIZE] = "WVSTWLWHRMS";
while(true){
showMenu();
int option;
scanf("%d",&option);
if(option==1){
encrypt(plaintext,cyphertext,WORD_SIZE,NORMAL_ALPHABET,SUBSTITUTED_ALPHABET);
printf("%s->%s\n",plaintext,cyphertext);
}
else if(option==2){
decrypt(cyphertext2,plaintext2,WORD_SIZE,NORMAL_ALPHABET,SUBSTITUTED_ALPHABET);
printf("%s->%s\n",cyphertext2,plaintext2);
}
else if(option==0){
break;
}
else{
perror("Invalid option!");
}
}
return 0;
}
```
### Q8
:::success
$26!$
:::
Pois cada chave é constituida pelo alfabeto de 26 letras, que não se podem repetir.
### Q9
$26!=403291461126605635584000000$ chaves possiveis.
Assumindo que um computador consegue testar uma chave em cada operação composta e que um computador moderno consegue efetuar cerca de $2^{26}$ operações compostas num segundo:
$\text{Operações compostas por segundo}=2^{26}=67108864$
$\text{Operações compostas por minuto}=2^{26}*60=4026531840$
$\text{Operações compostas por hora}=2^{26}*60*60=241591910400$
$\text{Operações compostas por dia}=2^{26}*60*60*24=5798205849600$
$\text{Operações compostas por mês}=2^{26}*60*60*24*31=179744381337600$
$\text{Operações compostas por ano}=2^{26}*60*60*24*31*12=2156932576051200$
$\text{Operações compostas por século}=2^{26}*60*60*24*31*12*100=215693257605120000$
$\text{Séculos para decrifrar cifra de substituição}=\frac{403291461126605635584000000}{215693257605120000}\approx186974533003$
:::success
**Não, não conseguia.**
:::
### Q10
:::success
**Em termos de número de chaves, parece-me ser segura, mas em termos de facilidade de ataque, não.**
:::
### Q11
```
Dados, e.g.:
a1=[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z]
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | | | | | | | | | | | | | | | | | | | |
a2=[S,Q,T,U,H,J,I,B,Y,K,A,V,L,C,W,E,Z,N,R,M,X,G,F,P,D,O]
Dada a frase: ATARTARUGA
O texto cifrado seria: SMSNMSNXIS
Se se soubesse que *TAR****** correspondia a SMSNMSNXIS, saberiamos
que todos os S correspondem a A, todos os M correspondem a T e
todos os N correspondem a R, logo saberiamos que na verdade que:
A frase: ATARTAR**A
O texto cifrado seria: SMSNMSNXIS
```
Na demonstração atrás, descobriu-se alguma coisa, logo sofre do primeiro ataque.
Também sofre da segunda, visto que as letras do texto cifrado correspondem as do texto original diretamente, logo consegue-se perceber quantas letras iguais existem.
:::success
**Sim, é vulnerável em ambas as situações.**
:::
### Q12
```python=
#enigmaTime.py
for i in range(712882560+1):
pass
```
```
time python3 enigmaTime.py
--------
real 0m19.516s
user 0m19.510s
sys 0m0.000s
```
:::success
**$\approx 19.5$ segundos**
:::
### Tarefa 7

### Q13
:::success
**9**
:::
### Q14
:::success
**7**
:::
### Q15
:::success
**4**
:::
### Q16
:::success
**5**
:::
### Q17
:::success
**Não, não ia**
:::
Como sao eventos independentes, a probabilididade de sair cara ou coroa na sétima tentativa continuaria a ser $\frac{1}{2}$
### Q18
:::success
**Sim, vai.**
:::
### Q19
:::success
**Aleatória**
:::
### Tarefa 8
```
0101000011010011
⊕ 0000000100000001
---------------------
0101000111010010
```
### Q20
:::success
**9**
:::
### Q21
:::success
**7**
:::
### Q22
:::success
**3**
:::
### Q23
:::success
**2**
:::
### Q24
:::success
**Sim, de facto parece**
:::
### Q25
:::success
**É impossível obter o texto-limpo de volta, a não ser que também lhe envie a sequência resultante da minha experiência.**
:::
## Lab 2
### Tarefa 1 e Q1
:::success
**O *openssl* é uma biblioteca de criptografia utilizada para certas comunicações. Pode ser utilizada na linha de comandos ou embutida em certas linguagens de programação, como C.**
:::
### Q2
:::success
**O OpenSSL é importante mas não há nada a reportar acerca de bugs severos, em termos de segurança, na sua implementação**
:::
Apesar de não ter tido bugs severos que íam fazendo com que a Internet fosse com o bodo, teve, sim, bastantes vulnerabilidades.
### Q3
:::success
**Escrevendo `man command` no terminal...**
:::
### Q4
:::success
**Sim, há... um é um toolkit e o outro é um comando de linux.**
:::
### Q5
:::success
**Sim**
:::
### Q6
:::success
**Claro**
:::
### Q7
:::success
**Também dá**
:::
### Q8
:::success
**FAZ TUDO!**
:::
### Q9
:::success
**Não, mas de resto faz tudo...**
:::
### Tarefa 2
```
openssl rand -hex 10
```
### Tarefa 3
```
openssl
```
### Q10
:::success
**Não**
:::
Estou agora num interpretador de comandos de openssl.
### Q11
```
help
```
:::success
**Sim**
:::
### Q12
:::success
**48**
:::
### Q13
:::success
* **`-in <file>`**;
* **`-out <file>`**;
* **`-pass <arg>`**;
* **`-e`**;
* **`-d`**;
* **`-a/-base64`**;
* **`-k`**;
* **`-kfile`**;
* **`-md`**;
* **`-S`**;
* **`-K/-iv`**;
* **`-[pP]`**;
* **`-bufsize <n>`**;
* **`-nopad`**.
:::
### Q14
:::success
**Só não fala como as pessoas!**
:::
### Tarefa 4
```
openssl enc -rc4 -e -K abcdefg0123456789 -in plaintext -out ciphertext.rc4
```
### Q15
:::success
**R**ivest **C**ipher **4**
:::
### Q16
:::success
**Sim, parece**
:::
Porque tem muita entropia.
### Q17
:::success
**Não, não funcionou. :(**
:::
Porque a chave tem que ser hexadecimal e a chave dada no comando tem um g. Corrige-se para:
```
openssl enc -rc4 -e -K abcdef0123456789 -in plaintext -out ciphertext.rc4
```
### Q18
:::success
**Sim, já verifiquei usando `cat ciphertext.rc4` e o que lá encontrei não faz sentido nenhum.**
:::
### Q19
## Lab 4
### Q1
:::success
**$u=log_b(n)$**
:::
### Tarefa 1
```c=
#include <stdio.h>
#include <math.h>
int main(int argc,char *argv[]){
size_t numberSymbols=0;
double entropyValue=0;
//check for invalid flags
if(argc!=2){
perror("Invalid flags!");
return -1;
}
//open file
FILE *fp=fopen(argv[1],"r");
if(fp==NULL){
puts("cannot open file");
return -1;
}
//initialize each character probability to 0
int asciiProbabilities[255];
for(size_t i=0;i<255;i++){
asciiProbabilities[i]=0;
}
//read each character of the file,
//incrementing the number of seen by each character in the ascii array
char readChar=1;
while((readChar=fgetc(fp))!=EOF){
numberSymbols++;
asciiProbabilities[(unsigned char)readChar]++;
}
//calculate entropy
for(size_t i=0;i<255;i++){
double eachCharacterProbability=(double)asciiProbabilities[i]/numberSymbols;
if(eachCharacterProbability>0){
entropyValue-=eachCharacterProbability*
log((float)eachCharacterProbability);
}
}
printf("\n\tThe entropy value for file %s is\n\n \t\t\t%f \n",argv[1],entropyValue);
printf("\n\tThe max entropy value is %f \n\n",log((double)256));
fclose(fp);
}
```
### Q2
:::success
**256**
:::
Pois essa é a quantidade de valores na tabela ASCII, o que é a quantidade possível de valores no ficheiro.
### Q3
:::success
**5.55**
:::
Pois $log_b(256)\approx 5.55$
### Tarefa 2 e Tarefa 3 e Tarefa 4 e Tarefa 5
```
zip passwords.zip passwords
```
```
openssl enc -aes-128 -in passwords -out passwords.aes
-K 62ee86b4dc34742afc452f1a2b90e831 -iv e1a1aa1a178faf6d74115ff09dac809d
```
```
openssl enc -aes-128 -in passwords.zip -out passwords.zip.aes
-K 62ee86b4dc34742afc452f1a2b90e831 -iv e1a1aa1a178faf6d74115ff09dac809d
```
```
zip passwords.aes.zip passwords.aes
```
| Name | Size (KB) | Entropy |
| -------- | -------- | -------- |
| passwords | 1.5 | 3.223813 |
| passwords.zip | 0.97 | 4.491682 |
| passwords.aes | 1.5 | 4.381308 |
| passwords.zip.aes | 0.97 | 3.028029 |
| passwords.aes.zip | 1.7 | 4.484435 |
### Q4
:::success
**Cipher Block Chaining**
:::
Visto que requer um vetor de inicialização.
### Q5
:::success
**128 bits**
:::
Porque $16$ bytes = $128$ bits.
### Q6
:::success
**Primeiro comprimir e depois cifrar.**
:::
Ao comprimir o ficheiro original, este irá conter diversos padrões, que poderão ser utilizados para uma maior redução do ficheiro. Se cifrarmos primeiro, muitos destes padrões serão perdidos, o que, não só, poderá fazer com que a compressão não faça nada, mas poderá, inclusive, aumentar o tamanho do ficheiro, devido à adição do cabeçalho de compressão.
### Tarefa 6
```
openssl enc -aes-128-ecb -in plaintext -out cyphertext.ecb -K 11232233
```
### Tarefa 7
```
hexdump -C cyphertext.ecb
```
```
00000000 fb 5d 84 63 be 29 f4 48 9e 5d 70 ec f8 e4 ff 80 |.].c.).H.]p.....|
00000010 4b cf 7a d4 3c d4 c0 f2 a2 0f 74 76 57 87 54 98 |K.z.<.....tvW.T.|
00000020 00 e1 74 34 22 5a 94 e2 59 10 d5 6c 0e d9 d2 19 |..t4"Z..Y..l....|
00000030 fb 5d 84 63 be 29 f4 48 9e 5d 70 ec f8 e4 ff 80 |.].c.).H.]p.....|
00000040 0a 1a e9 c0 2c e4 7d 86 45 63 76 65 f3 da 99 d0 |....,.}.Ecve....|
00000050
```
### Q7
:::success
**A**dvabced **E**ncryption **S**tandard
:::
### Q8
:::success
**Cifra de chave simétrica por blocos.**
:::
### Q9
:::success
**Sim**
:::
### Q10
:::success
**$16$ bytes**
:::
Porque $128$ bits = $16$ bytes.
### Q11
:::success
Não, não precisa.
:::
### Tarefa 8
```
openssl enc -aes-128-cbc -K 11232233 -in plaintext -out cyphertext.cbc
```
### Q12
:::success
**Digo, digo.**
:::
### Q13
:::success
**Adicionando um vetor de inicialização**
:::
Pois o modo cbc necessita de um iv para cifrar o primeiro bloco.
```
openssl enc -aes-128-cbc -K 11232233 -in plaintext -out cyphertext.cbc -iv 0
```
### Q14
:::success
**C**ypher **B**lock **C**haining
:::
### Q15
:::success
**Um modo de utilização de uma cifra**
:::
### Tarefa 9
```
hexdump -C cyphertext.cbc
```
### Q16
:::success
**Que interessante, não vejo qualquer padrão**
:::
### Q17
:::success
**Os dois criptogramas seriam totalmente distintos**
:::
Porque o primeiro bloco vai ser afetado pelo iv, o que significa que todos os blocos consequentes também serão.
## Lab 5
### Tarefa 1
```
openssl dgst -md5 PodiaSerAFreqMasNaoE.pdf > PodiaSerAFreqMasNaoE.md5
```
```
openssl dgst -sha1 PodiaSerAFreqMasNaoE.pdf > PodiaSerAFreqMasNaoE.sha1
```
### Q1
:::success
**Iguanas**
:::
### Q2
:::success
* **Que, neste caso, o ficheiro que chegou à minha máquina não sofreu erros durante a transmissão.**
* **Que, neste caso e confiando no que o Professor afirmou, o ficheiro que descarreguei é, de facto, o ficheiro que está no servidor, e para o qual calculou os valores de hash**
:::
### Q3
:::success
**Ron Rivest**
:::
### Q4
### Q5
:::success
**MD5 : 128**
**SHA1: 160**
:::
### Q6
:::success
**S**ecure **H**ash **A**lgorithm **1**
:::
### Q7
:::success
**M**essage **D**igest **5**
:::
### Q10
:::success
* **Integridade dos dados**;
* **Identificação de burlas em ficheiros descarregados da Internet**.
:::
### Q12
:::success
**Os valores de hash ficaram totalmente diferentes**
:::
### Q13
:::success
**Mudaram aproximadamente 1/2 dos bits**
:::
### Q14
:::success
**Obtínhamos exatamente o mesmo comportamento que observamos quando mudamos 1 só byte**
:::
### Q15
:::success
**Não. As alterações produzidas parecem ser aparentemente imprevisíveis**
:::
### Q16
:::success
**Não estou a ver como iria fazer isso para já, mas creio que iria conseguir. A minha ideia era a seguinte**
:::
É teóricamente possível com *bruteforce*, mas é, porém, quase impossível, i.e., praticamente impossível.
### Q17
:::success
**Resistência a colisões**
:::
### Q18
:::success
**Se não, procure explicar**
:::
Porque, $\frac{2^{160}}{2^{28}}=5.444517870735016e+39$, o que é big número, impossível de fazer em tempo útil, sendo $2^28$ número de operações dum computador em tempo útil e $2^160$ número de hashes do sha-1.
## Lab 6
## Q1
:::success
**8 bytes**
:::
## Q2
:::success
**` cc programa.c -lcrypto`**
:::
### Q4
:::success
**`javac sha1sum.java`**
:::
## Lab 7
### Q1
:::success
**M**essage **A**uthentication **C**ode
:::
### Tarefa 1
```
echo -n "arrozDePato" > plaintext
```
```
openssl dgst -sha1 plaintext > plaintext.sha1
```
```
openssl enc -aes128 -in plaintext.sha1 -out plaintext.sha1.aes -K 5555ffff1234aedf9876cbcb6546789e -iv 7e5766d419adfbc5859e7a48cfe9821d
```
### Tarefa 2
```
openssl enc -aes128 -d -in plaintext.sha1.aes -out deciphered.sha1 -K 5555ffff1234aedf9876cbcb6546789e -iv 7e5766d419
adfbc5859e7a48cfe9821d
```
```
openssl dgst -sha1 plaintext > plaintextNewHash.sha1
```
```
diff plaintextNewHash.sha1 plaintext.sha1
```
### Q4
:::success
**Todos os que possuem a chave secreta**
:::
### Q5
:::success
* **Garantia de que o ficheiro não sofreu erros aleatórios durante a transmissão (integridade)**;
* **Garantia de que o ficheiro não foi alterado intencionalmente durante a transmissão (autenticação da origem da informação)**
:::
### Tarefa 3 e Q6
:::success
**Sim, é, com um só comando: `openssl dgst -sha1 -hmac 5555ffff1234aedf9876cbcb6546789e plaintext > plaintext.hmac`**
:::
### Q7
:::success
**Hash**
:::
### Tarefa 4
```
openssl dgst -sha1 -hmac 5555ffff1234aedf9876cbcb6546789e plaintext > plaintext2.hmac
```
```
diff plaintext.hmac plaintext2.hmac
```
### Q8
:::success
**Não, não é. Mas o 3 já é!**
:::
### Q9
:::success
**14**
:::
Por Tentativa e erro
#### Q10
:::success
**Sim, concordo, porque o atacante apenas conseguia escutar as comunicações**
:::
## Lab 8
### Tarefa 1
```
p=13
q=17
N=221
FIN=192
e=5
d=77
pk=(e,N)=(5,221)
sk=(d,N)=(77,221)
```
### Tarefa 2
```
Para 69
encrypted=205
decrypted=69
```
### Q1
:::success
**Não, e não há qualquer problema de segurança nisso**
:::
### Q2
:::success
**Porque eu lha dei diretamente**
:::
### Q3
:::success
**Hummm.... não**
:::
### Q4
:::success
**A chave pública**
:::
### Q5
:::success
**A chave privada**
:::
### Tarefa 4
```
openssl genrsa -out myPrivateKey 1024
```
```
openssl rsa -in myPrivateKey -pubout -out myPublickey
```
```
openssl genrsa -out myPrivateKey -aes128 1024
```
```
openssl rsa -in myPrivateKey -pubout -out myPublickey
```
### Tarefa 5
```
openssl rsautl -in secretKey -out secretKey.rsa -pubin -inkey myPublickey -encrypt
```
```
openssl rsautl -in secretKey.rsa -out secretKey2 -inkey myPrivateKey -decrypt
```
### Q6
:::success
**Neste caso consegui, porque 128 bits é menor do que o tamanho do módulo que estou a usar**
:::
### Q7
:::success
**1024**
:::
### Q8
:::success
**Não. O texto é grande demais e o OpenSSL não deixa cifrar por blocos usando o RSA, visto que este modo (livro de escola), por sí só, já é inseguro.**
:::
### Q9
:::success
**Pretty good privacy**
:::
### Tarefa 9
```
openssl rsautl -sign -inkey myPrivateKey -in portugal.sha256 -out portugal.sha256.sig
```
```
openssl rsautl -verify -pubin -inkey myPublickey -in portugal.sha256.sig -out portugal2.sha256
```
```
diff portugal.sha256 portugal2.sha256
```
### Tarefa 10
```
openssl dgst -sha256 -sign myPrivateKey -out portugal.sig portugal.txt
```
```
openssl dgst -sha256 -verify myPublickey -signature portugal.sig portugal.txt
```
### Q11
:::success
**Só quem possui a chave privada**
:::
### Q12
:::success
**Só quem possui a chave simétrica secreta**
:::
### Q13
:::success
**Só quem possui a chave pública**
:::
### Q14
:::success
**Só quem possui a chave simétrica secreta**
:::
### Q15
:::success
* **Autenticação da origem da informação**;
* **Integridade**;
* **Não repúdio**;
* **Autenticidade**;
* **Dificuldade de falsificação**.
:::
### Q16
:::success
* **Integridade**;
* **Autenticidade**;
:::