Prima pagină » Diverse » Analiza forensică și steganografică a imaginilor cu Nicușor Dan și Florian Coldea. Nu există DOVEZI că ar fi fost modificate manual sau cu AI

Analiza forensică și steganografică a imaginilor cu Nicușor Dan și Florian Coldea. Nu există DOVEZI că ar fi fost modificate manual sau cu AI

Analiza forensică și steganografică a imaginilor cu Nicușor Dan și Florian Coldea. Nu există DOVEZI că ar fi fost modificate manual sau cu AI

Pe ultima „sută de metri” a campaniei electorale pentru alegerile prezidențiale din România, un set de fotografii a stârnit un val de reacții publice, controverse aprinse și speculații mediatice. Respectivele fotografii i-au adus în prim-plan pe Nicușor Dan – candidat la președinție și pe Florian Coldea – fost director adjunct al SRI.

Fotografiile au fost publicate în mediul online de Elena Lasconi, la rândul ei candidat pentru fotoliul de la Cotroceni. Lasconi a fost cea care l-a întrebat pe Nicușor Dan, în timpul uneia dintre cele trei dezbateri electorale, dacă a avut și o altă întâlnire cu Florian Coldea în afară de cea despre care vorbise, de la Ambasada Franței.

Dincolo de contextul politic și de momentul apariției acestor fotografii în spațiul public, s-au pus și mai multe întrebări extrem de interesante.

  • Sunt aceste imagini autentice sau fabricate?
  • Au fost modificate?
  • Conțin mesaje ascunse?
  • Sunt generate cu AI?

Analiză completă forensică și steganografică

Acest articol răspunde tehnic la aceste întrebări, printr-o analiză completă forensică și steganografică.

Vom parcurge următorii pași pentru fiecare fotografie:

  1. Extragerea metadatelor (EXIF/XMP)
  2. Detecția steganografică LSB
  3. Analiza tabelelor de cuantizare JPEG
  4. Error Level Analysis (ELA)
  5. Estimarea globală a zgomotului
  6. Spectru Fourier (FFT)
  7. Distribuția coeficienților DCT
  8. Detectarea copy–move (ORB keypoint matching)

Metodologie pe scurt

  • Metadate: extragem informații de cameră, dată și software din fișierul JPEG.
  • LSB Steganografie: verificăm dacă biții cei mai puțin semnificativi ai unui canal de culoare (albastru) conțin text ascuns.
  • Cuantizare JPEG: examinăm tabelele de compresie pentru nereguli care ar indica unelte neobișnuite.
  • ELA: suprapunem imaginea originală cu una recomprimată pentru a evidenția retușuri locale.
  • Zgomot: calculăm deviația standard a diferenței dintre imagine și o versiune blurată – o anomalie de zgomot poate indica splicing.
  • FFT & DCT: analizăm conținutul în domeniul frecvență pentru artefacte stego sau grilaj de blocuri.
  • Copy–Move: comparăm caracteristici ORB între regiuni ale aceleiași imagini pentru a găsi copii interne.

1. „coldea.jpg”

Rezumat rezultate
  • Metadate: complet lipsă → imagine curată de tag-uri identificabile.
  • LSB Stego: niciun text coerent extras.
  • Cuantizare: tabele standard, fără modificări personalizate.
  • ELA: hartă uniform întunecată, fără zone retușate.
  • Zgomot (σ ≈ 4.8): constant, fără regiuni anormale.
  • FFT: pic central luminos, decădere radială – conținut natural.
  • DCT: distribuție Gaussiană, fără vârfuri de cuantizare neobișnuite.
  • Copy–Move: puncte ORB dispersate, fără cluster de copiere.
  • Concluzie: „coldea.jpg” este autentică, netaftată și nu conține mesaje ascunse.

2. „nicusor_2.jpg”

