crystal-gpgme

Crystal bindings for gpgme

Crystal GPGME

Crystal bindings for the GPGME (GnuPG Made Easy) library. Provides a clean, idiomatic Crystal API for GPG operations.

Features

  • 🔑 Key Management: List public and private keys with detailed metadata
  • 🔒 Encryption: Encrypt data for one or multiple recipients
  • 🔓 Decryption: Decrypt PGP-encrypted data
  • ✍️ Signing: Create digital signatures
  • Verification: Verify digital signatures
  • 🎯 Clean API: Simple, idiomatic Crystal interface
  • 🔧 Low-level Access: Direct C bindings available when needed

Installation

  1. Install the GPGME library:

    # macOS
    brew install gpgme
    
    # Ubuntu/Debian
    sudo apt-get install libgpgme-dev
    
    # Fedora
    sudo dnf install gpgme-devel
    
  2. Add this to your application's shard.yml:

    dependencies:
      gpgme:
        github: yourusername/crystal-gpgme
    
  3. Run shards install

Usage

Listing Keys

require "gpgme"

# List all public keys
GPGME.public_keys.each do |key|
  puts "#{key.name} <#{key.email}>"
  puts "  Fingerprint: #{key.fingerprint}"
  puts "  Can encrypt: #{key.can_encrypt}"
end

# List private keys
GPGME.private_keys.each do |key|
  puts key
end

# Search for specific keys
keys = GPGME.public_keys("user@example.com")

Encrypting Data

require "gpgme"

plaintext = "Secret message"
recipients = ["user@example.com"]

# Encrypt with ASCII armor (default)
encrypted = GPGME.encrypt(plaintext, recipients)
puts encrypted

# Encrypt without ASCII armor (binary output)
encrypted = GPGME.encrypt(plaintext, recipients, armor: false)

Decrypting Data

require "gpgme"

encrypted_message = "-----BEGIN PGP MESSAGE-----\n..."

# Decrypt (will use your private key automatically)
decrypted = GPGME.decrypt(encrypted_message)
puts decrypted

Signing Data

require "gpgme"

message = "Important message"

# Create a clear-text signature
signed = GPGME.sign(message)

# Create a detached signature
signed = GPGME.sign(message, mode: LibGPGME::SigMode::Detach)

Verifying Signatures

require "gpgme"

signature = "-----BEGIN PGP SIGNED MESSAGE-----\n..."

# Verify a clear-text signature
valid = GPGME.verify(signature)
puts valid ? "Valid" : "Invalid"

# Verify a detached signature
valid = GPGME.verify(detached_signature, original_message)

Using Context for Multiple Operations

For better performance when performing multiple operations, create a context:

require "gpgme"

ctx = GPGME::Context.new
ctx.armor = true

# List keys
public_keys = ctx.public_keys
private_keys = ctx.private_keys

# Encrypt
encrypted = ctx.encrypt("Secret", ["user@example.com"])

# Decrypt
decrypted = ctx.decrypt(encrypted)

API Overview

Module Methods

  • GPGME.public_keys(pattern = nil) - List public keys
  • GPGME.private_keys(pattern = nil) - List private keys
  • GPGME.encrypt(data, recipients, armor = true) - Encrypt data
  • GPGME.decrypt(ciphertext) - Decrypt data
  • GPGME.sign(data, mode = Clear, armor = true) - Sign data
  • GPGME.verify(signature, signed_text = nil) - Verify signature

GPGME::Context

The main context class for GPG operations:

  • #public_keys(pattern = nil) - List public keys
  • #private_keys(pattern = nil) - List private keys
  • #get_key(fingerprint, secret = false) - Get a specific key
  • #encrypt(data, recipients, armor = true) - Encrypt data
  • #decrypt(ciphertext) - Decrypt data
  • #sign(data, mode = Clear, armor = true) - Sign data
  • #verify(signature, signed_text = nil) - Verify signature
  • #armor=(bool) - Enable/disable ASCII armor

GPGME::Key

Represents a GPG key with properties:

  • fingerprint - Key fingerprint
  • keyid - Key ID
  • name - Primary user name
  • email - Primary email address
  • can_encrypt - Can be used for encryption
  • can_sign - Can be used for signing
  • can_certify - Can be used for certification
  • can_authenticate - Can be used for authentication
  • is_secret - Is a private key
  • is_expired - Key has expired
  • is_revoked - Key has been revoked
  • user_ids - Array of user IDs
  • subkeys - Array of subkeys

Error Handling

Operations raise GPGME::Error on failure:

begin
  encrypted = GPGME.encrypt("data", ["invalid@example.com"])
rescue GPGME::Error => e
  puts "Encryption failed: #{e.message}"
end

Requirements

  • Crystal >= 1.0.0
  • GPGME library (libgpgme11)
  • GnuPG

Development

# Clone the repository
git clone https://github.com/yourusername/crystal-gpgme
cd crystal-gpgme

# Install dependencies
shards install

# Run examples
crystal run examples/basic_usage.cr

Contributing

  1. Fork it (https://github.com/yourusername/crystal-gpgme/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

License

MIT License - see LICENSE file for details

Credits

This library provides Crystal bindings for GPGME, which is part of the GnuPG project.

Repository

crystal-gpgme

Owner
Statistic
  • 1
  • 0
  • 0
  • 1
  • 0
  • 2 months ago
  • December 27, 2025
License

MIT License

Links
Synced at

Tue, 27 Jan 2026 10:23:46 GMT

Languages