Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ic:labs:10 [2021/01/11 02:05]
florin.mocanu1708
ic:labs:10 [2023/10/09 23:23] (current)
razvan.smadu
Line 1: Line 1:
-===== Laboratorul 10 - Present and Future ​Public Key Encryption =====+===== Laboratorul 10 - Prezentul și Viitorul criptării cu chei publice (Public Key Encryption=====
  
-In this lab we'll do some cool exercises using public key encryption methods for key exchange and data encryption.+Prezentarea PowerPoint pentru acest laborator o puteți găsi [[https://​drive.google.com/​file/​d/​1wi11KjB6wiCpz7lcrhNUrRzIAXcHokd1/​view?​usp=sharing|aici]]. Puteți lucra acest laborator folosind platforma Google Colab, accesând [[https://​colab.research.google.com/​github/​ACS-IC-labs/​IC-labs/​blob/​main/​labs/​lab10/​lab10.ipynb|acest]] link
  
-==== Exercise 1: Diffie-Hellman key exchange (4p) ====+<​hidden>​
  
-As we discussed in class, Diffie and Hellman proposed the first public ​key exchange ​mechanism such that +În acest laborator vom face niște exerciții strașnice folosind metode de criptare cu chei publice pentru schimb de chei (key exchange) ​și criptare de date.
-two parties, that did not share any previous secret could establish a common secret. This allows +
-the parties to have a shared key that only they know (except if there is an active man in the middle attack, +
-which is usually solved by using TLS/​certificates,​ but we shall not focus on that here).+
  
-Download the lab code from {{:ic:​laboratoare:​lab11.zip|here}}. After unzipping, you'll find the source code +==== Exercițiul 1: Diffie-Hellman ​key exchange (4p) ====
-for a client (dhe.c) and a server (dhe_server.c),​ along with a Makefile and fixed Diffie-Hellman ​p and g params in the files dhparam.pem.+
  
-The client and server have similar structure. Each of them should build a public keythen send it to the other party, receive the public key from the other party and finally compute the secret ​keyYour task is to complete ​the missing parts. For thisconsult the openssl documentation [[https://​www.openssl.org/​docs/​man1.1.0/​crypto/​|here]]. Since they are similarfocus only on one of them and then do similarly on the other one.+cum am discutat la cursDiffie și Hellman au propus primul mecanism de schimb de chei astfel încât două părți care nu partajează niciun ​secret ​a priori să poată stabili un secret comunAcest mecanism oferă posibilitatea ca cele două părți să aibă un secret comun pe care doar ele să îl știe, chiar dacă schimbul de mesaje este vizibil și unor părți terțe (cu excepția unui atac activ de tip man in the middle care poate modifica conținutul schimbului de mesajeatac care poate fi rezolvat folosind TLS/certificatedar nu vor face parte din subiectul acestui laborator).
  
-The makefile should help you build bothJust type 'make all'. +Descărcați codul laboratorului de {{:​ic:​laboratoare:​lab11.zip|aici}}După dezarhivareveți găsi codul sursă pentru un client ​(dhe.c) și pentru un server (dhe_server.c),​ împreună cu un Makefile și niște parametri fixați p și g în fișierele dhparam.pem.
-After completing the necessary todo's in the fileyou can start the server by typing 'make start_server'​ and the +
-client ​with 'make start_client'​.+
  
-If all goes wellyou should see the same secret ​key on both client and server.+Clientul și serverul au o structură similară. Fiecare are trebui să construiască o cheie publicăpe care să o trimită celeilalte părți, iar în final să își calculeze cheia secretă. Scopul vostru este să completați părțile lipsă din cod. 
 +Pentru aceasta, consultați documentația openssl de [[https://​www.openssl.org/​docs/​man1.1.1/​man3/​|aici]]. Din moment ce sunt similare, concentrați-vă numai pe unul dintre ele și completați în mod asemănător și în cealaltă parte.
  
-Before starting this task, check that you have openSSL ​installed ​(in this lab we'll use openSSL 1.1.0):+Fișierul Makefile ar trebui să vă ajute să faceți build la ambele. Folosiți comanda 'make all'​. 
 +După completarea TODO-urilor necesare din fișier, puteți porni server-ul folosind comanda 'make start_server'​ și clientul folosind comanda 'make start_client'​. 
 + 
 +Dacă totul merge bine, ar trebui să vedeți același secret atât la client, cât și la server. 
 + 
 +Înainte să începeți acest task, verificați dacă aveți ​openSSL ​instalat ​(în acest laborator vom folosi ​openSSL 1.1.1):
 <​code>​ <​code>​
 #openssl version #openssl version
 </​code>​ </​code>​
  
-Alsomake sure that you have "​libssl-dev" ​installed ​(ask your lab supervisor to help you if this is missinge.g. if you cannot find header ​files during compilation).+De asemeneaasigurați-vă că aveți ​"​libssl-dev" ​instalat ​(rugați pe asistenții de laborator să vă ajute dacă lipsescde exemplu dacă nu se găsesc fișierele ​header ​la compilare).
  
 <​note>​ <​note>​
-If you need to install ​openSSL ​on your own machinedownload ​openssl 1.1.0 from [[https://​www.openssl.org/​source/​openssl-1.1.0c.tar.gz|here]]. +Dacă aveți nevoie să instalați ​openSSL ​pe calculatorul vostrudescărcați ​openssl 1.1.1 de [[https://​www.openssl.org/​source/​openssl-1.1.1d.tar.gz|aici]]. 
-Save the file to some local folder ​accessible by youthen compile it and install it to some folder. +Salvați fișierul într-un ​folder ​local accesibilapoi compilați-l și instalați-l într-un ​folder. 
-Open the unpacked ​folder ​from bash, and run the following commands:+Deschideți ​folder-ul în bash și rulați următoarele comenzi:
 <code bash> <code bash>
 linux$ ./config --prefix=/​home/​student/​local --openssldir=/​home/​student/​local/​openssl linux$ ./config --prefix=/​home/​student/​local --openssldir=/​home/​student/​local/​openssl
Line 38: Line 38:
 linux$ make install linux$ make install
 </​code>​ </​code>​
-(in case of troublecheck also the instructions at the end of [[http://​ocw.cs.pub.ro/​courses/​ic/​laboratoare/​09|lab 9]]).+(în caz de problemeverificați și instrucțiunile de la finalul ​[[http://​ocw.cs.pub.ro/​courses/​ic/​laboratoare/​09|acestui laborator]]).
  
-Make sure to update the Makefile ​with the paths relevant to your installation folders if you do your own install.+Nu uitați să actualizați fișierul ​Makefile ​cu path-urile spre folderele voastre de instalare.
  
-While the tools are building/compiling you may start working on the other exercises.+În timp ce se face build se compilează,​ puteți începe să lucrați la celelalte exerciții.
 </​note>​ </​note>​
  
-<note tip> 
-For some distributions (e.g. ubuntu), you might need to put the "​-lcrypto"​ flag for compilation at the end. 
-That is, having the compile lines in the Makefile like this: 
-<​code>​ 
-#gcc -L/​usr/​local/​lib dhe.c -o dhe -lcrypto 
-</​code>​ 
-</​note>​ 
  
-<​hidden>​Hidden section+Hidden section
  
 === Bonus 1 === === Bonus 1 ===
  
-Perform the DH key exchange between two teamssending the public key values over the network and verify that you get the same secret ​key.+Executați schimbul de chei între două calculatoare (cu altcineva)trimițând cheile publice prin rețea și verificați că obțineți același ​secret.
  
 === Bonus 2 === === Bonus 2 ===
  
-Use the secret ​key to encrypt some data (see previous labsand check that the other party can decrypt it.+Folosiți cheia secretă pentru a cripta niște date (vedeți laboratoarele precedenteși verificați dacă pot fi decriptate pe celălalt calculator.
  
 ==== Exercise 2: RSA parity oracle (4p) ==== ==== Exercise 2: RSA parity oracle (4p) ====
Line 184: Line 177:
  
 </​file>​ </​file>​
-</​hidden>​+
  
 ==== Introduction to Post Quantum Cryptography ==== ==== Introduction to Post Quantum Cryptography ====
Line 268: Line 261:
 You have to implement the 3 main steps (Generate, Encrypt and Decrypt) for this toy LWE scheme. The scheme as you will implement in the code will work on 4bit numbers. You have to implement the 3 main steps (Generate, Encrypt and Decrypt) for this toy LWE scheme. The scheme as you will implement in the code will work on 4bit numbers.
 You will find more details for your task in the skeleton code. You will find more details for your task in the skeleton code.
-{{:ic:labs:ex2a_skeleton.txt|}}+ 
 + 
 + 
 +<spoiler Click pentru a vedea ex2a_skeleton.py>​ 
 +<file python ex2a_skeleton.py>​ 
 +import math 
 +import random 
 +from typing import List, Tuple 
 + 
 + 
 +def int2bin(valint) -> List[int]: 
 +    """​ 
 +    Convert a 4-bit value to binary and return it as a list. 
 + 
 +    ​:param val: 4-bit positive value. 
 + 
 +    :return l: list of the bits obtained when converting value to binary. 
 +    """​ 
 +    l = [0] * (4) 
 + 
 +    l[0] = val & 0x1 
 +    l[1] = (val & 0x2) >> 1 
 +    l[2] = (val & 0x4) >> 2 
 +    l[3] = (val & 0x8) >> 3 
 + 
 +    return l 
 + 
 + 
 +def generate( 
 +    q: int = 97, 
 +    s: int = 19, 
 +    nr_values: int = 20, 
 +) -> Tuple[List[int],​ List[int]]:​ 
 +    """​ 
 +    Generate the public key vectors A and B. 
 + 
 +    :param q: Modulus 
 +    :param s: Secret key 
 +    :param nr_values: Length of vector variables 
 + 
 +    :return A, B: Public key vectors, each with "​nr_values"​ elements 
 + 
 +        TODO 1: Generate public key A 
 +           A = [a0, a1, ..., an-1] vector with random values. Of course values modulo q. :) 
 + 
 +        TODO 2: Generate error vector e 
 +           e = [e0, e1, ..., en-1] error vector with small errors in interval [1, 4] 
 + 
 +        TODO 3: Compute public key B 
 +           B = [b0, b1, ..., bn-1] with bi = ai * s + ei. Modulo q do not forget.. 
 + 
 +        TODO 4: Return public keys A, B 
 +    """​ 
 + 
 +    # TODO 1: Generate public key "​A"​ 
 +    A = ... 
 + 
 +    # TODO 2: Generate error vector "​e"​ 
 +    e = ... 
 + 
 +    # TODO 3: Compute public key "​B"​ 
 +    B = ... 
 + 
 +    # TODO 4: Return public keys A, B 
 + 
 + 
 +def encrypt_bit( 
 +    A: List[int],​ 
 +    B: List[int],​ 
 +    plain_bit: int, 
 +    q: int = 97, 
 +) -> Tuple[int, int]: 
 +    """​ 
 +    Encrypt one bit using Learning with Errors(LWE). 
 + 
 +    :param A: Public key 
 +    :param B: Public key 
 +    :param plain_bit: Plain bit that you want to encrypt 
 +    :param q: Modulus 
 + 
 +    :return: Cipher pair u, v 
 + 
 +        TODO 1: Generate a list of 5 random indexes with which you will sample values from public keys A and B. 
 +            random_sample_index_list = [random_index_1,​ random_index_2,​ ..., random_index_5] 
 +            A sample for A is A[random_index_i] or for B is B[random_index_i]. 
 + 
 +        TODO 2: Compute "​u"​ 
 +            u = sum of the samples from vector A 
 +            Don't forget modulo. 
 + 
 +        TODO 3: Compute "​v"​ 
 +            v = sum of the samples from vector B + floor(q/2) * plain_bit 
 +            Don't forget modulo. 
 + 
 +        TODO 4: Return cipher pair u, v 
 +    """​ 
 + 
 +    # The pair (u, v) will be basically the cipher. 
 +    u = 0 
 +    v = 0 
 + 
 +    # TODO 1: Generate a list of 5 random indexes with which you will sample values from both public keys A and B. 
 +    random_sample_index_list = ... 
 + 
 +    # TODO 2: Compute u 
 +    u = ... 
 + 
 +    # TODO 3: Compute v 
 +    v = ... 
 + 
 +    # TODO Return the cipher pair (u, v) reduced modulo q 
 + 
 + 
 +def encrypt( 
 +    A: List[int],​ 
 +    B: List[int],​ 
 +    number: int, 
 +    q: int = 97, 
 +) -> List[Tuple[int,​ int]]: 
 +    """​ 
 +    Encrypt a 4-bit number 
 + 
 +    :param A: Public Key. 
 +    :param B: Public Key. 
 +    :param number: Number in interval [0, 15] that you want to encrypt. 
 +    :param q: Modulus 
 + 
 +    :return list with the cipher pairs (ui, vi). 
 +    """​ 
 +    # Convert number to binary; you will obtain a list with 4 bits 
 +    bit_list = int2bin(number) 
 + 
 +    # Using the function that you made before, encrypt each bit. 
 +    u0, v0 = encrypt_bit(A,​ B, bit_list[0],​ q) 
 +    u1, v1 = encrypt_bit(A,​ B, bit_list[1],​ q) 
 +    u2, v2 = encrypt_bit(A,​ B, bit_list[2],​ q) 
 +    u3, v3 = encrypt_bit(A,​ B, bit_list[3],​ q) 
 + 
 +    return [(u0, v0), (u1, v1), (u2, v2), (u3, v3)] 
 + 
 + 
 +def decrypt_bit(cipher_pair:​ Tuple[int, int], s: int = 19, q: int = 97) -> int: 
 +    """​ 
 +    Decrypt a bit using Learning with errors. 
 + 
 +    :param cipher_pair:​ Cipher pair (u, v) 
 +    :param s: Secret key 
 +    :param q: Modulus 
 + 
 +        TODO 1: Compute the "​dec"​ value with which you will decrypt the bit. 
 +            dec = (v - s * u) modulo q 
 + 
 +        TODO 2: Obtain and return the decrypted bit. 
 +            The decrypted bit is 1 if the previously computed "​dec"​ value is bigger than floor(q/2) and 0 otherwise. 
 + 
 +    :return list with the cipher pairs (ui, vi). 
 +    """​ 
 + 
 +    # Extract pair (u, v) from the argument "​cipher_pair"​. 
 +    u = cipher_pair[0] 
 +    v = cipher_pair[1] 
 + 
 +    # TODO 1: Compute "​dec"​ variable 
 +    dec = ... 
 + 
 +    # TODO 2: Decrypt bit and return it 
 +    #  return 0 or 1 
 + 
 + 
 +def decrypt( 
 +    cipher: List[Tuple[int,​ int]], 
 +    s: int = 19, 
 +    q: int = 97, 
 +) -> List[int]:​ 
 +    """​ 
 +    Decrypt a 4-bit number from the cipher text pairs (ui, vi). 
 + 
 +    :param cipher: Cipher text. List with 4 cipher pairs (u, v) corresponding to each encrypted bit 
 +    :param s: Secret key 
 +    :param q: Modulus 
 + 
 +    :return plain: List with the 4 decrypted bits. 
 +    """​ 
 +    u1, v1 = cipher[0][0],​ cipher[0][1] 
 +    u2, v2 = cipher[1][0],​ cipher[1][1] 
 +    u3, v3 = cipher[2][0],​ cipher[2][1] 
 +    u4, v4 = cipher[3][0],​ cipher[3][1] 
 + 
 +    bit0 = decrypt_bit((u1,​ v1), s, q) 
 +    bit1 = decrypt_bit((u2,​ v2), s, q) 
 +    bit2 = decrypt_bit((u3,​ v3), s, q) 
 +    bit3 = decrypt_bit((u4,​ v4), s, q) 
 + 
 +    return [bit3, bit2, bit1, bit0] 
 + 
 + 
 +def main() -> None: 
 +    # Initialize Parameters 
 +    q = 97 
 +    s = 19 
 +    nr_values = 20 
 +    print( 
 +        f"​Initial parameters are:​\n"​ 
 +        " modulus={q}\n" 
 +        " secret_key={s}\n" 
 +        " nr_of_values={nr_values}\n"​ 
 +    ) 
 + 
 +    # Integer in [0, 15] that you want to encrypt 
 +    number_to_encrypt = 10 
 +    print("​You want to encrypt number " + str(number_to_encrypt)) 
 + 
 +    # Generate Step 
 +    A, B = generate(q, s, nr_values) 
 +    print("​\nPublic Keys obtained:"​) 
 +    print("​A=",​ end=""​) 
 +    print(A) 
 +    print("​B=",​ end=""​) 
 +    print(B) 
 + 
 +    # Encrypt Step 
 +    cipher = encrypt(A, B, number_to_encrypt,​ q) 
 +    print("​\nCipher is ", end=""​) 
 +    print(cipher) 
 + 
 +    # Decrypt Step 
 +    plain = decrypt(cipher,​ s, q) 
 +    print("​\nPlain value in binary is ", end=""​) 
 +    print(plain) 
 + 
 +    # If plain is the representation in binary of "​number_to_encrypt"​ it should be fine but you can check with other numbers. :D 
 + 
 + 
 +if __name__ == "​__main__":​ 
 +    main() 
 + 
 +</​file>​ 
 +</​spoiler>​ 
 + 
  
 === Exercise 2b) Testing decryption (2p) === === Exercise 2b) Testing decryption (2p) ===
 Easy right? I have encrypted 5 numbers and stored the ciphers in this file. Can you decrypt them with the function you implemented before? Easy right? I have encrypted 5 numbers and stored the ciphers in this file. Can you decrypt them with the function you implemented before?
  
-{{:ic:labs:ex2b.txt|}}+<spoiler Click pentru a vedea ex2b_cipher.py>​ 
 +<file python ex2b_cipher.py>​ 
 +# Try to decrypt some secret numbers encrypted using the decryption you just implemented. 
 + 
 +# The parameters are the same except that I changed the secret key s. :
 +# Of course you need the secret key in order to decrypt the numbers but I won't tell it to you because is secret (s=17). 
 + 
 +secretnumber1 = [(57, 11), (91, 13), (38, 29), (68, 55)] 
 +secretnumber2 = [(35, 22), (9, 67), (91, 10), (50, 89)] 
 +secretnumber3 = [(51, 52), (51, 8), (76, 90), (90, 89)] 
 +secretnumber4 = [(68, 50), (18, 28), (93, 43), (61, 77)] 
 +secretnumber5 = [(33, 39), (68, 6), (17, 57), (53, 90)] 
 + 
 +# Does [number1, number2, number3, number4, number5] make sense? Maybe in hexadecimal ?? 
 + 
 +</​file>​ 
 +</​spoiler>​ 
  
 Just for fun: Do these numbers have a meaning? Maybe they form a word?  Just for fun: Do these numbers have a meaning? Maybe they form a word? 
Line 283: Line 532:
 To do that just take two 4bit numbers that you want to xor, for example 10 and 5 and encrypt them. Before decrypting you just have to take the obtained ciphers(two (u, v) pairs) and just add them (i.e. (u1 + u2, v1 + v2)). For convenience,​ you can use if you want the functions provided in the file below. ​ To do that just take two 4bit numbers that you want to xor, for example 10 and 5 and encrypt them. Before decrypting you just have to take the obtained ciphers(two (u, v) pairs) and just add them (i.e. (u1 + u2, v1 + v2)). For convenience,​ you can use if you want the functions provided in the file below. ​
  
-{{:ic:labs:​xor_then_decrypt_bit.txt|}}+ 
 +<spoiler Click pentru a vedea xor_then_decrypt.py>​ 
 +<file python ex2b_cipher.py>​ 
 +from ex2a_skeleton import * 
 + 
 + 
 +def xor_then_decrypt_bit( 
 +    cipher_pair1Tuple[int, int], 
 +    cipher_pair2Tuple[int, int], 
 +    sint = 19, 
 +    q: int = 97, 
 +): 
 +    """​ 
 +    Xor Cipher pairs and then decrypt a bit using Learning with errors. 
 + 
 +    :param cipher_pair1:​ First cipher pair (u, v) 
 +    :param cipher_pair2:​ Second cipher pair (u, v) 
 +    :param s: Secret key 
 +    :param q: Modulus 
 + 
 +        TODO 1: Compute the "​dec"​ value with which you will decrypt the bit. 
 +            dec = ((v_1 - s * u_1) + (v_2 - s * u_2)) % q 
 + 
 +        TODO 2: Obtain and return the decrypted bit. 
 +            The decrypted bit is 1 if the previously computed "​dec"​ value is bigger than floor(q/2) and 0 otherwise. 
 + 
 +    :return the decrypted bit 
 +    """​ 
 + 
 +    # Extract pair (u, v) from the argument "​cipher_pair"​. 
 +    u_1 = cipher_pair1[0] 
 +    v_1 = cipher_pair1[1] 
 + 
 +    u_2 = cipher_pair2[0] 
 +    v_2 = cipher_pair2[1] 
 + 
 +    # TODO 1: Compute "​dec"​ variable 
 + 
 +    # TODO 2: Decrypt bit and return it 
 + 
 + 
 +def xor_then_decrypt( 
 +    cipher1: List[Tuple[int,​ int]], 
 +    cipher2: List[Tuple[int,​ int]], 
 +    s: int = 19, 
 +    q: int = 97, 
 +) -> List[int]:​ 
 +    """​ 
 +    Bit wise xor the two cipher pairs and the decrypt 4-bit number result. 
 + 
 +    :param cipher1: Cipher 1. 
 +    :param cipher2: Cipher 2. 
 +    :param s: Secret key 
 +    :param q: Modulus 
 + 
 +    :return plain: List with the 4 decrypted bits. 
 +    """​ 
 +    u1_1, v1_1 = cipher1[0][0],​ cipher1[0][1] 
 +    u2_1, v2_1 = cipher1[1][0],​ cipher1[1][1] 
 +    u3_1, v3_1 = cipher1[2][0],​ cipher1[2][1] 
 +    u4_1, v4_1 = cipher1[3][0],​ cipher1[3][1] 
 + 
 +    u1_2, v1_2 = cipher2[0][0],​ cipher2[0][1] 
 +    u2_2, v2_2 = cipher2[1][0],​ cipher2[1][1] 
 +    u3_2, v3_2 = cipher2[2][0],​ cipher2[2][1] 
 +    u4_2, v4_2 = cipher2[3][0],​ cipher2[3][1] 
 + 
 +    bit0 = xor_then_decrypt_bit((u1_1, v1_1), (u1_2, v1_2), s, q) 
 +    bit1 = xor_then_decrypt_bit((u2_1,​ v2_1), (u2_2, v2_2), s, q) 
 +    bit2 = xor_then_decrypt_bit((u3_1,​ v3_1), (u3_2, v3_2), s, q) 
 +    bit3 = xor_then_decrypt_bit((u4_1,​ v4_1), (u4_2, v4_2), s, q) 
 + 
 +    return [bit3, bit2, bit1, bit0] 
 + 
 + 
 +def main() -> None: 
 +    # TODO 3: Test it on some examples to see if is working properly 
 +    ​... 
 + 
 + 
 +if __name__ == "​__main__":​ 
 +    main() 
 + 
 +</​file>​ 
 +</​spoiler>​ 
  
 Test it on some examples to see if is working properly! Test it on some examples to see if is working properly!
Line 292: Line 626:
 [[https://​github.com/​IBM/​fhe-toolkit-linux/​blob/​master/​GettingStarted.md]] [[https://​github.com/​IBM/​fhe-toolkit-linux/​blob/​master/​GettingStarted.md]]
 </​note>​ </​note>​
 +</​hidden>​
 +
ic/labs/10.1610323557.txt.gz · Last modified: 2021/01/11 02:05 by florin.mocanu1708
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0