Rezumat rezultate
  • Metadate: minimale sau absente.
  • LSB Stego: doar caractere ÿ → nimic semnificativ.
  • Cuantizare: identică ca pattern cu prima imagine.
  • ELA: uniform întunecat, fără artefacte de compoziție.
  • Zgomot (σ ≈ 3.4): valoare ușor mai mică, dar constantă.
  • FFT & DCT: forme naturale, fără linii de bloc sau spike-uri.
  • Copy–Move: nicio regiune copiată identificată.
  • Concluzie: „nicusor_2.jpg” se aliniază complet cu o sursă autentică de cameră.

Concluzii generale

Fotografiile au trecut cu brio testele pentru:

  • Steganografie (tehnică prin care informația este ascunsă într-o zonă de informație aparent inofensivă pentru a o păstra secretă);
  • Analiză de retuș/manipulare;
  • Artefacte frecvențiale și de zgomot;
  • Detectarea copierii interne.

Din punct de vedere forensic, nu există dovezi că oricare dintre ele ar ascunde informații secrete sau ar fi fost modificate (manual sau cu AI).

Librării și comenzi de instalare

pip install pillow           # manipulare imagini, EXIF, ELA
pip install opencv-python    # procesare imagini, FFT, DCT, ORB
pip install numpy            # calcule matriciale
pip install matplotlib       # vizualizări (histograme, ELA, FFT)
pip install pandas           # tabele (metadate, cuantizare)
pip install piexif           # extras opțional de EXIF mai avansat

2. Script Python complet (forensic_analysis.py)

#!/usr/bin/env python3
import sys
from io import BytesIO
from PIL import Image, ImageChops, ImageEnhance, ExifTags, ImageFilter
import piexif
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import cv2

def extract_exif(img: Image.Image) -> pd.DataFrame:
    # încearcă cu piexif, fallback la PIL
    metadata = []
    try:
        exif_dict = piexif.load(img.info['exif'])
        for ifd in exif_dict:
            for tag_id, value in exif_dict[ifd].items():
                tag = piexif.TAGS[ifd].get(tag_id, {'name':tag_id})['name']
                metadata.append({'Tag': f"{ifd}.{tag}", 'Value': value})
    except Exception:
        raw = img.info.get('exif')
        if raw:
            metadata.append({'Tag': 'RawBytesLength', 'Value': len(raw)})
    return pd.DataFrame(metadata)


def reveal_lsb(img_path: str) -> str:
    arr = np.array(Image.open(img_path))
    blue = arr[:, :, 2].flatten() & 1
    bits = blue.reshape(-1, 8)
    chars = [chr(int("".join(b.astype(str)), 2)) for b in bits]
    message = "".join(chars).split('\x00')[0]
    return message if message.strip() else None


def quant_tables(img: Image.Image) -> pd.DataFrame:
    rows = []
    qt = img.quantization if hasattr(img, 'quantization') else {}
    for table_id, table in qt.items():
        for idx, val in enumerate(table):
            rows.append({'Table': table_id, 'Index': idx, 'Value': val})
    return pd.DataFrame(rows)


def error_level_analysis(img: Image.Image, quality=90, scale=10):
    buf = BytesIO()
    img.save(buf, format='JPEG', quality=quality)
    buf.seek(0)
    recompressed = Image.open(buf)
    diff = ImageChops.difference(img, recompressed)
    return ImageEnhance.Brightness(diff).enhance(scale)


def noise_std(img: Image.Image, blur_radius=2) -> float:
    blur = img.filter(ImageFilter.GaussianBlur(radius=blur_radius))
    noise = np.array(img, float) - np.array(blur, float)
    return float(np.std(noise))


def fourier_spectrum(gray: np.ndarray):
    f = np.fft.fft2(gray)
    fshift = np.fft.fftshift(f)
    return np.log(np.abs(fshift) + 1)


def dct_coeffs_hist(gray: np.ndarray, pos=(1,2), bins=50):
    h, w = gray.shape
    coeffs = []
    for i in range(0, h, 8):
        for j in range(0, w, 8):
            block = gray[i:i+8, j:j+8]
            if block.shape == (8,8):
                d = cv2.dct(block.astype(np.float32))
                coeffs.append(d[pos])
    plt.hist(coeffs, bins=bins)
    plt.title(f"DCT coef dist {pos}")
    plt.xlabel("Value")
    plt.ylabel("Frequency")
    plt.show()


