Pod simetricnom kriptografijom se podrazumeva sistem za sifrovanje koji koristi isti kljuc i za sifrovanje i za desifrovanje.
Dve vrste sifarskih sistema:
uglavnom se koristi random generator i sabiranje po modulu dva ili xor
drugi nacin je da se random dogovore za kljuc koji je duzine iste kao poruka i da se to iskoristi (mana dug kljuc koji treba razmeniti, kljuc ne sme da se ponavlja)
zasto je lose da se ponovi isti kljuc vise puta
random generator treba da ima dobre osobine:
primeri: RC4(probijena), A5(teorijski probijen ali se koristi), chacha20
sifruje blokove u blokove i koristi isti kljuc za sifrovanje i desifrovanje
padding- ako poruka nije odgovarajuce duzine
-PKCS#7 padding(Public Key Criptography Standards #7) - ako treba dopuniti poruku sa 5 bajta svaki bajt ima vrednost 5 odnosno poruka se dopunjava sa 5 bajta 0x05, ako je duzina poruke vec deljiva sa duzinom bloka, dodaje se jos jedan blok gde svi bajtovi imaju vrenost duzine bloka
Prvi standard, zastareo ne koristi se vise u izvornom obliku, koristi se trostruki des(sa dva ili tri kljuc- nije mnogo sigurniji sa tri nego sa dva, a lakse je razmeniti dva kljuca od tri) Meet In The Middle napad za dvosturki des
AES (advanced encription standard) je blokovska sifra koja sifruje blok od 128 bita u blok od 128 bita, koristeci kljuc duzine 128,192 ili 256 bita. Sifrovanje i desiforvanje se odvija u rundama, u zavisnosti od duzine kljuca imamo razlicit broj rundi 10,12 ili 14
openssl enc -aes-256-cbc -out proba.txt
openssl enc -d -aes-256-cbc -in proba.txt Da bi blokovske sifre mogle da sifruju dugacke tekstove koristite se razliciti modovi:
Ovo je kao da imamo zapravo n posebnih poruka, svaka se sifruje posebno i salje odnosno
Prednosti: najlaksi za implementaciju, moguca paralelizacija, otpornost na greske Mana: isti blokovi se sifruju u iste blokove, pokazi Tuxa
def encrypt(key: bytes, message: bytes) -> bytes:
blocks = bytes_to_blocks(message)
ciphertext = bytes()
for block in blocks:
ciphertext += encrypt_block(key, block)
return ciphertext
def decrypt(key: bytes, ciphertext: bytes) -> bytes:
blocks = bytes_to_blocks(ciphertext)
message = bytes()
for block in blocks:
message += decrypt_block(key, block)
return messageOvde se pravi lanac sifrovanja, imamo neki inicijalni blok(iv) koji koristimo za prvo sifrovanje, a zatim se prvo sifrovanje koristi za sledece…
ne bi trebalo ponavljati iv Mana: pisanje na disku
def encrypt(key: bytes, message: bytes, iv: bytes) -> bytes:
blocks = bytes_to_blocks(message)
cipher = [iv]
for block in blocks:
cipher.append(encrypt_block(key, xor(block, cipher[-1])))
return blocks_to_bytes(cipher)
def decrypt(key: bytes, ciphertext: bytes) -> bytes:
blocks = bytes_to_blocks(ciphertext)
message = bytes()
for i in range(1, len(blocks)):
message += xor(decrypt_block(key, blocks[i]), blocks[i-1])
return messageKoristi se da od blokovske sifre napravi protocnu sifru, tako sto se blok otvorenog teksta xoruje sa blokom Ek(nonce+brojac)
Mana: ponovljeni nonce otkriva previse informacija, lako se menjaju poruke, a da ostane neprimeceno
def encrypt(key: bytes, message: bytes, n: int) -> bytes:
keystream = bytes()
for i in range(0, 1 + len(message) // block_size):
keystream += encrypt_block(key, int.to_bytes(n + i, block_size))
return xor(message, keystream)
def decrypt(key: bytes, ciphertext: bytes, n: int) -> bytes:
keystream = bytes()
for i in range(0, 1 + len(ciphertext) // block_size):
keystream += encrypt_block(key, int.to_bytes(n + i, block_size))
return xor(ciphertext, keystream)Jedan od naprednijih modova, pored sifrovanja generise i auth kod, koji sluzi kao potvrda da niko nije menjao poruku i da je poruku generisao neko ko zna privatni kljuc, generise se zajedno sa sifratom