-
Notifications
You must be signed in to change notification settings - Fork 23
PGP Encryption with Ruby
The key that is used to encrypt data. Must be properly secured to prevent the key from being used by unauthorized parties.
Key that is shared with others and is derived from the private key.
When a key is generated, it is recommended to use a passphrase to secure access to the private key. Without a passphrase anyone with access to the PGP keystore can encrypt and decrypt files with that key.
When a file is encrypted for a specific recipient it should be signed with the senders credentials so that the recipient is certain the file came from the expected sender.
Signing encrypted files is optional, as well as verifying the signature of the sent file. It is however recommended to both sign and verify any signatures to prevent the "man in the middle" attack.
If the Private key is ever exposed:
- A new Private key must be generated.
- The old private and public keys should be discarded.
- Any parties that have been sent the previous public key should be instructed to remove it immediately from their keystore, since that public key can no longer be trusted.
- Send out the new public key to relevant parties.
GPG supports several trust levels, but only appears to allow the use of keys at the ultimate
trust level.
Keys at other levels, although present in the keystore, are not used for encryption, decryption, signing, or signature
verification purposes.
After importing either a public or private key, the key must then be explicitly trusted as ultimate
before it can be used.
:none
- No compression, encrypt only
:zip
- Default
:zlib
- :zlib is better than zip
:bzip2
- :bzip2 is smallest, but uses a lot of memory and is much slower.
PGP standard only supports :zip. OpenGPG supports the others.
PGP supports several encryption algorithms referred to as key types in PGP:
- RSA Encryption with a key length of 2048 or 4096.
Although the key is encryption is RSA, AES is used to encrypt the contents of the file.
The iostreams
gem supports streaming data to/from various targets, one of which is PGP using Gnu Privacy Guard (GPG).
GPG is called via the command line so that data can be streamed to avoid encrypting or decrypting the entire file in memory.
Mac OSX via homebrew
brew install gpg2
Redhat Linux
rpm install gpg2
Senders private and public key
IOStreams::Pgp.generate_key(
name: 'Sender',
email: 'sender@example.org',
passphrase: 'sender_passphrase'
)
Receivers private and public key
IOStreams::Pgp.generate_key(
name: 'Receiver',
email: 'receiver@example.org',
passphrase: 'receiver_passphrase'
)
Create encrypted file that only receiver@example.org
can decrypt,
and sign it with the senders public key: sender@example.org
.
data = %w(this is some data that should be encrypted using pgp)
IOStreams::Pgp::Writer.open(
'secure.pgp',
recipient: 'receiver@example.org',
signer: 'sender@example.org',
signer_passphrase: 'sender_passphrase'
) do |output|
data.each { |word| output.puts(word) }
end
Decrypt the file for receiver@example.org
using the private key,
and verify the signature using the senders public key.
IOStreams::Pgp::Reader.open('secure.pgp', passphrase: 'receiver_passphrase') do |stream|
while !stream.eof?
puts stream.read(10)
end
end
Using a default user and passphrase to sign the output file:
IOStreams::Pgp::Writer.default_signer = 'sender@example.org'
IOStreams::Pgp::Writer.default_signer_passphrase = 'sender_passphrase'
Default passphrase for decrypting file
IOStreams::Pgp::Reader.default_passphrase = 'receiver_passphrase'
Create encrypted file that only receiver@example.org
can decrypt,
and sign it with the senders public key: sender@example.org
.
data = %w(this is some data that should be encrypted using pgp)
IOStreams.writer('secure.gpg', pgp: {recipient: 'receiver@example.org'}) do |output|
data.each { |word| output.puts(word) }
end
Decrypt the file for receiver@example.org
using the private key,
and verify the signature using the senders public key.
IOStreams.reader('secure.gpg') do |stream|
while data = stream.read(10)
ap data
end
end
To generate a secure passphrase:
SecureRandom.urlsafe_base64(128)
- Designed for processing larger files since a process is spawned for each file processed.
- For small in memory files or individual emails, use the 'opengpgme' library.
Running tests on an Early 2015 Macbook Pro Dual Core with Ruby v2.3.1
Input file: test.log 3.6GB
-
:none
: size: 3.6GB write: 52s read: 45s -
:zip
: size: 411MB write: 75s read: 31s -
:zlib
: size: 241MB write: 66s read: 23s ( 756KB Memory ) -
:bzip2
: size: 129MB write: 430s read: 130s ( 5MB Memory )
- Generate keys
- Export keys
- Import keys
- Set trust level
- Delete Keys
- Check for keys
- Key fingerprint
Output PGP encrypted files.
class Cron::ExportJob < RocketJob::Job
include RocketJob::Plugins::Batch
before_complete :download_file
def download_file
download(
output_file_name,
streams: [
pgp: {
recipient: 'receiver@example.org',
compression: :zlib
}
]
)
end
def perform(record)
# Implement
end
end