def copy_move_orb(gray: np.ndarray, n_features=2000, match_count=100):
    orb = cv2.ORB_create(n_features)
    kp, des = orb.detectAndCompute(gray, None)
    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
    matches = bf.match(des, des)
    # filtrare self-match și apropiere
    good = []
    for m in matches:
        if m.queryIdx != m.trainIdx:
            p1 = np.array(kp[m.queryIdx].pt)
            p2 = np.array(kp[m.trainIdx].pt)
            if np.linalg.norm(p1-p2) > 20:
                good.append(m)
    good = sorted(good, key=lambda x: x.distance)[:match_count]
    vis = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
    for m in good:
        pt1 = tuple(map(int, kp[m.queryIdx].pt))
        pt2 = tuple(map(int, kp[m.trainIdx].pt))
        cv2.line(vis, pt1, pt2, (255,0,0), 1)
    plt.imshow(cv2.cvtColor(vis, cv2.COLOR_BGR2RGB))
    plt.title("Copy–Move ORB matches")
    plt.axis('off')
    plt.show()


def analyze_image(path: str):
    print(f"\n=== Analiză {path} ===")
    img = Image.open(path).convert('RGB')
    gray = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

    # 1. Metadate
    df_exif = extract_exif(img)
    print("\n>> EXIF metadata:")
    print(df_exif if not df_exif.empty else "  ")

    # 2. Stego LSB
    msg = reveal_lsb(path)
    print("\n>> LSB hidden:", msg or "")

    # 3. Quant tables
    df_q = quant_tables(img)
    print("\n>> JPEG quant tables (first 16 intrări):")
    print(df_q.head(16))

    # 4. ELA
    ela = error_level_analysis(img)
    plt.imshow(ela)
    plt.title("ELA (×10)")
    plt.axis('off')
    plt.show()

    # 5. Noise
    ns = noise_std(img)
    print(f"\n>> Noise σ: {ns:.2f}")

    # 6. Fourier
    spec = fourier_spectrum(gray)
    plt.imshow(spec, cmap='viridis')
    plt.title("Fourier Spectrum")
    plt.axis('off')
    plt.show()

    # 7. DCT histogram
    dct_coeffs_hist(gray)

    # 8. Copy–move
    copy_move_orb(gray)


if __name__ == "__main__":
    if len(sys.argv)  [ ...]")
        sys.exit(1)
    for img_path in sys.argv[1:]:
        analyze_image(img_path)

-------------
chmod +x forensic_analysis.py
./forensic_analysis.py coldea.jpg nicusor_2.jpg ponta.jpg

-------------

NOTĂ - Acest script va parcurge toate cele 8 etape pentru fiecare fișier JPEG furnizat și va afișa:
  • Tabelul de metadate EXIF
  • Mesajul LSB (dacă există)
  • Primele intrări din tabelele de cuantizare
  • Imaginea ELA
  • Valoarea deviației standard a zgomotului
  • Spectrul Fourier
  • Histogramă DCT
  • Vizualizarea potrivirilor ORB pentru copy–move

Citește și:

Nicușor Dan a REFUZAT să jure pe Biblie că spune adevărul, după ce Elena Lasconi l-a acuzat, în direct, de minciună

Nicuşor Dan, reacție în scandalul „Autorizaţie pentru spital oncologic privat”: „E incalificabil să foloseşti bolnavi de cancer ca temă electorală”

Gabriela Firea: „În mandatul primarului general Nicușor Dan, investițiile în spitale au bătut pasul pe loc, banii au fost ținuți în CONTURI!”

PSD a publicat avizul pentru spitalul privat de oncologie pentru copii, cu semnătura lui Nicușor Dan. „Parcă era ilegal, cum de l-ai semnat? Câtă PERVERSITATE!”

