Revision 0a2010c8
Added by Marc Dequènes over 15 years ago
- ID 0a2010c8f3bfce182daa7f7e71dfe5019c68d300
lib/cyborghood/mail.rb | ||
---|---|---|
require 'delegate'
|
||
require 'tmail'
|
||
require 'tmail_extra'
|
||
require 'gpgme' # >= 1.0.2 needed for :always_trust sign option
|
||
require 'action_mailer/quoting'
|
||
require 'action_mailer/utils'
|
||
require 'net/smtp'
|
||
... | ... | |
|
||
def sign
|
||
data = build_intermediate_mail()
|
||
signature = data.pgp_sign([@config.mail.key_id]) do |uid_hint, passphrase_info, prev_was_bad|
|
||
sign_data = data.pgp_sign([@config.mail.key_id]) do |uid_hint, passphrase_info, prev_was_bad|
|
||
@config.mail.key_passphrase
|
||
end
|
||
|
||
... | ... | |
|
||
# build properly signed mail
|
||
# (modify original mail parts)
|
||
@mail.set_content_type("multipart", "signed", {'boundary' => TMail.new_boundary, 'protocol' => "application/pgp-signature"})
|
||
@mail.set_content_type("multipart", "signed", {'boundary' => TMail.new_boundary, 'protocol' => "application/pgp-signature", 'micalg' => sign_data[:micalg]})
|
||
@mail.transfer_encoding = "7bit"
|
||
@mail['content-disposition'] = nil
|
||
@mail.body = "This mail is a RFC3156 signed message.\n"
|
||
... | ... | |
p_signature.set_content_type("application", "pgp-signature")
|
||
p_signature.transfer_encoding = "7bit"
|
||
p_signature.content_disposition = "inline"
|
||
p_signature.body = signature
|
||
p_signature.body = sign_data[:signature]
|
||
@mail.parts << p_signature
|
||
end
|
||
|
lib/tmail_extra.rb | ||
---|---|---|
# attempt to check PGP signature in a RFC3156-compliant way
|
||
require 'gpgme' # >= 1.0.2 needed for :always_trust sign option
|
||
|
||
# Attempt to handle PGP/GPG features in a RFC3156-compliant way
|
||
#
|
||
# notes: These methods have been designed to be able to sign, crypt,
|
||
# or sign+crypt with RFC 1847 Encapsulation. There is no
|
||
# support (yet?) for the combined method described in chapter
|
||
# 6.2 of RFC3156.
|
||
module TMail
|
||
class Mail
|
||
def is_pgp_signed?
|
||
... | ... | |
end
|
||
|
||
def pgp_sign(signers_id, &passphrase_callback)
|
||
signers = signers_id.collect{|key_id| gpg_key(key_id) }
|
||
GPGME.sign(self.to_rfc3156, {:signers => signers, :passphrase_callback => method(:gpg_passphrase_callback_wrapper),
|
||
:passphrase_callback_value => passphrase_callback, :armor => true})
|
||
signers = signers_id.collect{|key_id| gpg_key(key_id, true) }
|
||
# we don't use GPGME.sign(), because we need to get operation information to get the hash_algo and compute the micalg parameter
|
||
gpg = GPGME::Ctx.new({:signers => signers, :passphrase_callback => method(:gpg_passphrase_callback_wrapper),
|
||
:passphrase_callback_value => passphrase_callback, :armor => true})
|
||
gpg.add_signer(*signers)
|
||
sig_data = GPGME::Data.new
|
||
gpg.sign(GPGME::Data.new(self.to_rfc3156), sig_data, GPGME::SIG_MODE_NORMAL)
|
||
hash_algo = GPGME.gpgme_op_sign_result(gpg).signatures.first.hash_algo
|
||
micalg = "pgp-" + GPGME.gpgme_hash_algo_name(hash_algo).downcase
|
||
sig_data.seek(0, IO::SEEK_SET)
|
||
{:signature => sig_data.read, :micalg => micalg}
|
||
end
|
||
|
||
def to_rfc3156
|
||
... | ... | |
|
||
protected
|
||
|
||
def gpg_key(fingerprint)
|
||
def gpg_key(fingerprint, secret = false)
|
||
gpg = GPGME::Ctx.new
|
||
gpg.get_key(fingerprint)
|
||
gpg.get_key(fingerprint, secret)
|
||
end
|
||
|
||
def gpg_passphrase_callback_wrapper(hook, uid_hint, passphrase_info, prev_was_bad, fd)
|
||
# sending key
|
||
io = IO.for_fd(fd, 'w')
|
||
io.puts hook.call(uid_hint, passphrase_info, prev_was_bad)
|
||
io.flush
|
Also available in: Unified diff
[evol] set the 'micalg' parameter in signed mails