OpenPGP è ancora il modo in cui molte organizzazioni si scambiano i file. Una banca vuole lotti di pagamenti cifrati con la sua chiave pubblica, un partner invia report cifrati con GnuPG, una release deve essere distribuita con una firma detached. Da Delphi questo significava di solito installare GnuPG su ogni macchina e chiamare gpg.exe da riga di comando, con tutta la gestione di percorsi, keyring e codici di uscita che ne consegue.
sgcCrypto ora implementa OpenPGP in autonomia, in puro Object Pascal. Non c'è nessuna DLL da distribuire, nessuno strumento da riga di comando da chiamare e nessuna dipendenza da Indy. Chiavi, cifratura, decifratura, firme e verifica si riducono a una manciata di chiamate a funzione su TBytes, e il risultato interopera con GnuPG in entrambe le direzioni.
Versione 4 e versione 6
Sono supportate due generazioni del formato:
- La versione 4 (RFC 4880 e RFC 6637) è quella usata oggi da GnuPG, Kleopatra e dalla maggior parte dei client di posta. Sceglila quando scambi chiavi e file con strumenti esistenti.
- La versione 6 (RFC 9580) è lo standard attuale. Aggiunge la cifratura autenticata (AEAD con OCB, EAX o GCM), Argon2 per le passphrase e chiavi native Ed25519, Ed448, X25519 e X448.
Quando cifri per più destinatari, la libreria sceglie il formato che tutti possono leggere: il formato AEAD della RFC 9580 se lo supportano tutti, altrimenti il classico formato con protezione dell'integrità. Un messaggio destinato a un insieme di chiavi vecchie e nuove si apre comunque ovunque.
Generare una chiave
Una sola chiamata crea una chiave completa: una chiave primaria di firma, una sottochiave di cifratura, lo user ID e le autofirme che li legano insieme.
uses
sgcCrypto_PGP, sgcCrypto_PGP_Cert;
var
oAlice: TsgcPGPKey;
begin
// v4 Ed25519 + Curve25519, the default key type of GnuPG
oAlice := sgcPGP_GenerateKey('Alice <alice@example.com>', 'secret',
pgpkEd25519, 4);
try
Memo1.Text := oAlice.SaveToArmored(False); // public key, share it
SaveSecretKey(oAlice.SaveToArmored(True)); // protected secret key
finally
oAlice.Free;
end;
end;
I tipi di chiave sono RSA 2048, 3072 e 4096, Ed25519, Ed448 (versione 6) ed ECDSA con ECDH su NIST P-256, P-384 e P-521. Le chiavi Brainpool possono essere importate. Le chiavi segrete sono protette con la tua passphrase, usando SHA-256 iterato per la versione 4 e Argon2 con AES-OCB per la versione 6.
Cifrare e decifrare
Cifra per una o più chiavi pubbliche, con firma facoltativa del mittente. L'output è in ASCII armor per impostazione predefinita, pronto da allegare a una mail o da caricare su un server.
// encrypt to Bob, signed by Alice, compressed with ZIP
vEncrypted := sgcPGP_Encrypt(vData, [oBob], oAlice);
// or protect a file with a passphrase only
vEncrypted := sgcPGP_EncryptSymmetric(vData, 'shared passphrase');
La decifratura richiede un keyring con le tue chiavi segrete. Una chiave bloccata viene sbloccata su una copia privata con la passphrase, quindi il keyring stesso non cambia mai. Il risultato ti dice a chi era destinato il messaggio, come è stato cifrato e se la firma al suo interno è valida.
var
oRing: TsgcPGPKeyRing;
vResult: TsgcPGPDecryptResult;
begin
oRing := TsgcPGPKeyRing.Create;
try
oRing.LoadFromFile('bob-secret.asc');
vData := sgcPGP_Decrypt(vEncrypted, oRing, 'bob passphrase', oContacts,
vResult);
if vResult.Verify.Valid then
Log('Signed by ' + vResult.Verify.SignerUserID);
finally
oRing.Free;
end;
end;
Firmare e verificare
Sono supportate le firme detached per file e release, i messaggi firmati inline e le firme in chiaro (cleartext) per i testi che devono restare leggibili, con la modalità testo per firme indipendenti dalla codifica di fine riga.
// detached signature, the classic file.sig
vSignature := sgcPGP_Sign(vData, oAlice);
if sgcPGP_VerifyDetached(vData, vSignature, oContacts, vVerify) then
Log('Valid signature from ' + vVerify.SignerUserID);
// cleartext signed text, readable without any tool
vSigned := sgcPGP_ClearSign('Payment batch 2026-10 approved', oAlice);
Funziona con GnuPG
Ogni funzionalità è stata testata in entrambe le direzioni con GnuPG 2.4.5: i file e le firme creati da GnuPG si decifrano e si verificano in Delphi, e tutto ciò che la libreria produce viene accettato da gpg --decrypt e gpg --verify. Questo include i messaggi cifrati con OCB che GnuPG 2.4 scrive per impostazione predefinita per le chiavi che ha generato, e che molte librerie OpenPGP non sono in grado di leggere. Il supporto alla versione 6 è stato verificato con le chiavi e i messaggi di esempio della RFC 9580.
Le chiavi passano da un mondo all'altro come testo armored. Esporta una chiave da Delphi ed esegui gpg --import, oppure carica l'output di gpg --export --armor in un TsgcPGPKeyRing.
Pensato per input non attendibili
Un'applicazione che decifra file provenienti dall'esterno deve presumere che alcuni di essi siano ostili. La libreria rifiuta il vecchio formato di cifratura senza protezione, segnala ogni errore di decifratura con lo stesso errore in modo che non possa essere usato come oracolo, rifiuta le firme SHA-1 sui documenti e impone limiti ai fattori di lavoro delle passphrase e alla dimensione decompressa, così un messaggio costruito ad arte non può bloccare il server.
Cos'altro c'è di nuovo
- La cifratura autenticata AES-OCB (RFC 7253) e AES-EAX, disponibili anche da sole in sgcCrypto.
- La compressione DEFLATE e ZLIB in una nuova unit in puro Object Pascal,
sgcCrypto_Deflate. - Una demo VCL,
Demos\18.Cryptography\09.OpenPGP, con generazione, importazione ed esportazione di chiavi, cifratura, decifratura, firma e verifica in un'unica finestra.
Le unit OpenPGP compilano con Delphi 7 fino a Delphi 13 e con C++Builder, per Win32 e Win64. Le chiavi DSA ed ElGamal possono essere caricate ma non usate, e i vecchi cifrari CAST5, 3DES e IDEA non sono supportati.
Continua a leggere
- Crittografia post-quantistica in Delphi
- OpenSSL o crittografia nativa in Delphi: scegli a runtime
- sgcCrypto, tutto il pacchetto di crittografia
Domande su un'integrazione specifica, un formato bancario o una chiave che devi importare? Mettiti in contatto. Riceverai una risposta dalle persone che hanno scritto il codice.
