h-gpgme wraps gpgme, the library GnuPG
offers to programs that want OpenPGP without shelling out to gpg. The API
stays close to the C one, but the memory management, error handling and resource
cleanup a C API leaves to the caller become ordinary Haskell values and
bracket-style functions.
The crypto itself comes from the GnuPG installation already on the machine: the
same keyrings, the same gpg-agent, the same trust database.
- Encryption and decryption — to one or more recipients (
encrypt,decrypt), symmetrically when you name no recipient at all, and on file descriptors (encryptFd,decryptFd) for data you would rather not hold in memory. - Signing and verification — normal, detached and cleartext signatures
(
signwithSignMode), verification of attached and detached signatures (verify,verifyDetached), and the combinedencryptSign/decryptVerify. - Key lookup — by fingerprint (
getKey), across a keyring (listKeys), or by user id (searchKeys), down to the user ids, subkeys, algorithms and validity of what comes back. - Key import, export and removal —
importKeyFromFile,importKeyFromBytes;exportKey,exportSecretKeyandexportKeyswithExportMode, armored if the context hassetArmor;removeKey. - Key generation —
Crypto.Gpgme.Key.Genbuilds the parameter list gpgme expects (key type, length, usage, expiry, passphrase) out of types rather than hand-written strings. - Callbacks — answer a passphrase request from your own code instead of a
pinentry prompt (
setPassphraseCallback), and follow slow operations withsetProgressCallback.
Every operation runs in a Ctx, a gpgme context bound to a GnuPG home
directory. Use withCtx and it is freed for you.
The gpgme C library with its headers, and a GnuPG installation:
apt install libgpgme-dev # Debian, Ubuntu
brew install gpgme # macOSBoth the gpgme 1.x and 2.x series work. gpgme 2.x additionally needs
bindings-gpgme >= 0.2, since gpgme 2.0 dropped the trust item API that older
bindings referenced.
{-# LANGUAGE OverloadedStrings #-}
import Crypto.Gpgme
main :: IO ()
main = do
let alicePubFpr = "EAACEB8A"
-- encrypt for alice, out of bob's keyring
Just enc <- withCtx "test/bob" "C" OpenPGP $ \bCtx -> do
Just aPubKey <- getKey bCtx alicePubFpr NoSecret
either (const Nothing) Just <$> encrypt bCtx [aPubKey] NoFlag "hello"
-- decrypt as alice, answering the passphrase request in-process rather than
-- at a pinentry prompt (needs allow-loopback-pinentry in gpg-agent.conf)
dec <- withCtx "test/alice" "C" OpenPGP $ \aCtx -> do
setPassphraseCallback aCtx (Just (\_ _ _ -> return (Just "alice123")))
decrypt aCtx enc
print decwithCtx takes the home directory, the locale and the protocol. For one-shot
use there are shorthands that build their own context, like
encrypt' "test/bob" alicePubFpr "hello".
The test suite doubles as the fullest set of examples: it exercises every
operation above against the keyrings in test/.
The API docs live on Hackage. For what each underlying call really does, the gpgme manual is the authority — h-gpgme's names follow it closely.
Issues and pull requests are welcome. cabal test runs the suite; tests
marked NoCi are skipped in CI with --test-options='--pattern=!/NoCi/'. test/README.md describes
the test keyrings, and RELEASE.md how a release is cut.