Autor teksta: Krunoslav Tomičić
Uvod
Crystals-Kyber
Kyber je kriptografski sustav razmjene ključeva i enkripcije koji se temelji na težini rješavanja
problema učenja s greškama (LWE) preko modul rešetki. Osnovna jednadžba glasi
B = As + e mod q
Finalist je NIST-ovog post-kvantnog kriptografskog natječaja.
Program
Uvod
Koristimo neslužbenu implementaciju koju se može preuzeti kao zip datoteku i koja sadrži izvorni kod algoritma. U sklopu projekta, u programskom jeziku Python, napravljeno je sučelje za demonstraciju rada Kyber-a.
Implementacija
Potrebno je raspakirati skinutu zip datoteku, zatim se pozicionirati u
/pyky
, te dodati
datoteku: main.py
Demonstracija
Python program pokreće se iz direktorija u kojemu se nalazi datoteka main.py
sljedećom
naredbom:

Otvara se prozor:

Pritiskom na dio prozora u kojemu piše "KEY ENCAPSULATION MECHANISM" otvara se sljedeći prozor:

Pritiskom na gumb "Generiraj seed" generiramo seed koji se koristi za kreiranje privatnog i javnog ključa. Pritiskom na gumb "Generiraj par ključeva" generiramo privatni i javni ključ. Pritiskom na gumb "Enkapsuliraj" dobivamo šifru i zajedničku tajnu.

Pritiskom na gumb "Dekapsuliraj - provjeri zajedničku tajnu" provjerava se je li šifra generirana iz javnog ključa valjana za zadani tajni ključ.

Poruka o ispravnosti postupka enkapsulacije prikazuje se u doljnjem prozoru. Pritiskom na gumb olovčice u poljima "Javni ključ", "Privatni ključ" i "Seed" moguće je ručno promijeniti vrijednosti navedenih polja. Ukoliko tajni ključ ne odgovara javnom ključu, enkapsulacija će biti neispravna.


Program se također sastoji i od enkripcije.

Pritiskom na gumb "Generiraj seed" generiramo seed koji se koristi za kreiranje privatnog i javnog ključa. Pritiskom na gumb "Generiraj par ključeva" generiramo privatni i javni ključ. Pritiskom na gumb "Kriptiraj" dobivamo šifru.

Pritiskom na gumb "Dekriptiraj poruku" provodi se dekripcija šifre korištenjem tajnog ključa.

