#Skupaj z Python Napredno geslo2.py
import cryptolib
import uos # Za generiranje naključnih števil (IV)
import math # Za izračun paddinga

# ----- Funkcije za pomoč (če cryptolib ne omogoča avtomatskega paddinga) -----
# PKCS7 Padding je standarden način za dodajanje bajtov do polnega bloka
def pkcs7_pad(data, block_size):
    padding_len = block_size - (len(data) % block_size)
    # Če je dolžina podatkov že večkratnik block_size, dodamo celoten blok paddinga
    if padding_len == 0:
        padding_len = block_size
    padding = bytes([padding_len]) * padding_len
    return data + padding

def pkcs7_unpad(padded_data):
    padding_len = padded_data[-1]
    return padded_data[:-padding_len]
# --------------------------------------------------------------------------

def sifriraj_in_desifriraj_aes_cbc_rp2040():
    # Ključ mora biti 16 bajtov (AES-128), 24 bajtov (AES-192) ali 32 bajtov (AES-256)
    # Za MicroPython ponavadi uporabimo AES-128 zaradi omejenih virov.
    geslo = b'inv6OlP3_oiz9heK' # 16 bajtov ključ
    
    # Originalno sporočilo - daljše in z ponavljajočimi se deli za prikaz varnosti CBC
    originalno_sporocilo = b'To je skrivno sporocilo, ki ga zelimo varno posiljati. To je skrivno sporocilo, ki ga zelimo varno posiljati.'

    # 1. Generiranje naključnega IV (Inicializacijski vektor)
    # IV mora biti 16 bajtov dolg in naključen. Pošlje se skupaj s šifriranimi podatki.
    iv = uos.urandom(16) # ustvarimo 16 naključnih bajtov
    print(f"Generiran IV: {iv.hex()}")

    # 2. Inicializacija AES šifre v CBC načinu
    # V cryptolib je '2' običajno način za CBC.
    try:
        sifra = cryptolib.aes(geslo, 2, iv) # Način 2 za CBC, podamo tudi IV
    except Exception as e:
        print(f"Napaka pri inicializaciji AES v CBC načinu: {e}")
        print("Preverite dokumentacijo vaše verzije cryptolib.aes za pravilne parametre CBC načina.")
        print("Morda boste morali posodobiti cryptolib ali uporabiti drug način uvoza.")
        return

    # 3. Dodajanje paddinga sporočilu
    # Podatki morajo biti večkratnik velikosti bloka (16 bajtov za AES).
    podatki_s_paddingom = pkcs7_pad(originalno_sporocilo, 16)
    
    print(f"\nOriginalno sporočilo (brez paddinga): {originalno_sporocilo}")
    print(f"Sporočilo s paddingom: {podatki_s_paddingom}")
    print(f"Dolžina sporočila s paddingom: {len(podatki_s_paddingom)} bajtov")

    # 4. Šifriranje
    kodirani_podatki = sifra.encrypt(podatki_s_paddingom)
    print(f"Zakodirani podatki: {kodirani_podatki.hex()}") # Hex izpis za lažjo berljivost

    # 5. Dešifriranje (potrebujemo nov objekt šifre z istim ključem in IV-jem)
    # Ključno: za dešifriranje potrebujete isti IV, ki je bil uporabljen pri šifriranju!
    # Ta IV morate shraniti in posredovati skupaj s šifriranimi podatki.
    sifra_desifriranje = cryptolib.aes(geslo, 2, iv) 
    odkodirani_podatki_s_paddingom = sifra_desifriranje.decrypt(kodirani_podatki)

    # 6. Odstranjevanje paddinga
    odkodirani_podatki = pkcs7_unpad(odkodirani_podatki_s_paddingom)

    print(f"Odkodirani podatki (brez paddinga): {odkodirani_podatki}")

    # Preverba
    if originalno_sporocilo == odkodirani_podatki:
        print("\nŠifriranje in dešifriranje CBC sta bila uspešna!")
    else:
        print("\nNapaka pri šifriranju/dešifriranju CBC.")

# Zaženemo primer
sifriraj_in_desifriraj_aes_cbc_rp2040()