După ce l-a făcut MINCINOS, Elena Lasconi i-a cerut lui Nicușor Dan să jure pe Biblie. Reacția candidatului independent

Mediafax
Caz șocant! Bebeluș de 4 luni testat pozitiv la cocaină. Părinții au fost puși sub acuzare
Digi24
Tragedia ascunsă a „supraviețuitorilor miraculoși”: Au sfidat moartea, dar nu au fost pregătiți pentru ce i-a așteptat după dezastru
Cancan.ro
Ți se rupe sufletul! Ce scrie în necrologul lui Felix Baumgartner: s-a aflat acum ce fel de om a fost
Prosport.ro
Imagini spectaculoase cu Nicolae Dică și soția lui, în costum de baie roz, la plajă
Adevarul
Joburile în care românii simpli câștigă cât un director la stat: „Cel mai bine plătit ia 11.000 de euro pe lună, iar cel mai prost 6.000”
Mediafax
HOROSCOP 21 iulie. Zi de cotitură pentru Raci și revelații pentru toți nativii
Click
Ce adoră chef Sorin Bontea să consume vara: „Prima oară am mâncat în Egipt”. Florin Dumitrescu îi împărtășește gusturile culinare
Wowbiz
„Noi am fost DRAGOSTE”. Prima reacție a Mihaelei Rădulescu după moartea lui Felix Baumgartner
Antena 3
Ilie Bolojan îi trimite pe demnitari la autobuz. „Cine nu are permis, să meargă cu transportul în comun”
Digi24
Cristian Diaconescu: Există o invitație a lui Donald Trump adresată lui Nicușor Dan. Trebuie să concretizăm rapid această bilaterală
Cancan.ro
Ce neregulă ar fi avut parapanta lui Felix Baumgartner. Un martor a văzut tot: O astfel de cădere nu poate fi datorată decât unei probleme tehnice
Ce se întâmplă doctore
Vrei mai mulți bani? Lucruri care atrag bogăția în viața ta. Ce să porți în permanență
observatornews.ro
Premii acordate cetățenilor care raportează evaziunea fiscală. Guda: "Primești bonus, în cont, bani direct"
StirileKanalD
Urmărire ca în filme la Giurgiu! Un bărbat a furat o ambulanță din curtea spitalului și a fugit cu ea. A fost oprit cu focuri de armă
KanalD
Mihail supraviețuise unui accident aviatic cu câteva ore înainte. Cine sunt cei doi bărbați care au murit în avionul prăbușit la Gura Portiței
Ciao.ro
Poveştile de iubire care au rămas doar o amintire! Imagini tari cu Gina Pistol, Răzvan Fodor sau Andra Măruţă şi foştii parteneri
Promotor.ro
Noua Dacia Sandero, surprinsă fără camuflaj pe drumurile publice! Mai are rost să îți cumperi Duster?
Descopera.ro
Capcanele pe care Hitler și Stalin și le-au întins reciproc
Capital.ro
Mașinile care vor fi interzise din 2030. Ordinul venit de la UE. Toți sunt obligați
Evz.ro
Rețeta tradițională de tzatziki. Sosul, cremos și răcoritor
A1
Cea mai sexy prințesă a Europei. În ce ipostază seducătoare a pozat Maria-Olympia a Greciei
Stirile Kanal D
O nouă pistă în căutarea lui Emil Gânj. Criminalul s-a întâlnit cu un cioban și i-a furat mâncarea
Kfetele
Familia lui Felix Baumgartner a anunțat când și unde va avea loc înmormântarea. Ce au transmis apropiații. „Ne dorim ca în aceste momente să ne putem lua rămas bun în liniște.”
RadioImpuls
Locul în care va fi înmormântat Felix Baumgartner i-a facut pe toți să plângă. Hotărârea luată de familie îți frânge sufletul
Râzi cu lacrimi
BANCUL ZILEI. BULĂ: – Dumnezeule, cât ești de frumoasă! Vrei să fii iubita mea?
Descopera.ro
Ziua în care a ars una dintre cele şapte minuni ale lumii