OpenPGP is voor veel organisaties nog steeds de manier om bestanden uit te wisselen. Een bank wil betalingsbatches versleuteld met haar publieke sleutel, een partner stuurt rapporten versleuteld met GnuPG, een release moet met een losse handtekening worden uitgeleverd. Vanuit Delphi betekende dat meestal GnuPG op elke machine installeren en gpg.exe aanroepen via de opdrachtregel, met alle afhandeling van paden, sleutelringen en exitcodes die daarbij hoort.
sgcCrypto implementeert OpenPGP nu zelf, in pure Object Pascal. Er is geen DLL om uit te leveren, geen opdrachtregelprogramma om aan te roepen en geen afhankelijkheid van Indy. Sleutels, versleuteling, ontsleuteling, handtekeningen en verificatie zijn een handvol functieaanroepen op TBytes, en het resultaat werkt in beide richtingen samen met GnuPG.
Versie 4 en versie 6
Twee generaties van het formaat worden ondersteund:
- Versie 4 (RFC 4880 en RFC 6637) is wat GnuPG, Kleopatra en de meeste mailclients vandaag gebruiken. Kies deze versie wanneer je sleutels en bestanden uitwisselt met bestaande hulpmiddelen.
- Versie 6 (RFC 9580) is de huidige standaard. Het voegt geauthenticeerde versleuteling toe (AEAD met OCB, EAX of GCM), Argon2 voor wachtwoordzinnen en native Ed25519-, Ed448-, X25519- en X448-sleutels.
Wanneer je naar meerdere ontvangers versleutelt, kiest de library het formaat dat elk van hen kan lezen: het AEAD-formaat van RFC 9580 wanneer ze het allemaal ondersteunen, anders het klassieke formaat met integriteitsbescherming. Een bericht aan een mix van oude en nieuwe sleutels opent overal.
Een sleutel genereren
Eén aanroep maakt een complete sleutel: een primaire ondertekeningssleutel, een versleutelingssubsleutel, de gebruikers-ID en de zelfhandtekeningen die ze aan elkaar binden.
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;
De sleuteltypen zijn RSA 2048, 3072 en 4096, Ed25519, Ed448 (versie 6) en ECDSA met ECDH op NIST P-256, P-384 en P-521. Brainpool-sleutels kunnen worden geïmporteerd. Geheime sleutels worden beschermd met je wachtwoordzin, met geïtereerde SHA-256 voor versie 4 en Argon2 met AES-OCB voor versie 6.
Versleutelen en ontsleutelen
Versleutel naar een of meer publieke sleutels, desgewenst ondertekend door de afzender. De uitvoer is standaard ASCII armored, klaar om aan een mail te hangen of naar een server te uploaden.
// 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');
Voor ontsleuteling is een sleutelring met je geheime sleutels nodig. Een vergrendelde sleutel wordt met de wachtwoordzin ontgrendeld op een privékopie, zodat de sleutelring zelf nooit verandert. Het resultaat vertelt voor wie het bericht bedoeld was, hoe het is versleuteld en of de handtekening erin geldig is.
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;
Ondertekenen en verifiëren
Losse handtekeningen voor bestanden en releases, inline ondertekende berichten en cleartext-handtekeningen voor tekst die leesbaar moet blijven worden allemaal ondersteund, met tekstmodus voor handtekeningen die onafhankelijk zijn van regeleinden.
// 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);
Werkt met GnuPG
Elke functie is in beide richtingen getest met GnuPG 2.4.5: bestanden en handtekeningen die door GnuPG zijn gemaakt, worden in Delphi ontsleuteld en geverifieerd, en alles wat de library produceert wordt geaccepteerd door gpg --decrypt en gpg --verify. Dat geldt ook voor de met OCB versleutelde berichten die GnuPG 2.4 standaard schrijft voor sleutels die het zelf heeft gegenereerd, en die veel OpenPGP-libraries niet kunnen lezen. De ondersteuning voor versie 6 is gecontroleerd aan de hand van de voorbeeldsleutels en berichten uit RFC 9580.
Sleutels gaan als armored tekst heen en weer tussen beide werelden. Exporteer een sleutel uit Delphi en voer gpg --import uit, of laad de uitvoer van gpg --export --armor in een TsgcPGPKeyRing.
Gebouwd voor onbetrouwbare invoer
Een toepassing die bestanden van buiten ontsleutelt, moet ervan uitgaan dat sommige daarvan kwaadaardig zijn. De library weigert het oude onbeschermde versleutelingsformaat, meldt elke ontsleutelingsfout met dezelfde fout zodat die niet als orakel kan dienen, verwerpt SHA-1-handtekeningen op documenten en heeft limieten voor de werkfactoren van wachtwoordzinnen en de gedecomprimeerde grootte, zodat een geprepareerd bericht de server niet kan vastzetten.
Wat is er nog meer nieuw
- AES-OCB (RFC 7253) en AES-EAX geauthenticeerde versleuteling, ook los beschikbaar in sgcCrypto.
- DEFLATE en ZLIB-compressie in een nieuwe pure Object Pascal-unit,
sgcCrypto_Deflate. - Een VCL-demo,
Demos\18.Cryptography\09.OpenPGP, met sleutels genereren, importeren en exporteren, versleutelen, ontsleutelen, ondertekenen en verifiëren in één venster.
De OpenPGP-units compileren met Delphi 7 tot en met Delphi 13 en C++Builder, voor Win32 en Win64. DSA- en ElGamal-sleutels kunnen worden geladen maar niet gebruikt, en de oude cijfers CAST5, 3DES en IDEA worden niet ondersteund.
Lees verder
- Post-kwantumcryptografie in Delphi
- OpenSSL of native cryptografie in Delphi: kies tijdens runtime
- sgcCrypto, alles in het cryptografiepakket
Vragen over een specifieke integratie, een bankformaat of een sleutel die je moet importeren? Neem contact op. Je krijgt antwoord van de mensen die de code hebben geschreven.
