OpenPGP en Delphi : chiffrer, signer et vérifier sans GnuPG

· Composants
OpenPGP en Delphi : chiffrer, signer et vérifier sans GnuPG

OpenPGP reste la façon dont de nombreuses organisations échangent des fichiers. Une banque veut des lots de paiement chiffrés avec sa clé publique, un partenaire envoie des rapports chiffrés avec GnuPG, une version doit être livrée avec une signature détachée. Depuis Delphi, cela signifiait généralement installer GnuPG sur chaque machine et appeler gpg.exe en ligne de commande, avec toute la gestion des chemins, des trousseaux et des codes de sortie que cela implique.

sgcCrypto implémente désormais OpenPGP lui-même, en Object Pascal pur. Il n'y a aucune DLL à déployer, aucun outil en ligne de commande à appeler et aucune dépendance envers Indy. Les clés, le chiffrement, le déchiffrement, les signatures et la vérification se résument à quelques appels de fonction sur des TBytes, et le résultat est interopérable avec GnuPG dans les deux sens.

Version 4 et version 6

Deux générations du format sont prises en charge :

Quand vous chiffrez pour plusieurs destinataires, la bibliothèque choisit le format que chacun d'eux peut lire : le format AEAD de la RFC 9580 quand tous le prennent en charge, le format classique protégé en intégrité dans le cas contraire. Un message destiné à un mélange de clés anciennes et nouvelles s'ouvre partout.

Générer une clé

Un seul appel crée une clé complète : une clé de signature principale, une sous-clé de chiffrement, l'identifiant utilisateur et les auto-signatures qui les relient.

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;

Les types de clé sont RSA 2048, 3072 et 4096, Ed25519, Ed448 (version 6), et ECDSA avec ECDH sur NIST P-256, P-384 et P-521. Les clés Brainpool peuvent être importées. Les clés secrètes sont protégées par votre phrase secrète, avec un SHA-256 itéré pour la version 4 et Argon2 avec AES-OCB pour la version 6.

Chiffrer et déchiffrer

Chiffrez pour une ou plusieurs clés publiques, avec en option une signature de l'expéditeur. La sortie est par défaut en armure ASCII, prête à être jointe à un courriel ou envoyée sur un serveur.

// 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');

Le déchiffrement prend un trousseau contenant vos clés secrètes. Une clé verrouillée est déverrouillée sur une copie privée avec la phrase secrète, de sorte que le trousseau lui-même ne change jamais. Le résultat vous indique à qui le message était destiné, comment il a été chiffré et si la signature qu'il contient est valide.

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;

Signer et vérifier

Les signatures détachées pour les fichiers et les versions, les messages signés en ligne et les signatures en clair pour les textes qui doivent rester lisibles sont tous pris en charge, avec un mode texte pour des signatures indépendantes des fins de ligne.

// 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);

Compatible avec GnuPG

Chaque fonctionnalité a été testée dans les deux sens avec GnuPG 2.4.5 : les fichiers et signatures créés par GnuPG se déchiffrent et se vérifient dans Delphi, et tout ce que produit la bibliothèque est accepté par gpg --decrypt et gpg --verify. Cela inclut les messages chiffrés en OCB que GnuPG 2.4 écrit par défaut pour les clés qu'il a générées, et que de nombreuses bibliothèques OpenPGP ne savent pas lire. La prise en charge de la version 6 a été vérifiée avec les clés et messages d'exemple de la RFC 9580.

Les clés circulent entre les deux mondes sous forme de texte armuré. Exportez une clé depuis Delphi et exécutez gpg --import, ou chargez la sortie de gpg --export --armor dans un TsgcPGPKeyRing.

Conçu pour les entrées non fiables

Une application qui déchiffre des fichiers venus de l'extérieur doit partir du principe que certains sont hostiles. La bibliothèque refuse l'ancien format de chiffrement non protégé, signale chaque échec de déchiffrement avec la même erreur pour qu'elle ne puisse pas servir d'oracle, rejette les signatures SHA-1 sur les documents, et impose des limites sur les facteurs de travail des phrases secrètes et sur la taille décompressée, afin qu'un message forgé ne puisse pas immobiliser le serveur.

Quoi d'autre de neuf

Les unités OpenPGP se compilent avec Delphi 7 à Delphi 13 et C++Builder, pour Win32 et Win64. Les clés DSA et ElGamal peuvent être chargées mais pas utilisées, et les anciens chiffrements CAST5, 3DES et IDEA ne sont pas pris en charge.

À lire ensuite

Des questions sur une intégration précise, un format bancaire ou une clé que vous devez importer ? Contactez-nous. Vous recevrez une réponse de la part des personnes qui ont écrit le code.