Documentazione tecnica approfondita dell'architettura crittografica di PDF Pro
Trasferimento File con Crittografia End-to-End
PDF Pro Whitepaper WP-001 — Architettura e Sicurezza
Questo whitepaper descrive l'architettura del sistema di Trasferimento Sicuro di PDF Pro, un meccanismo di trasferimento file con crittografia end-to-end in cui i file vengono cifrati lato client tramite AES-256-GCM prima del caricamento. Il server archivia esclusivamente testo cifrato opaco e non è in grado di decifrare, ispezionare o leggere il contenuto dei file in nessun momento. Il sistema supporta due modalità di chiave: una chiave casuale generata automaticamente (trasportata tramite il frammento URL, che non viene mai inviato al server) o una chiave derivata da passphrase tramite PBKDF2. In entrambe le modalità, la chiave di cifratura esiste solo nei browser del mittente e del destinatario. Questo documento dettaglia le primitive crittografiche, il flusso di dati, il modello di minaccia e le limitazioni documentate del sistema. Nota sulla terminologia: questo sistema non utilizza prove a conoscenza zero (ZKP). Quando affermiamo che il server ha "zero conoscenza" dei tuoi file, intendiamo che — come conseguenza della crittografia lato client — il server detiene esclusivamente testo cifrato che non è in grado di decifrare.
Il sistema di Trasferimento Sicuro segue una rigida separazione client-server in cui tutte le operazioni crittografiche avvengono esclusivamente nel browser:
Il server è progettato intenzionalmente come un "canale passivo" per i dati cifrati. Non dispone di alcuna conoscenza della chiave di cifratura, della passphrase o del contenuto dei file. Questo è garantito architetturalmente, non semplicemente tramite policy.
Principio di progettazione: Il server deve poter essere compromesso senza compromettere i dati degli utenti. Anche con accesso completo al database e con l'esecuzione di codice lato server, un attaccante non può decifrare i file trasferiti.
Tutta la cifratura dei file utilizza l'algoritmo di cifratura autenticata AES-256-GCM, accessibile tramite la Web Crypto API nativa del browser. Questo garantisce sia la riservatezza (i dati non possono essere letti) sia l'integrità (i dati non possono essere modificati senza rilevamento).
| Parametro | Valore | Motivazione |
|---|---|---|
| Algoritmo | AES-256-GCM | Approvato dal NIST, cifratura autenticata con dati associati (AEAD) |
| Dimensione chiave | 256 bit | Lunghezza massima della chiave AES; fornisce sicurezza a 128 bit contro la forza bruta |
| Dimensione IV | 96 bit (12 byte) | Lunghezza IV raccomandata dal NIST per la modalità GCM |
| Dimensione tag | 128 bit (16 byte) | Tag di autenticazione a lunghezza intera per la massima protezione dell'integrità |
| Generazione IV | crypto.getRandomValues() | Generatore di numeri casuali crittograficamente sicuro |
// Flusso di cifratura semplificato (Web Crypto API) const iv = crypto.getRandomValues(new Uint8Array(12)); const salt = crypto.getRandomValues(new Uint8Array(16)); // Deriva la chiave dalla passphrase (vedi Sezione 1.4) const key = await deriveKey(passphrase, salt); // Cifra il file const ciphertext = await crypto.subtle.encrypt( { name: "AES-GCM", iv: iv }, key, fileArrayBuffer ); // Pacchetto: [salt (16B)] + [iv (12B)] + [ciphertext + tag] const blob = concatenate(salt, iv, ciphertext);
Il blob cifrato finale è una concatenazione di tre componenti: il salt di 16 byte (usato per la derivazione della chiave), l'IV di 12 byte (usato per AES-GCM) e il testo cifrato con il tag di autenticazione GCM di 16 byte aggiunto in coda. Questo blob è ciò che il server riceve e archivia.
Il Trasferimento Sicuro supporta due modalità di chiave mutuamente esclusive. La modalità viene selezionata dal mittente al momento della creazione del trasferimento.
Nella modalità predefinita, non è coinvolta alcuna passphrase. Il browser genera direttamente una chiave AES a 256 bit casuale e crittograficamente sicura:
crypto.getRandomValues() e crypto.subtle.generateKey().#).Quando il mittente sceglie di impostare una passphrase, la chiave viene derivata da essa tramite PBKDF2:
| Parametro | Valore | Motivazione |
|---|---|---|
| Algoritmo | PBKDF2 | Raccomandato dal NIST SP 800-132; ampiamente verificato |
| Funzione hash | SHA-256 | Hash crittografico standard; output a 256 bit |
| Iterazioni | 600.000 | Soddisfa la raccomandazione OWASP 2023 per PBKDF2-SHA256 |
| Dimensione salt | 128 bit (16 byte) | Unico per trasferimento; previene attacchi rainbow table |
| Lunghezza chiave di output | 256 bit | Corrisponde al requisito della chiave AES-256 |
async function deriveKey(passphrase, salt) { // Importa la passphrase come materiale grezzo della chiave const keyMaterial = await crypto.subtle.importKey( "raw", new TextEncoder().encode(passphrase), { name: "PBKDF2" }, false, ["deriveKey"] ); // Deriva la chiave AES-256-GCM return crypto.subtle.deriveKey( { name: "PBKDF2", salt: salt, iterations: 600000, hash: "SHA-256" }, keyMaterial, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"] ); }
Nota sulla sicurezza: La sicurezza nella Modalità B dipende dall'entropia della passphrase. Si raccomandano passphrase di almeno 12 caratteri che combinino maiuscole, minuscole, cifre e simboli.
Il ciclo di vita completo di un trasferimento sicuro segue questo percorso:
crypto.getRandomValues().#).crypto.getRandomValues().| Elemento Dati | Il Server ha Accesso? | Dettagli |
|---|---|---|
| Blob cifrato (salt + IV + testo cifrato + tag) | Sì | Dati binari opachi; il server non può interpretarne il contenuto |
| ID trasferimento | Sì | Gli identificatori di trasferimento sono valori UUID v4 generati da gen_random_uuid() di PostgreSQL, che fornisce 122 bit di casualità crittografica dal CSPRNG del server |
| Nome file originale | Sì | Archiviato nei metadati per la visualizzazione al destinatario |
| Dimensione file originale | Sì | Archiviata nei metadati a scopo di visualizzazione |
| Timestamp di scadenza | Sì | Utilizzato per l'applicazione dell'eliminazione automatica |
| Contatore/limite download | Sì | Utilizzato per burn-on-read e applicazione del limite di download |
| ID utente mittente (se autenticato) | Sì | Collega il trasferimento all'account per la gestione |
| Passphrase | No — mai | Non viene mai inviata al server; non lascia mai il browser |
| Chiave di cifratura derivata | No — mai | Esiste solo nella memoria del browser durante le operazioni di cifratura/decifratura |
| Contenuto del file in chiaro | No — mai | Solo il testo cifrato raggiunge il server |
| Contatore di iterazioni PBKDF2 | No | Hardcoded nel client; non viene trasmesso al server |
Tutti i trasferimenti sicuri sono effimeri per design. Non è disponibile alcuna opzione di archiviazione permanente.
| Opzione | Comportamento | Applicazione |
|---|---|---|
| Burn on read | Il blob cifrato viene eliminato immediatamente dopo il primo download avvenuto con successo | Lato server: il blob viene eliminato dallo storage al termine del flusso di download |
| 1 ora | Eliminato automaticamente dopo 1 ora indipendentemente dallo stato del download | Lato server: job di pulizia pianificato + verifica scadenza all'accesso |
| 24 ore | Eliminato automaticamente dopo 24 ore | Come sopra |
| 7 giorni | Conservazione massima; eliminato automaticamente dopo 7 giorni | Come sopra |
Quando un trasferimento scade o viene bruciato alla lettura, il blob cifrato viene eliminato definitivamente da Supabase Storage. Il record dei metadati viene conservato per 30 giorni in uno stato di eliminazione temporanea (per indagini su abusi) prima di essere eliminato definitivamente. Il record dei metadati non contiene la chiave di cifratura, la passphrase né alcuna informazione che possa essere utilizzata per ricostruire il file.
| Minaccia | Vettore di Attacco | Mitigazione |
|---|---|---|
| Compromissione del server | L'attaccante ottiene accesso completo al database e allo storage | Tutti i dati archiviati sono testo cifrato AES-256-GCM. L'attaccante ottiene solo blob opachi. Senza la passphrase, forzare AES a 256 bit è computazionalmente non fattibile. |
| Intercettazione di rete (MITM) | L'attaccante intercetta i dati in transito | Tutto il traffico utilizza TLS 1.3. Anche se TLS venisse violato, l'attaccante otterrebbe solo blob cifrati (come nel caso di compromissione del server). |
| Passphrase debole | L'attaccante esegue un attacco a forza bruta su una passphrase breve o comune | PBKDF2 con 600K iterazioni rende ogni tentativo computazionalmente costoso. Una passphrase di 4 caratteri richiederebbe comunque risorse computazionali significative. L'interfaccia utente applica una lunghezza minima della passphrase e fornisce un feedback sulla robustezza. |
| Intercettazione della passphrase | L'attaccante intercetta la passphrase condivisa tra mittente e destinatario | La passphrase viene condivisa fuori banda (non tramite il nostro sistema). Si consiglia di condividerla tramite un canale diverso dall'URL di trasferimento. Questa è una responsabilità dell'utente. |
| Manomissione del codice lato client | L'attaccante modifica il JavaScript servito all'utente | Tutti gli asset vengono serviti tramite HTTPS con la CDN di Vercel. Gli hash di integrità delle sottorisorse (SRI) proteggono dalla manomissione a livello CDN. Gli utenti possono verificare il codice sorgente negli strumenti di sviluppo del browser. |
| Estrazione dalla memoria | L'attaccante estrae la chiave di cifratura dalla memoria del browser | Le chiavi dell'API Web Crypto sono contrassegnate come non estraibili ove possibile. Le chiavi derivate esistono in memoria solo durante l'operazione di cifratura/decifratura. L'isolamento della memoria del browser fornisce protezione a livello di sistema operativo. |
| Attacco replay | L'attaccante riproduce un blob cifrato catturato | Ogni trasferimento ha un ID univoco ed è protetto da limiti di download e scadenza. I trasferimenti burn-on-read vengono eliminati dopo il primo accesso. |
Limitazioni documentate: Nessun sistema di sicurezza è perfetto. Crediamo nella divulgazione trasparente delle limitazioni note.
Firma Crittografica dei Documenti con Priorità alla Privacy
PDF Pro Whitepaper WP-002 — Architettura e Sicurezza
Questo whitepaper descrive l'architettura del sistema di Firma Privacy di PDF Pro, un meccanismo di firma crittografica dei documenti in cui il documento PDF non lascia mai il browser del firmatario. Il sistema utilizza ECDSA con la curva P-256 e l'hashing SHA-256 per produrre firme digitali distaccate. Solo l'hash del documento, la firma crittografica e la chiave pubblica vengono trasmessi al server. Le chiavi private vengono generate, cifrate e archiviate esclusivamente nel browser dell'utente tramite IndexedDB, protette dalla derivazione della chiave PBKDF2 (600.000 iterazioni) e dalla cifratura AES-256-GCM. Questo documento dettaglia l'architettura completa di firma e verifica, il modello di gestione delle chiavi, lo schema del payload firmato, il design della catena di audit, il modello di minaccia e le limitazioni documentate.
Il sistema di Firma Privacy è progettato attorno a un vincolo fondamentale: il documento PDF non deve mai essere trasmesso al server. Questo è garantito architetturalmente tramite un modello di firma distaccata.
Garanzia fondamentale: Il server non vede, riceve né elabora mai il documento PDF. L'unico dato correlato al documento che il server riceve è un hash SHA-256 — un valore a dimensione fissa di 256 bit dal quale il documento originale non può essere ricostruito.
| Parametro | Valore | Motivazione |
|---|---|---|
| Algoritmo di firma | ECDSA (Elliptic Curve Digital Signature Algorithm) | NIST FIPS 186-4; firme compatte; elevata sicurezza per bit di chiave |
| Curva | P-256 (secp256r1 / prime256v1) | Approvata dal NIST; livello di sicurezza a 128 bit; ampio supporto della Web Crypto API |
| Funzione hash | SHA-256 | NIST FIPS 180-4; digest a 256 bit; resistente alle collisioni |
| Dimensione chiave | Chiave privata a 256 bit, chiave pubblica a 512 bit (non compressa) | Standard per P-256; equivalente a RSA a ~3072 bit |
| Dimensione firma | 64 byte (r: 32 byte, s: 32 byte) | Compatta; adatta all'archiviazione e alla trasmissione |
| Formato firma | IEEE P1363 (r || s grezzo) | Output nativo della Web Crypto API; codificato in base64url per l'archiviazione |
Codifica della firma: L'ECDSA della Web Crypto API con P-256 produce una firma grezza di 64 byte composta da due interi di 32 byte (r || s) in formato big-endian a larghezza fissa. Questo output grezzo viene codificato in base64url per l'archiviazione. NON è codificato DER — è il formato IEEE P1363 prodotto nativamente dalla Web Crypto API.
// 1. Hash del documento PDF (lato client) const fileBuffer = await file.arrayBuffer(); const hashBuffer = await crypto.subtle.digest("SHA-256", fileBuffer); const hashHex = Array.from(new Uint8Array(hashBuffer)) .map(b => b.toString(16).padStart(2, '0')).join(''); // 2. Firma l'hash con la chiave privata (lato client) const signature = await crypto.subtle.sign( { name: "ECDSA", hash: "SHA-256" }, privateKey, // CryptoKey da IndexedDB (decifrata) hashBuffer ); // 3. Invia al server: hash + firma + chiave pubblica (NON il PDF) await submitSignature({ documentHash: hashHex, signature: base64Encode(signature), publicKey: exportedPublicKeyJWK });
| Tipo di Chiave | Contesto | Ciclo di Vita | Archiviazione |
|---|---|---|---|
| Effimera | Utenti ospiti (non autenticati) | Generata per sessione; distrutta alla chiusura della scheda | Solo in memoria (oggetto CryptoKey); mai persistita |
| Persistente | Utenti autenticati (con accesso effettuato) | Generata una volta; persistita tra le sessioni; revocabile | IndexedDB (cifrata con PBKDF2 + AES-256-GCM) |
// Genera coppia di chiavi ECDSA P-256 (Web Crypto API) const keyPair = await crypto.subtle.generateKey( { name: "ECDSA", namedCurve: "P-256" }, true, // estraibile (necessario per cifratura + archiviazione) ["sign", "verify"] ); // Esporta la chiave pubblica come JWK per la registrazione sul server const publicKeyJWK = await crypto.subtle.exportKey("jwk", keyPair.publicKey); // Esporta la chiave privata come JWK per l'archiviazione cifrata const privateKeyJWK = await crypto.subtle.exportKey("jwk", keyPair.privateKey);
Formato chiave pubblica: Le chiavi pubbliche vengono esportate e archiviate in formato JWK (JSON Web Key). L'impronta digitale della chiave è calcolata come SHA-256 del JWK canonico contenente solo i campi pubblici {crv, kty, x, y} con le chiavi ordinate alfabeticamente.
Le chiavi private persistenti non vengono mai archiviate in chiaro. Prima di essere scritte su IndexedDB, la chiave privata (esportata come JSON JWK) viene cifrata usando lo stesso schema del Trasferimento Sicuro:
| Parametro | Valore |
|---|---|
| Derivazione chiave | PBKDF2-SHA256, 600.000 iterazioni |
| Salt | 16 byte casuali (per chiave) |
| Cifratura | AES-256-GCM |
| IV | 12 byte casuali (per cifratura) |
| Input | JWK della chiave privata (stringa JSON, codificata UTF-8) |
| Output archiviato in IndexedDB | { salt, iv, ciphertext, publicKeyJWK, keyId, createdAt } |
// Struttura del record IndexedDB per una chiave di firma cifrata { "keyId": "uuid-v4-unique-identifier", "publicKey": { /* formato JWK, non cifrato */ }, "encryptedPrivateKey": { "salt": "base64-encoded-16-bytes", "iv": "base64-encoded-12-bytes", "ciphertext": "base64-encoded-aes-gcm-ciphertext" }, "algorithm": "ECDSA", "curve": "P-256", "createdAt": "2026-04-16T00:00:00.000Z", "userId": "supabase-auth-user-id" }
Recupero della chiave: Se l'utente dimentica la passphrase di firma, la chiave privata non può essere recuperata. Non disponiamo della passphrase, della chiave derivata né di alcun meccanismo per aggirare la protezione PBKDF2 + AES-GCM. Gli utenti dovrebbero esportare backup delle chiavi.
PDF Pro utilizza un modello di firma distaccata, il che significa che la firma viene archiviata separatamente dal documento. Questo è il meccanismo critico per la privacy: il documento non lascia mai il dispositivo del firmatario.
Garanzia crittografica: SHA-256 è una funzione hash unidirezionale. Dato solo l'hash e3b0c44298fc1c14..., fornisce una solida garanzia crittografica, nell'ambito delle assunzioni di sicurezza di ECDSA e SHA-256, che il documento originale non possa essere ricostruito. L'hash non rivela nulla sul contenuto, la lunghezza o la struttura del documento, se non la conferma dell'identità al momento del ricalcolo dell'hash.
Il seguente schema JSON definisce il record di firma completo archiviato sul server:
{
"schemaVersion": "1.0",
"signatureId": "uuid-v4",
"documentHash": "sha256-hex-64-chars",
"hashAlgorithm": "SHA-256",
"signature": "base64-encoded-ecdsa-signature",
"signatureAlgorithm": "ECDSA",
"curve": "P-256",
"publicKey": {
"kty": "EC",
"crv": "P-256",
"x": "base64url-encoded-x-coordinate",
"y": "base64url-encoded-y-coordinate"
},
"signer": {
"identityLevel": "authenticated | self-asserted",
"displayName": "string or null",
"email": "string or null",
"userId": "supabase-uid or null"
},
"timestamp": "ISO-8601-UTC",
"metadata": {
"fileName": "original-file-name.pdf",
"fileSize": 123456,
"pageCount": 12,
"clientVersion": "2.0.0",
"userAgent": "browser-user-agent-string"
},
"auditChain": {
"previousEventHash": "sha256-of-previous-audit-event or null",
"eventHash": "sha256-of-this-record"
}
}La verifica della firma è un processo in due fasi: verifica crittografica lato client seguita da una verifica incrociata lato server.
const isValid = await crypto.subtle.verify( { name: "ECDSA", hash: "SHA-256" }, importedPublicKey, signatureBuffer, hashBuffer );
isValid === true, la firma è crittograficamente valida: il documento non è stato modificato dalla firma e la firma è stata prodotta dal titolare della chiave privata corrispondente.| Risultato | Significato |
|---|---|
| Valida (Autenticata) | La firma è crittograficamente valida E la chiave pubblica appartiene a un utente PDF Pro registrato e autenticato. |
| Valida (Auto-dichiarata) | La firma è crittograficamente valida ma l'identità del firmatario è auto-dichiarata (utente ospite o nome non verificato). |
| Non valida | La verifica crittografica ha fallito. Il documento è stato modificato dopo la firma, oppure la firma è danneggiata. |
| Revocata | La firma era valida ma è stata esplicitamente revocata dal firmatario. |
| Nessuna firma trovata | Non esiste alcun record di firma per questo hash del documento. |
Ogni evento di firma e verifica viene registrato in una catena di audit a prova di manomissione. Gli eventi sono concatenati tramite hash: ogni evento include l'hash SHA-256 dell'evento precedente, formando una catena solo-aggiunta simile a una blockchain.
| Tipo di Evento | Trigger | Dati Registrati |
|---|---|---|
KEY_REGISTERED | L'utente registra una nuova chiave pubblica | JWK della chiave pubblica, ID utente, timestamp |
DOCUMENT_SIGNED | L'utente firma un documento | Hash del documento, firma, chiave pubblica, identità del firmatario, timestamp |
SIGNATURE_VERIFIED | Qualsiasi utente verifica una firma | Hash del documento, risultato della verifica, informazioni sul verificatore (se autenticato), timestamp |
SIGNATURE_REVOKED | Il firmatario revoca una firma | ID firma, motivo della revoca, timestamp |
KEY_REVOKED | L'utente revoca una chiave pubblica | ID chiave pubblica, motivo della revoca, timestamp |
// Ogni evento di audit include: { "eventId": "uuid-v4", "eventType": "DOCUMENT_SIGNED", "timestamp": "ISO-8601-UTC", "data": { /* payload specifico dell'evento */ }, "previousEventHash": "sha256-of-previous-event-json", "eventHash": "sha256-of-this-event-json-without-eventHash" } // Rilevamento delle manomissioni: per verificare la catena, calcolare: // SHA-256(JSON.stringify(evento senza campo eventHash)) // e confermare che corrisponda a eventHash. // Poi confermare che previousEventHash corrisponda all'eventHash dell'evento precedente.
Se viene modificato qualsiasi evento nella catena, tutti i collegamenti hash successivi si romperanno, rendendo immediatamente rilevabile la manomissione. Questo fornisce una solida garanzia di integrità della catena di audit.
Limitazione importante: La catena hash rende rilevabile la manomissione all'interno della sequenza di eventi registrati. Tuttavia, un amministratore del database con accesso diretto potrebbe teoricamente eliminare e ricostruire la catena. Garanzie più forti richiederebbero una marcatura temporale esterna o un'attestazione di terze parti, che non è implementata in questa versione.
| Livello | Requisiti | Proprietà di Fiducia | Caso d'Uso |
|---|---|---|---|
| Autenticato | Utente PDF Pro con accesso effettuato ed email verificata; coppia di chiavi persistente registrata sull'account | Email verificata da Supabase Auth; chiave pubblica associata all'account autenticato; catena di audit collegata all'ID utente | Documenti aziendali, contratti, accordi formali |
| Auto-dichiarato | Utente ospite o utente autenticato con nome inserito autonomamente; coppia di chiavi effimera o persistente | Integrità crittografica garantita; l'identità del firmatario è auto-dichiarata e non verificata in modo indipendente | Firma rapida, documenti personali, accordi informali |
Nota: Nell'interfaccia del prodotto, 'self_asserted' può essere visualizzato come 'Identità Auto-dichiarata' o 'Firma Ospite'. 'authenticated' può essere visualizzato come 'Account Autenticato'. Queste sono etichette di visualizzazione per gli stessi livelli di identità sottostanti.
Associazione dell'identità: Una firma "autenticata" significa che la chiave pubblica è registrata a un account PDF Pro con email verificata. NON significa che l'identità reale del firmatario sia stata verificata tramite documento d'identità governativo, dati biometrici o verifica di persona. Non eseguiamo controlli Know Your Customer (KYC).
| Minaccia | Vettore di Attacco | Mitigazione |
|---|---|---|
| Attacco replay | L'attaccante copia una firma valida e la applica a un documento diverso | La firma è associata all'hash SHA-256 del documento specifico. Un documento diverso avrà un hash diverso e la verifica ECDSA fallirà. |
| Contraffazione | L'attaccante crea una firma valida senza la chiave privata | La sicurezza di ECDSA P-256 si basa sul Problema del Logaritmo Discreto su Curve Ellittiche (ECDLP). Contraffare una firma senza la chiave privata è computazionalmente non fattibile (livello di sicurezza a 128 bit). |
| Sostituzione della chiave | L'attaccante registra la propria chiave pubblica e afferma che una firma è stata effettuata da qualcun altro | Le firme autenticate associano la chiave pubblica a un'email verificata. La catena di audit registra quale chiave ha firmato quale documento. Gli eventi di registrazione della chiave sono concatenati tramite hash. |
| Sostituzione del documento | L'attaccante modifica un PDF firmato e afferma che la firma sia ancora valida | Qualsiasi modifica al PDF cambia il suo hash SHA-256. La firma esistente fallirà la verifica contro il nuovo hash. Trovare una collisione (documento diverso con lo stesso hash) richiede ~2^128 operazioni. |
| Furto della chiave privata | L'attaccante estrae la chiave privata cifrata da IndexedDB | La chiave privata è cifrata con AES-256-GCM, con chiave derivata da PBKDF2 (600K iterazioni). Senza la passphrase, decifrare la chiave è computazionalmente non fattibile. |
| Compromissione del server | L'attaccante ottiene accesso completo al server | Il server dispone solo di chiavi pubbliche e record di firma. Le chiavi private non raggiungono mai il server. Un attaccante non può contraffare nuove firme. Potrebbe eliminare o modificare record esistenti, ma le interruzioni nella catena hash sarebbero rilevabili. |
| Manomissione della catena di audit | L'attaccante modifica gli eventi della catena di audit sul server | Eventi con hash concatenati: la modifica di qualsiasi evento rompe la catena da quel punto in avanti. Gli strumenti di verifica indipendenti possono rilevare le interruzioni della catena. |
Cosa NON sono le firme PDF Pro:
Il nostro impegno: Costruiamo la sicurezza attraverso l'architettura, non il marketing. Questi whitepaper descrivono esattamente come funzionano i nostri sistemi, comprese le loro limitazioni. Crediamo che gli utenti attenti alla sicurezza meritino una completa trasparenza tecnica. Se hai domande su qualsiasi aspetto della nostra architettura, contattaci all'indirizzo info@webdesign9.com.