Algoritam
Crystals-Kyber ostvaren je na nekoliko razina sigurnosti. Ovdje su navedeni odgovarajući setovi parametara.
Set parametara | n | k | q | η1 | η2 | (du, dv) | δ |
Kyber512 | 256 | 2 | 3329 | 3 | 2 | (10, 4) | 2-139 |
Kyber768 | 256 | 3 | 3329 | 2 | 2 | (10, 4) | 2-164 |
Kyber1024 | 256 | 4 | 3329 | 2 | 2 | (11, 5) | 2-174 |
Funkcije enkapsulacije
Generiranje ključeva
KYBER.CCAKEM.KeyGen()
Izlaz: Javni ključ pk - B (12 · k · n/8 + 32)
Izlaz: Tajni ključ sk - B (24 · k · n/8 + 96)
z ← B32 (pk, sk') := Kyber.CPAPKE.KeyGen() sk := (sk' ‖ pk ‖ H(pk) ‖ z) return (pk, sk)
Duljine uz definirane konstante (u bajtovima):
Javni ključ - pk: 800
Tajni ključ - sk: 1632
Enkapsulacija simetričnog ključa
Funkcija enkapsulacije ključa na ulazu uzima prethodno generirani javni ključ te pomoću njega vraća
dva druga parametra. Šifru i zajedničku tajnu.
Zajednička tajna je u ovom slučaju vektor duljine 32 bajta i predstavlja generirani simetrični
ključ
koji treba enkapsulirati u asimetričnom algoritmu. Šifra je enkapsulirani simetrični
ključ.
KYBER.CCAKEM.Enc(pk)
Ulaz: Javni ključ pk - B (12 · k · n/8 + 32)
Izlaz: Šifra c - B (du · k · n/8 + dv ·
n/8)
Izlaz: Zajednička tajna K - B*
m ← B32 m ← H(m) (K, r) := G(m ‖ H(pk)) c := Kyber.CPAPKE.Enc(pk, m, r) K := KDF(K ‖ H(c)) return (c, K)
Duljine uz definirane konstante (u bajtovima):
Šifra - c: 768
Zajednička tajna - K: 32
Dekapsulacija simetričnog ključa
Funkcija dekapsulacije prima šifru te s pomoću tajnog ključa vraća dekapsuliranu zajedničku tajnu
(ključ za simetričnu kriptografiju).
KYBER:CCAKEM:Dec(c, sk)
Ulaz: Šifra c - B (du · k · n/8 + dv ·
n/8)
Ulaz: Tajni ključ sk - B (24 · k · n/8 + 96)
Izlaz: Zajednička tajna K - B*
pk := sk + 12 · k · n/8 h := sk + 24 · k · n/8 + 32 ∈ B32 z := sk + 24 · k · n/8 + 64 m' := Kyber.CPAPKE.Dec(s, (u, v)) (K', r') := G(m' ‖ h) c' := Kyber.CPAPKE.Enc(pk, m', r') if c = c' then return K := KDF(K' ‖ H(c)) else return K := KDF(z ‖ H(c)) end if return K
Duljine uz definirane konstante (u bajtovima):
Zajednička tajna - K: 32
Funkcije enkripcije
Generiranje ključeva
Funkcija generiranja ključeva vraća dva vektora različitih duljina.
KYBER.CPAPKE.KeyGen()
Izlaz: Tajni ključ sk - B (12 · k · n/8)
Izlaz: Javni ključ pk - B (12 · k · n/8 + 32)
d ← B32 (ρ, σ) := G(d) N := 0 for i from 0 to k - 1 do for j from 0 to k - 1 do Â[i][j] := Parse(XOF(ρ, j, i)) end for end for for i from 0 to k - 1 do s[i] := CBDη1(PRF(σ, N )) N := N + 1 end for for i from 0 to k - 1 do e[i] := CBDη1(PRF(σ, N )) N := N + 1 end for ŝ := NTT(s) ê := NTT(e) t̂ := Â ◦ ŝ + ê pk := (Encode12(t̂ mod+q)‖ρ) . pk := As + e sk := Encode12(ŝ mod+q) . sk := s return (pk , sk)
Duljine uz definirane konstante (u bajtovima):
Javni ključ - pk: 768
Tajni ključ - sk: 800
Enkripcija poruke
Za enkripciju poruke koristi se javni ključ I “salt”, što je vektor 32 nasumično odabrana bajta.
Bitno je naglasiti da je ulazna poruka također 32 bajtni vektor te ukoliko želimo enkriptirati poruku
proizvoljne duljine,
moramo obaviti dopunu do duljine djeljive s 32 te šifrirati koristeći neki od poznatih modova
operacije u blok kodovima.
KYBER.CPAPKE.Enc(pk ,m , r)
Ulaz: Javni ključ pk - B (12 · k · n/8 + 32)
Ulaz: Poruka m - B 32
Ulaz: Salt r - B 32
Izlaz: Šifra c - B (du · k · n/8 + dv ·
n/8)
N := 0 t̂ := Decode12(pk ) ρ := pk + 12 · k · n/8 for i from 0 to k - 1 do for j from 0 to k - 1 do ÂT [i][j] := Parse(XOF(ρ, i, j)) end for end for for i from 0 to k - 1 do r[i] := CBDη1(PRF(r, N )) N := N + 1 end for for i from 0 to k - 1 do e1[i] := CBDη2 (PRF(r, N )) N := N + 1 end for e2 := CBDη1(PRF(r, N )) r̂ := NTT(r) u := NTT-1(ÂT ◦ r̂) + e1 v := NTT-1(t̂T ◦ r̂) + e2 + Decompressq(Decode1(m), 1) c1 := Encodedu(Compressq(u, du)) c2 := Encodedv(Compressq(v, dv)) return c = (c1 ‖ c2)
Duljine uz definirane konstante (u bajtovima):
Šifra - c: 768
Dekripcija poruke
Funkcija dekapsulacije prima šifru te s pomoću tajnog ključa vraća dekapsuliranu zajedničku tajnu
(ključ za simetričnu kriptografiju).
KYBER.CPAPKE.Dec(sk, c)
Ulaz: Tajni ključ sk - B (12 · k · n/8)
Ulaz: Šifra c - B (du · k · n/8 + dv ·
n/8)
Izlaz: Poruka m - B 32
u := Decompressq(Decodedu(c), du) v := Decompressq(Decodedv(c + du · k · n/8), dv) ŝ := Decode12(sk) m := Encode1(Compressq(v - NTT-1(ŝT ◦ NTT(u)), 1)) return m
Duljine uz definirane konstante (u bajtovima):
Poruka - K: 32
Algoritam enkripcije
Generiranje ključa

Alice generira matricu A dimenzija n x n nasumičnih koeficijenata,
te dva vektora, s dimenzije K i vektor e, vrlo malih koeficijenata.
Nakon toga računa vektor t također dimenzije K.
Objavljuje javni ključ (A,t) te za sebe ostavlja privatni ključ (s)
Enkripcija poruke

Bob generira nasumični vektor r duljine K te pomoću njega,
javnog ključa dobivenog od Alice, malih error-a e1 i e2 te same poruke m dobiva
šifru (u, v).
Računanje v dijela

U ovom koraku t se rastavlja na svoje dijelove A x s + e.
Množenjem svih komponenti s r dobivamo rAs + re.
Imajući na umu da su koeficijenti greški (e, e1, e2) izrazito mali, oni ne pridonose mnogo
cjelini.
Onda je r x e vrlo mal i objedinjujemo ga s e2 te i dalje imamo vrlo neznatan
vektor. (Na slici žuti bez naziva)
Ono što nam ostaje na kraju je rAs + greška + m
Računanje u x s dijela

U se rastavlja na r x A + e1 te se oba dijela vektorski množe sa
s.
U prethodnom koraku smo se vidi da je v jednako rAs + greška + m.
No u ovom koraku dobivamo da je vektorski umnožak u x s jedak rAs + e1s.
Možemo prepoznati jednak dio obje jednadže - rAs i znajući da je e1s također vrlo malih
koeficijenata
govorimo kako je u x s aproksimativno jednako v - m!
Dekripcija poruke

Nakon što su prethodni koraci uspješno obavljeni sama dekripcija poruke postaje vrlo jednostavna.
Oduzimanjem u x s od v. Uvrštavajući prethodno raspisane korake, poništavaju se
izrazi rAs
i ostaje samo m + greška gdje je greška dovoljno mala da ne utječe na
originalnu poruku.
Literatura
-
Roberto Avanzi, Joppe Bos, Léo Ducas, Eike Kiltz, Tancrède Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe, Gregor Seiler, Damien Stehlé
CRYSTALS-Kyber Algorithm Specifications And Supporting Documentation
-
Hauke Malte Steffen, Lucie Johanna Kogelheide, Timo Bartkewitz
In-depth Analysis of Side-Channel Countermeasures for CRYSTALS-Kyber Message Encoding on ARM Cortex-M4