english version - versione inglese
Questo progetto è nato dalla necessità di estrarre semplicemente il contenuto dei file .P7M in alcune applicazioni Delphi.
Dal 1 gennaio 2019 gli sviluppatori italiani hanno dovuto affrontare il nuovo sistema di Fatturazione Elettronica, divenuto obbligatorio per Legge.
Le Fatture Elettroniche sono esenzialmente rappresentante in file XML che vengono firmate digitalmente utilizzando la modalità CAdES-BEM.
Gli sviluppatori che gestiscono fatture devono quindi generare questi file XML ed essere in grado di rileggerli, ma quando si tratta di una fattura firmata digitalmente inglobata in un file .P7M molti di loro hanno trovato la soluzione poco ortodossa di rimuovere l'envelope trovando il tag di apertura e di chiusura XML all'interno del file e copiando quella parte.
Abbiamo pensato che questo non potesse essere il modo professionale di gestire questa operazione, quindi abbiamo iniziato a studiare e siamo finiti a creare questo progetto.
- Libreria PKCS#7 Extractor per Delphi / Free Pascal / Lazarus
- Indice
- File inclusi
- Applicazione demo
- Unit tests
- File necessari
- Nota sui file codificati Base64
- Cronologia versioni
- Compatibilità con i compilatori
- Progetti per il futuro
- Ringraziamenti
- Progetti che utilizzano questa libreria
- Commenti
Questa è la unit principale con cui gli sviluppatori dovranno confrontarsi, esporta alcune utili funzioni per gestire i messaggi PKCS#7.
Ogni funzione esportata ha una sua storia così lunga che a raccontarla nessuno ci crederebbe. Siamo chiari, non è stato per nulla facile, ma da ora dovrebbe esserlo. Iniziamo con il descrivere le funzioni esportate per il wrapper delle funzioni di OpenSSL.
function Load: Boolean;Richiamare la funzione Load per inizializzare il wrapper, questo causerà se necessario il caricamento della libreria. Se è stata precedentemente specificata una cartella valida utilizzando la procedure SetFolder, verrà tentato di caricare la libreria dalla cartella specificata.
Il valore ritornato indica se il caricamento e/o collegamento della libreria è avvenuto con successo ed implica che tutte le funzioni necessarie siano state tornare.
Chiamare questa funzione più volte non ha alcun effetto pratico a meno che non venga scaricata prima la libreria.
function Loaded: Boolean;Ritorna se il wrapper è attualmente inizializzato correttamente.
procedure Unload;La procedure Unload causa la deinizializzazione del wrapper ma, come detto prima, la libreria rimarrà residente in memoria.
procedure SetFolder(const S: String);Richiamare SetFolder prima di Load per impostare una cartella specifica da cui caricare la libreria. Si notic che qualora la libreria fosse già stata caricata da questo wrapper o da qualsiasi altro componente o classe, le chiamate a questa procedura non avranno alcun effetto pratico.
Se viene specificata una cartella non valida o una cartella in cui non si trovi la libreria, verranno seguiti i normali percorsi utilizzati dal sistema operativo per il caricamento della libreria.
Non ha alcun effetto nel caso la libreria sia linkata staticamente nell'eseguibile.
function GetFolder: String;La funzione GetFolder ritorna il percorso assoluto da cui la libreria è attualmente caricata in memoria oppure una stringa vuota se la libreria non è presente in memoria.
Questo potrebbe differire dalla cartella specificata utilizzando SetFolder qualora la cartella specificata non sia valida o non contenga la libreria o ancora qualora la libreria fosse già precedentemente caricata.
function GetVersion: String;La funzione GetVersion ritorna semplicemente la stringa contenente la versione della libreria attualmente caricata in memoria o una stringa vuota qualora il wrapper non sia inizializzato.
La funzione corrispondente è stata introdotta in OpenSSL dalla versione 0.9.7, qyuindi questa funzione ritornerà una stringa vuota con versioni precedenti.
function GetErrorCode: Cardinal;Ritorna un codice numerico che rappresenta l'ultimo errore interno della libreria OpenSSL.
function GetError(const ErrorCode: Cardinal): String;Ritorna la descrizione testuale per un dato codice di errore.
function GetError: String;Ritorna la descrizione testuale per l'ultimo errore interno della libreria OpenSSL.
Prima di continuare, è necessario prendere visione di due tipi indispensabili.
TVerifyStatus = (vsUnknown, vsFull, vsPartial);| Valore | Descrizione |
|---|---|
vsUnknown |
Nessun dato è stato caricato o i dati non erano validi. |
vsPartial |
I dati e la struttura dell'envelope sono stati verificati. |
vsFull |
E' stata eseguita una verifica completa dei dati. |
TSignatureMode = (smUnknown, smPKCS7, smCMS);| Valore | Descrizione |
|---|---|
smUnknown |
Nessun dato è stato caricato o i dati non erano validi. |
smPKCS7 |
I dati sono stati caricati ed erano imbustati con funzioni PKCS#7. |
smCMS |
I dati sono stati caricati ed erano imbustati con funzioni CMS. |
Quelle che seguono sono le funzioni di utilità.
function Extract(InStream, OutStream: TStream): Boolean;Dato un messaggio PKCS#7 presente in uno stream, ritorna il contenuto estratto ad un altro stream.
Ritorna se l'operazione è andata a buon fine o meno.
Si prega di notare che InStream.Position deve essere impostata al punto di inizio del messaggio PKCS#7 prima di richiamare questa funzione, perché la stessa abbia successo. La proprietà Position sarà variata al termine dell'esecuzione di questa funzione, anche se la stessa non ha prodotto un risultato positivo.
I dati risultati - se ve ne sono - sono aggiunti in coda al contenuto corrente dello stream di output, è quindi necessario fornire uno stream vuoto prima di richiamare questa funzione per ottenere solamente il contenuto del messaggio estratto.
function Extract(InFilename, OutFilename: String): Boolean;Funzione parallela che estrae i dati da un file PKCS#7 specificato con nome file ad un altro file. Ritorna se l'operazione è avvenuta correttamente o meno.
function Extract(Filename: String): Boolean;Estrae il contenuto di un file contenente un messaggio PKCS#7 usando come file di output un nome di file calcolato automaticamente. Ritorna se l'operazione è avvenuta correttamente o meno. Si tenga conto che se il nome di file di destinazione non può essere calcolato, l'operazione fallirà.
Per vedere come il file viene calcolato si legga della funzione GuessFilename qui sotto.
function GuessFilename(Filename: String): String;Prova a calcolare il nome di file di destinazione di un dato file originale, il che significa rimuovere l'estensione aggiunta (solitamente ".p7m") dal nome di file.
Per verificare che l'estensione sia stata aggiunta invece che sostituita, se nel file risultante non dovesse esserci un'altra estensione, la funzione fallità e ritornerà il nome del file originale.
function Verify(Stream: TStream): TVerifyStatus;Funzione necessaria a verificare se un dato stream contiene o meno un messaggio PKCS#7 valido. Come per Extract(TStream, TStream) ci si ricordi che la proprietà Position dello stream di input deve essere impostato all'inizio del messaggio PKCS#7 prima di essere passato a questa funzione.
A differenza di Extract(TStream, TStream) comunque, questa funzione manterrà il valore della proprietà Position al suo valore corrente.
function Verify(Filename: String): TVerifyStatus;Verifica semplicemente che un dato file contenga un messaggio PKCS#7 valido.
function Extract(Stream: TStream; var S: String): Boolean;Funzione per ottenere il contenuto di un messaggio PKCS#7 estratto da uno stream direttamente in una stringa. Se l'operazione fallisse il valore tornato sarebbe False e sarà tornata uns stringa vuota.
function ExtractToString(Filename: String; var S: String): Boolean;Funzione per ottenere il contenuto di un messaggio PKCS#7 estratto da un file direttamente in una stringa. Se l'operazione fallisse il valore tornato sarebbe False e sarà tornata uns stringa vuota.
function SignatureMode(Stream: TStream): TSignatureMode; overload;Ritorna il tipo di funzioni crittografiche utilizzate per imbustare dei dati. Preserva il valore della proprietà Position dello stream.
function SignatureMode(const Filename: String): TSignatureMode; overload;Ritorna il tipo di funzioni crittografiche utilizzate per imbustare un file.
Quasta unit esporta una classe chiamata TPKCS7Message che è il cuore pulsante dove il lavoro viene svolto. Qualora si preferisse lavorare con questa, ecco come funziona. Si informa che a differenza delle suddette funzioni rapide, questa classe non tenta di caricare la libreria da sola, quindi bisogna sempre ricordare di richiamare Load() prima di utilizzarla.
constructor TPKCS7Message.Create;Crea un'istanza della classe.
procedure TPKCS7Message.Clear;Pulisce tutte le variabili locali cancellando eventuali dati caricati.
function TPKCS7Message.LoadFromStream(Stream: TStream): Boolean;Carica un messaggio PKCS#7 da uno stream, ritorna True al successo.
function TPKCS7Message.LoadFromFile(Filename: String): Boolean;Carica un messaggio PKCS#7 da un file, ritorna True al successo.
function TPKCS7Message.SaveToStream(Stream: TStream): Boolean;Salva il contenuto precedentemente caricato con LoadFromStream o LoadFromFile su uno stream, ritorna True al successo.
function TPKCS7Message.SaveToFile(Filename: String): Boolean;Salva il contenuto precedenemtente caricato con LoadFromStream o LoadFromFile su un file, ritorna True al successo.
property SignatureMode: TSignatureMode;Proprietà in sola lettura che rappresenta il tipo di funzioni crittografiche utilizzate per imbustare i dati.
property VerifyStatus: TVerifyStatus;Proprietà in sola lettura che rappresenta il tipo di verifica che è stata effettuata sui dati.
La classe estrae tutto il contenuto dai dati e li memorizza durante l'uso delle funzioni LoadFromStream o LoadFromFile.
Si è scelto di memorizzare i dati in memoria RAM utilizzando un TMemoryStream, visto che i dati per cui era inizialmente destinata questa classe dovevano essere di dimensioni ridotte.
Tuttavia è possibile che ci sia la necessità di reindirizzare i dati estratti altrove, per questo motivo è stato definito un evento, scatenato nel momento in cui la classe ha bisogno di allocare lo spazio dove memorizzare i dati.
In questo modo è possibile redirigere i dati a qualsiasi discendente di TStream che sia scrivibile.
property OnStreamCreate: TStreamCreateEvent;Per esempio potremo definire nella nostra Form un evento con cui andare a creare un file temporaneo.
type
TMyForm = class(TForm)
...
procedure FormCreate(Sender: TObject);
private
FPKCS7Message: TPKCS7Message;
protected
procedure PKCS7Stream(Sender: TObject; var AStream: TStream);
...
...
procedure TMyForm.PKCS7Stream(Sender: TObject; var AStream: TStream);
begin
AStream := TFileStream.Create('temp.tmp', fmCreate or fmOpenReadWrite or fmShareDenyWrite)
end;
...
procedure TMyForm.FormCreate(Sender: TObject);
begin
FPKCS7Message := TPKCS7Message.Create;
FPKCS7Message.OnStreamCreate := PKCS7Stream;
...
end;
...La classe si occuperà di richiamare il Free dello stream creato quando questo non sarà più necessario.
ADDENDUM: nella cartella "Utils" potete trovare il file CCLib.TempFileStream.pas che non fa parte di questa libreria ma è liberamente disponibile.
Esporta una semplice classe discendente da TStream che crea un file temporaneo con nome casuale nella cartella temporanea di sistema, impedendone l'accesso ad altre applicazioni.
Questo file sarà eliminato automaticamente quando verrà richiamato il metodo Free della classe.
L'applicazione demo contenuto nella cartella \Demo è un semplice estrattore che permette inoltre di cambiare la cartella da cui le librerie OpenSSL vengono caricate e selezionare un file, estrarlo verso un file di destinazione e visualizzare il suo contenuto in un controllo TMemo.
La unit tests contenuta nella cartella \Tests è un progetto di un'applicazione console che esegue tutta una serie di test sulla libreria e sul wrapper.
Il software richiede l'esistenza di alcune cartelle e file all'interno della stessa cartella in cui l'eseguibile viene lanciato, ecco una lista delle cartelle e che cosa devono contenere.
| Nome cartella | Obbligatoria? | Descrizione |
|---|---|---|
| Data | SI | Questa cartella deve contenere una serie di file sui quali i test saranno eseguiti. |
| DataCheck | SI | In questa cartella devono essere contenuti dei file con i risultati attesi dall'estrazione dei file nella cartella "Data". Ogni file deve avere esattamente lo stesso nome file ed estensione del file sorgente. I test verranno eseguiti solamente sui file che hanno corrispondenza nelle due cartelle. |
| OpenSSL\x32 | NO* | Questa cartella deve contenere delle sottocartelle ognuna delle quali deve contenere le librerie di OpenSSL in forma binaria. I test verranno eseguiti per ogni cartella trovata. Inserire qui solamente librerie compilate a 32-bit |
| OpenSSL\x64 | NO* | Stessa cosa di cui sopra, ma per le librerie 64-bit. |
| Temp | NO** | Questa cartella è utilizzata mentre i test vengono eseguiti per salvare alcuni file. Non inserire alcun file in questa cartella, questa cartella verrà eliminata ogni volta che vengono eseguiti i test. |
| Addendum | |
|---|---|
| * | Questa cartella è richiesta solamente se l'applicazione demo è compilata per questa architettura. |
| ** | Questa cartella verrà creata automaticamente dal software ogni volta che viene eseguito. |
Per salvare un report dei test su un file di testo per una migliore analisi - o per smettere di perder tempo a scorrere la console - torna utile la redirezione dell'output.
PKCS7ExtractorTest.exe >report.txt
Genererà un file chiamato "report.txt" contenente tutte le informazioni necessarie.
Per ottenere una lista delle librerie OpenSSL presenti nelle cartelle .\OpenSSL\x32 e/o .\OpenSSL\x64 è possibile eseguire il programma di testo come:
PKCS7ExtractorTest.exe /list
Questo causerà l'output delle sole versioni delle librerie che il programma è in grado di caricare. Per salvare questa lista su un file di testo, è possibile sfruttare la ridirezione dell'output eseguendo il comando:
PKCS7ExtractorTest.exe /list >output.txt
Questo genererà un file chiamato "output.txt".
Avendo una lunga lista di versioni diverse di OpenSSL nella cartella .\OpenSSL perdavamo molto tempo eseguendo i test, per questa ragione abbiamo implementato la possibilità di specificare quali versioni eseguire.
E' sufficiente eseguire l'eseguibile specificando i nomi delle sottocartelle da cui caricare, ad esempio:
PKCS7ExtractorTest.exe 0.9.6 openssl-0.9.8x-i386-win32 "openssl ultima"
Eseguirà i test solamente con le librerie presenti nella cartelle chiamate "0.9.6", "openssl-0.9.8x-i386-win32" e "openssl ultima".
Il progetto richiede le librerie GNU Win32/64 binarie per Windows.
La versione minima supportata dovrebbe essere la 0.9.6 rilasciata il 24 settembre 2000. Non siamo in grado di testare librerie precedenti a tale versione.
Con la versione 1.1.0 le librerie OpenSSL hanno avuto una riscrittura importante e stiamo attualmente lavorando per capire come rendere questa librerie compatibile con entrambe le versioni. Non garantiamo che questa libreria sarà in futuro compatibile con tali versioni.
Questa unit è stata testata con le seguenti versioni binarie:
| Versione | Data | x86 | x64 | Note |
|---|---|---|---|---|
| 0.9.6 | 24 Sep 2000 | ✅ | N/A | |
| 0.9.6b | 9 Jul 2001 | ✅ | N/A | |
| 0.9.6i | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.6j | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| N/A | STIAMO ATTUALMENTE INVESTIGANDO SU QUESTO PROBLEMA | |||
| 0.9.6l | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| N/A | STIAMO ATTUALMENTE INVESTIGANDO SU QUESTO PROBLEMA | |||
| 0.9.7 | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.7a | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.7b | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.7c | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.7d | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.7e | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.7f | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.7g | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.7h | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.7i | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| N/A | STIAMO ATTUALMENTE INVESTIGANDO SU QUESTO PROBLEMA | |||
| 0.9.7k | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.7l | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| N/A | STIAMO ATTUALMENTE INVESTIGANDO SU QUESTO PROBLEMA | |||
| 0.9.8 | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.8a | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.8b | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.8c | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.8d | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.8e | 23 Feb 2007 | ✅ | N/A | |
| 0.9.8f | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.8g | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.8h | 28 May 2008 | ✅ | ✅ | |
| 0.9.8h | 28 May 2008 | ✅ | N/A | Indy / IntraWeb Edition |
| 0.9.8i | 15 Sep 2008 | ✅ | ✅ | |
| 0.9.8j | 07 Jan 2009 | ✅ | ✅ | |
| 0.9.8k | 25 Mar 2009 | ✅ | ✅ | |
| 0.9.8l | 5 Nov 2009 | ✅ | ✅ | |
| 0.9.8l | 5 Nov 2009 | ✅ | N/A | Indy Backport |
| 0.9.8m | 25 Feb 2010 | ✅ | ✅ | |
| 0.9.8n | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.8o | 01 Jun 2010 | ✅ | ✅ | |
| 0.9.8p | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.8q | 2 Dec 2010 | ✅ | ✅ | |
| 0.9.8r | 8 Feb 2011 | ✅ | ✅ | |
| 0.9.8r | 8 Feb 2011 | ✅ | ✅ | rev.2 |
| 0.9.8s | 4 Jan 2012 | ✅ | ✅ | |
| 0.9.8t | 18 Jan 2012 | ✅ | ✅ | |
| 0.9.8u | 12 Mar 2012 | ✅ | ✅ | |
| 0.9.8v | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.8w | 23 Apr 2012 | ✅ | ✅ | |
| 0.9.8x | 10 May 2012 | ✅ | ✅ | |
| 0.9.8y | 5 Feb 2013 | ✅ | ✅ | |
| 0.9.8za | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 0.9.8zb | 6 Aug 2014 | ✅ | ✅ | |
| 0.9.8zc | 15 Oct 2014 | ✅ | ✅ | |
| 0.9.8zd | 8 Jan 2015 | ✅ | ✅ | |
| 0.9.8ze | 15 Jan 2015 | ✅ | ✅ | |
| 0.9.8zf | 19 Mar 2015 | ✅ | ✅ | |
| 0.9.8zg | 11 Jun 2015 | ✅ | ✅ | |
| 0.9.8zh | 3 Dec 2015 | ✅ | ✅ | |
| 1.0.0 | 29 Mar 2010 | ✅ | ✅ | |
| 1.0.0a | 1 Jun 2010 | ✅ | ✅ | |
| 1.0.0b | ??? | ??? | ??? | searching fo this |
| 1.0.0c | 2 Dec 2010 | ✅ | ✅ | |
| 1.0.0d | 8 Feb 2011 | ✅ | ✅ | |
| 1.0.0d | 8 Feb 2011 | ✅ | ✅ | rev.2 |
| 1.0.0e | 6 Sep 2011 | ✅ | ✅ | |
| 1.0.0f | 4 Jan 2012 | ✅ | ✅ | |
| 1.0.0g | 18 Jan 2012 | ✅ | ✅ | |
| 1.0.0h | 12 Mar 2012 | ✅ | ✅ | |
| 1.0.0i | 19 Apr 2012 | ✅ | ✅ | |
| 1.0.0j | 10 May 2012 | ✅ | ✅ | |
| 1.0.0k | 5 Feb 2013 | ✅ | ✅ | |
| 1.0.0l | 6 Jan 2014 | ✅ | ✅ | |
| 1.0.0m | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 1.0.0n | 6 Aug 2014 | ✅ | ✅ | |
| 1.0.0o | 15 Oct 2014 | ✅ | ✅ | |
| 1.0.0p | 8 Jan 2015 | ✅ | ✅ | |
| 1.0.0q | 15 Jan 2015 | ✅ | ✅ | |
| 1.0.0r | 19 Mar 2015 | ✅ | ✅ | |
| 1.0.0s | 11 Jun 2015 | ✅ | ✅ | |
| 1.0.0t | 3 Dec 2015 | ✅ | ✅ | |
| 1.0.1 | 14 Mar 2012 | ✅ | ✅ | |
| 1.0.1a | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 1.0.1b | 26 Apr 2012 | ✅ | ✅ | |
| 1.0.1c | 10 May 2012 | ✅ | ✅ | |
| 1.0.1d | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 1.0.1e | 11 Feb 2013 | ✅ | ✅ | |
| 1.0.1f | 6 Jan 2014 | ✅ | ✅ | |
| 1.0.1g | 7 Apr 2014 | ✅ | ✅ | |
| 1.0.1h | 5 Jun 2014 | ✅ | ✅ | |
| 1.0.1i | 6 Aug 2014 | ✅ | ✅ | |
| 1.0.1j | 15 Oct 2014 | ✅ | ✅ | |
| 1.0.1k | 8 Jan 2015 | ✅ | ✅ | |
| 1.0.1l | 15 Jan 2015 | ✅ | ✅ | |
| 1.0.1m | 19 Mar 2015 | ✅ | ✅ | |
| 1.0.1o | 12 Jun 2015 | ✅ | ✅ | |
| 1.0.1p | 9 Jul 2015 | ✅ | ✅ | |
| 1.0.1q | 3 Dec 2015 | ✅ | ✅ | |
| 1.0.1r | 28 Jan 2016 | ✅ | ✅ | |
| 1.0.1s | 1 Mar 2016 | ✅ | ✅ | |
| 1.0.1t | 3 May 2016 | ✅ | ✅ | |
| 1.0.1u | 22 Sep 2016 | ✅ | ✅ | |
| 1.0.2 | 22 Jan 2015 | ✅ | ✅ | |
| 1.0.2a | 19 Mar 2015 | ✅ | ✅ | |
| 1.0.2b | ??? | ??? | ??? | siamo alla ricerca di questa versione |
| 1.0.2c | 12 Jun 2015 | ✅ | ✅ | |
| 1.0.2d | 9 Jul 2015 | ✅ | ✅ | |
| 1.0.2e | 3 Dec 2015 | ✅ | ✅ | |
| 1.0.2f | 28 Jan 2016 | ✅ | ✅ | |
| 1.0.2g | 1 Mar 2016 | ✅ | ✅ | |
| 1.0.2h | 3 May 2016 | ✅ | ✅ | |
| 1.0.2i | 22 Sep 2016 | ✅ | ✅ | |
| 1.0.2j | 26 Sep 2016 | ✅ | ✅ | |
| 1.0.2k | 26 Jan 2017 | ✅ | ✅ | |
| 1.0.2l | 25 May 2017 | ✅ | ✅ | |
| 1.0.2m | 2 Nov 2017 | ✅ | ✅ | |
| 1.0.2n | 7 Dec 2017 | ✅ | ✅ | |
| 1.0.2o | 27 Mar 2018 | ✅ | ✅ | |
| 1.0.2p | 14 Aug 2018 | ✅ | ✅ | |
| 1.0.2q | 20 Nov 2018 | ✅ | ✅ | |
| 1.0.2r | 26 Feb 2019 | ✅ | ✅ | |
| 1.0.2s | 28 May 2019 | ✅ | ✅ | |
| 1.0.2t | 10 Sep 2019 | ✅ | ✅ | |
| 1.0.2u | 20 Dec 2019 | ✅ | ✅ |
La maggior parte di queste versioni binarie è stata trovata su indy.fulgan.com.
Siamo attualmente alla ricerca delle versioni binarie che ci mancano quindi fateci sapere qualora doveste trovarne qualcosa, saremo ben lieti di aggiungerle ai nostri test.
Ogni informazioni riguardante problemi di compatibilità sarà benvenuto.
Si è deciso di ignorare le versioni 1.1.0+ da questa tabella, così come le versioni beta che non sono adatte alla distribuzione.
La libreria non gestisce i file codificati Base64, leggere il presente capitolo per scoprire come abilitarne la gestione.
Da quando questa libreria è stata rilasciata, siamo spesso stati contattati da persone che utilizzandola hanno trovato dei file che non venivano correttamente gestiti e spesso ci venivano indicati come corrotti o "strani".
Ad una attenta analisi tutti questi file erano semplicemente codificati attraverso l'algoritmo Base64 e vista la disponibilità di un gran numero di librerie, componenti o semplici unit che gestiscono tale formato, abbiamo sempre indirizzato altrove per porre rimedio.
La scelta di tale modus operandi è stata fatta anche sulla base dei risultati di un sondaggio sulle pagine del Delphi Club Italia nel quale infatti è emerso che tale funzionalità avrebbe dovuto esulare da questa libreria in quanto non parte del processo. Molti hanno evidenziato come tanti sviluppatori avessero già risolto in proprio la problematica con una propria implementazione di un decoder Base64.
Tuttavia recenti sviluppi ci hanno spinti nella direzione di integrare un controllo ed una gestione di tali file, anche in virtù del fatto che le librerie OpenSSL includono le funzionalità per la decodifica di tale formato, ma non applicano un riconoscimento automatico del formato in entrata delle funzioni.
Le funzioni delle librerie si aspettano infatti che i dati siano racchiusi tra due separatori di blocco come qui mostrato per indicare come interpretare il dato.
-----BEGIN PKCS7-----
Q2kgZmEgcGlhY2VyZSBjaGUgc2lhdGUgY3VyaW9zaSBkaSBjb25vc2NlcmUgaWwgY29udGVudXRv
IGRlbCBub3N0cm8gdGVzdG8gZGkgcHJvdmEsIG5vbiDDqCB1biBzZW1wbGljZSBsb3JlbSBpbXBz
dW0sIG1hIHVuIHRlc3QgYWQgaG9jLiBWaSBhdWd1cmlhbW8gdW5hIGJ1b25hIGdpb3JuYXRhLg==
-----END PKCS7-----
Per questo motivo, si è introdotta una funzione in apertura dei file che verifica se è in formato Base64 ed in tal caso aggiunge i tag di apertura e chiusura di blocco.
Nonostante le librerie OpenSSL non supportino la variante URL safe dell'alfabeto di Base64, tale procedura effettua il riconoscimento di entrambi gli alfabeti e eventualmente effettua conversione verso l'alfabeto standard.
Ciò introduce un possibile comportamento fallace in quanto un file nel quale vi sia la presenza mista di elementi distintivi dei due alfabeti non dovrebbe essere considerato un file codificato Base64 valido. Tuttavia si è valutato e si ritiene che l'evenienza che un file binario rientri in questa casistica sia talmente remota da non introdurre alcun tipo di problematica nell'utilizzo di questa libreria.
Questa modifica non ha alcun effetto su tutti i file che già precedentemente si aprivano tenendo conto che:
- qualsiasi file binario contenga valori al di fuori dei suddetti alfabeti di Base64 - ad eccezione dei caratteri CR e LF - non viene modificato;
- qualsiasi file codificato Base64 contenga già tali tag ricade già nella suddetta regola.
Chi volesse abilitare questa novità introdotta può semplicemente definire la direttiva di compilazione
{$DEFINE PKCS7MANAGEBASE64}Presente anche in testa al file PKCS7Extractor.pas.
-
Versione 1.3.0.0 rilasciata il 15 giugno 2021
- aggiunta la gestione dei file codificati Base64 sfruttando un funzionamento interno delle librerie OpenSSL
Tale funzionalità non è attivata di default, ma può esserlo definendo la direttiva di compilazione PKCS7MANAGEBASE64
- aggiunta la gestione dei file codificati Base64 sfruttando un funzionamento interno delle librerie OpenSSL
-
Versione 1.2.0.0 rilasciata il 2 marzo 2020
- aggiunta la gestione dei file firmati utilizzando le funzioni di crittografia CMS (richiede librerie OpenSSL 0.9.8h o successive)
- ora compatibile con Lazarus / Free Pascal
- il sorgente non è compatibile con compilatori precedenti a Delphi 6
- tutta l'elaborazione è stata sposta in LoadFromStream, utilizza meno variabili di classe
- TPKCS7Message.Verify è stata sostituita dalla proprietà TPKCS7Message.VerifyStatus
- nuova proprietà TPKCS7Message.SignatureMode
- nuove funzioni veloci SignatureMode(Stream) and SignatureMode(String)
- nuovo evento TPKCS7Message.OnStreamCreate che consente di modificare la classe TStream da utilizzare
- Extract(Stream, S) e ExtractToString ora gestiscono i BOM e le codifiche (Delphi 2009+)
- aggiunte le funzioni GetErrorCode, GetError(Cardinal) e GetError
- non è più necessario specificare le opzioni di verifica
- non lascia un file vuoto quando si crea un nuovo file con SaveToFile e fallisce
- spostate tutte le noiose definizioni delle strutture nell'implementation
- evitato hint del compilatore Delphi (ne persistono alcuni molto sciocchi su Free Pascal / Lazarus)
- aggiunto il file CCLib.TempFileStream.pas
- testato con le librerie OpenSSL versioni 1.0.2q, 1.0.2r, 1.0.2s, 1.0.2t e 1.0.2u
- risolti bug minori e riscritto parte di codice, rimosso lo zucchero sintattico
- aggiunto file batch per la creazione automatica dei risultati attesi dei test
- aggiornati README.md, LEGGIMI.md e lo screenshot della demo
- ripristinato file dell'icona DCI nella cartella della demo
-
Versione 1.0.0.0 rilasciata il 27 novembre 2018
- primo rilascio pubblico
- correzione di errori minori
- pulizia del codice ed aggiunta commenti
- provato con alcune versioni in più di OpenSSL
-
Versione 0.9.5.0 - 26 novembre 2018
- correzione errori
-
Versione 0.9.3.0 - 25 novembre 2018
- la verifica supporta ora la verifica della firma
- aggiunto il parametro per la verifica ad ogni funzione
-
Versione 0.9.0.0 - 25 novembre 2018
- completamente modificata la struttura della libreria
- ora è necessario un solo file
- eliminate le due classi statiche
Libeay32WrapperePKCS7Message - introdotta una classe
TPKCS7Message, le funzioni rapide usano tale classe
-
Versione 0.8.2.0 - 24 novembre 2018
- rimossa
PKCS7LibraryLocationdaPKCS7Extractor.pasutilizzareLibeay32Wrapper.GetLibraryFolder - rimossa
PKCS7LibraryVersiondaPKCS7Extractor.pasutilizzareLibeay32Wrapper.SSLeay_version
- rimossa
-
Versione 0.8.0.0 - 24 novembre 2018
- aggiunta compatibilità x64
-
Versione 0.7.0.0 - 23 novembre 2018
- rimossa la funzione
LoadeddaLibeay32Wrapper, utilizzareLoad - riscritta completamente la funzione
LoadinLibeay32Wrapper - aggiunta funzione
GetLibraryFolderper avere la posizione della libreria caricata SSLeay_versionnon è più una semplice replica della funzione omonima esportata da OpenSSL ma una funzione più utile che ritorna una stringa contenente la versione
- rimossa la funzione
-
Versione 0.5.0.0 - 23 novembre 2018
- abbandonata la dipendenza dal progetto Indy, utilizza ora un proprio wrapper minimale
- rimossa la funzione
PKCS7CheckdaPKCS7Extractor.pasutilizzare le funzioniLibeay32Wrapper.Loade.Loaded - aggiunto il file
Libeay32Wrapper.pas
-
Versione 0.2.1.0 - 22 novembre 2018
- aggiunta la funzione
PKCS7GuessFilename - la funzione
PKCS7Extract(Filename)ritorna ora il nome di destinazione o una stringa vuota - compatibile con Delphi 2007
- aggiunta la funzione
-
Versione 0.2.0.0 - 22 novembre 2018
- aggiunto
PKCS7ExtractorTest.dpr - aggiunta la funzione
PKCS7Check - aggiunta la funzione
PKCS7LibraryLocation - aggiunta la funzione
PKCS7LibraryVersion - aggiunta la funzione
IsPKCS7
- aggiunto
-
Versione 0.1.1.0 - 21 novembre 2018
- risolta mancante inizializzazione della Libeay32.dll
-
Versione 0.1.0.0 - 20 novembre 2018
- prima versione funzionante
Vorremmo essere in grado di raggiungere la piena compatiblità con ogni compilatore Delphi (magari anche con Free Pascal), ma abbiamo bisogno che altri ci aiutino a testare il codice con compilatori di cui non abbiamo la licenza. Per ogni compilatore non indicato come compatibile stiamo aspettando che qualcuno si metta in contatto con noi per inviarci i test compilati con quel compilatore.
| Compilatore | S.O. | Architettura | Versione | Tester/Note | |
|---|---|---|---|---|---|
| ❌ | Borland Delphi 1 | 🗻 | N/A | No 32-bit support. | |
| ❌ | Borland Delphi 2 | 🗻 | x86 | 1.2.0.0 | Christian Cristofori |
| ❌ | Borland Delphi 3 | 🗻 | x86 | 1.2.0.0 | Non dovrebbe funzionare. |
| ❌ | Borland Delphi 4 | 🗻 | x86 | 1.2.0.0 | Non dovrebbe funzionare. |
| ❌ | Borland Delphi 5 | 🗻 | x86 | 1.2.0.0 | Non dovrebbe funzionare. |
| ✅ | Borland Delphi 6 | 🗻 | x86 | ||
| ✅ | Borland Delphi 7 | 🗻 | x86 | 1.2.0.0 | Marcello Gribaudo |
| 💭 | Borland Delphi 2005 | 🗻 | x86 | ||
| 💭 | Borland Delphi 2006 | 🗻 | x86 | ||
| 💭 | Turbo Delphi 2006 | 🗻 | x86 | ||
| ✅ | CodeGear Delphi 2007 | 🗻 | x86 | 1.2.0.0 | Christian Cristofori |
| 💭 | Embarcadero Delphi 2009 | 🗻 | x86 | ||
| 💭 | Embarcadero Delphi 2010 | 🗻 | x86 | ||
| 💭 | Embarcadero Delphi XE | 🗻 | x86 | ||
| 💭 | Embarcadero Delphi XE2 | 🗻 | x86 | ||
| 💭 | 🗻 | x64 | |||
| 💭 | Embarcadero Delphi XE3 | 🗻 | x86 | ||
| 💭 | 🗻 | x64 | |||
| 💭 | Embarcadero Delphi XE4 | 🗻 | x86 | ||
| 💭 | 🗻 | x64 | |||
| 💭 | Embarcadero Delphi XE5 | 🗻 | x86 | ||
| 💭 | 🗻 | x64 | |||
| 💭 | Embarcadero Delphi XE6 | 🗻 | x86 | ||
| 💭 | 🗻 | x64 | |||
| ✅ | Embarcadero Delphi XE7 | 🗻 | x86 | 1.2.0.0 | Diego Rigoni |
| ✅ | 🗻 | x64 | 1.0.0.0 | Diego Rigoni | |
| 💭 | Embarcadero Delphi XE8 | 🗻 | x86 | ||
| 💭 | 🗻 | x64 | |||
| 💭 | Embarcadero Delphi 10 Seattle | 🗻 | x86 | ||
| 💭 | 🗻 | x64 | |||
| ✅ | Embarcadero Delphi 10.1 Berlin | 🗻 | x86 | 1.2.0.0 | Gianni Giorgetti |
| ✅ | 🗻 | x64 | 1.0.0.0 | Christian Cristofori | |
| ✅ | Embarcadero Delphi 10.2 Tokyo | 🗻 | x86 | 1.0.0.0 | Christian Cristofori |
| ✅ | 🗻 | x64 | 1.0.0.0 | Christian Cristofori | |
| ✅ | Embarcadero Delphi 10.3 Rio | 🗻 | x86 | 1.2.0.0 | Christian Cristofori |
| ✅ | 🗻 | x64 | 1.2.0.0 | Christian Cristofori | |
| ✅ | Lazarus 2.0.6 Free Pascal 3.0.4 | 🗻 | x86 | 1.2.0.0 | Christian Cristofori |
| 💭 | 🗻 | x64 | |||
| ❌ | 🐧 | x86 | *1.1.0.0 | Christian Cristofori | |
| 💭 | 🐧 | x64 |
*: la versione 1.1.0.0 non è mai stata più che una banale versione alpha.
La libreria è nata per un obiettivo che al momento pare essere stato ampiamente raggiunto.
Vista la longevità delle versioni crediamo che a questo punto la libreria si possa definire stabile e completa.
Non verranno pertanto aggiunte altre funzionalità, verranno pubblicate eventuali sotto-versioni per le seguenti motivazioni:
- Correzioni e miglioramenti.
- Rendere questa unit compatibile con ogni versione di Delphi o compilatore Object Pascal.
- Compatibilità con ogni possibile versione di OpenSSL.
- Delphi Club Italia - Pagina Facebook
- Christian Cristofori
- Giancarlo Oneglio
- Diego Rigoni
- Gianni Giorgetti
- Marcello Gribaudo
Questa libreria è utilizzabile liberamente dove e come si desidera, senza alcun obbligo. Ci farebbe però piacere avere un vostro feedback e aggiungere a questa lista un collegamento al vostro progetto.
- FExpolorer (Fattura Elettronica in Windows Explorer) di Carlo Barazzetta e Andrea Magni
Progetto Open-Source Delphi di un visualizzatore di Fatture Elettroniche con integrazione nella shell di Windows.
Qualsiasi suggerimento, contributo o commento sarà veramente apprezzato.

