2010-11-30 11:41:14 +01:00
|
|
|
## src/common/gpg.py
|
2005-04-12 13:46:20 +02:00
|
|
|
##
|
2010-03-11 16:52:36 +01:00
|
|
|
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
|
2008-08-15 05:20:23 +02:00
|
|
|
## Copyright (C) 2005 Alex Mauer <hawke AT hawkesnest.net>
|
|
|
|
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
|
|
|
|
## Copyright (C) 2007 Stephan Erb <steve-e AT h3c.de>
|
|
|
|
## Copyright (C) 2008 Jean-Marie Traissard <jim AT lapin.org>
|
|
|
|
## Jonathan Schleifer <js-gajim AT webkeks.org>
|
2005-04-12 13:46:20 +02:00
|
|
|
##
|
2007-10-22 13:13:13 +02:00
|
|
|
## This file is part of Gajim.
|
|
|
|
##
|
|
|
|
## Gajim is free software; you can redistribute it and/or modify
|
2005-04-12 13:46:20 +02:00
|
|
|
## it under the terms of the GNU General Public License as published
|
2007-10-22 13:13:13 +02:00
|
|
|
## by the Free Software Foundation; version 3 only.
|
2005-04-12 13:46:20 +02:00
|
|
|
##
|
2007-10-22 13:13:13 +02:00
|
|
|
## Gajim is distributed in the hope that it will be useful,
|
2005-04-12 13:46:20 +02:00
|
|
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2008-08-15 05:20:23 +02:00
|
|
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2005-04-12 13:46:20 +02:00
|
|
|
## GNU General Public License for more details.
|
|
|
|
##
|
2007-10-22 13:13:13 +02:00
|
|
|
## You should have received a copy of the GNU General Public License
|
2008-08-15 05:20:23 +02:00
|
|
|
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
2007-10-22 13:13:13 +02:00
|
|
|
##
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2010-11-30 11:41:14 +01:00
|
|
|
from gajim import HAVE_GPG
|
2010-11-29 18:44:22 +01:00
|
|
|
import os
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2010-11-30 11:41:14 +01:00
|
|
|
if HAVE_GPG:
|
2010-11-29 18:44:22 +01:00
|
|
|
import gnupg
|
2010-02-08 15:08:40 +01:00
|
|
|
|
2010-11-29 18:44:22 +01:00
|
|
|
class GnuPG(gnupg.GPG):
|
|
|
|
def __init__(self, use_agent=False):
|
|
|
|
gnupg.GPG.__init__(self)
|
|
|
|
self.passphrase = None
|
2010-02-08 15:08:40 +01:00
|
|
|
self.use_agent = use_agent
|
|
|
|
self.always_trust = False
|
|
|
|
|
|
|
|
def _setup_my_options(self):
|
|
|
|
self.options.armor = 1
|
|
|
|
self.options.meta_interactive = 0
|
|
|
|
self.options.extra_args.append('--no-secmem-warning')
|
|
|
|
# disable photo viewer when verifying keys
|
|
|
|
self.options.extra_args.append('--verify-options')
|
|
|
|
self.options.extra_args.append('no-show-photo')
|
|
|
|
if self.use_agent:
|
|
|
|
self.options.extra_args.append('--use-agent')
|
|
|
|
|
|
|
|
def encrypt(self, str_, recipients, always_trust=False):
|
2010-11-29 18:44:22 +01:00
|
|
|
result = super(GnuPG, self).encrypt(str_, recipients,
|
|
|
|
always_trust=always_trust, passphrase=self.passphrase)
|
|
|
|
|
|
|
|
if result.status == 'invalid recipient':
|
2010-02-08 15:08:40 +01:00
|
|
|
return '', 'NOT_TRUSTED'
|
2010-11-29 18:44:22 +01:00
|
|
|
|
|
|
|
if result.ok:
|
2010-02-08 15:08:40 +01:00
|
|
|
error = ''
|
2010-11-29 18:44:22 +01:00
|
|
|
else:
|
|
|
|
error = result.status
|
2010-02-08 15:08:40 +01:00
|
|
|
|
2010-11-29 18:44:22 +01:00
|
|
|
return self._stripHeaderFooter(str(result)), error
|
2010-02-08 15:08:40 +01:00
|
|
|
|
2010-11-29 18:44:22 +01:00
|
|
|
def decrypt(self, str_, keyID):
|
|
|
|
data = self._addHeaderFooter(str_, 'MESSAGE')
|
|
|
|
result = super(GnuPG, self).decrypt(data,
|
|
|
|
passphrase=self.passphrase)
|
2010-02-08 15:08:40 +01:00
|
|
|
|
2010-11-29 18:44:22 +01:00
|
|
|
return str(result)
|
2010-02-08 15:08:40 +01:00
|
|
|
|
|
|
|
def sign(self, str_, keyID):
|
2010-11-29 18:44:22 +01:00
|
|
|
result = super(GnuPG, self).sign(str_, keyid=keyID, detach=True,
|
|
|
|
passphrase=self.passphrase)
|
|
|
|
|
|
|
|
if result.fingerprint:
|
|
|
|
return self._stripHeaderFooter(str(result))
|
|
|
|
# if 'KEYEXPIRED' in resp:
|
|
|
|
# return 'KEYEXPIRED'
|
2010-02-08 15:08:40 +01:00
|
|
|
return 'BAD_PASSPHRASE'
|
|
|
|
|
|
|
|
def verify(self, str_, sign):
|
|
|
|
if str_ is None:
|
|
|
|
return ''
|
2010-11-29 18:44:22 +01:00
|
|
|
data = '-----BEGIN PGP SIGNED MESSAGE-----' + os.linesep
|
|
|
|
data = data + 'Hash: SHA1' + os.linesep + os.linesep
|
|
|
|
data = data + str_ + os.linesep
|
|
|
|
data = data + self._addHeaderFooter(sign, 'SIGNATURE')
|
|
|
|
result = super(GnuPG, self).verify(data)
|
2010-02-08 15:08:40 +01:00
|
|
|
|
2010-11-29 18:44:22 +01:00
|
|
|
if result.valid:
|
|
|
|
return result.key_id
|
|
|
|
return ''
|
2010-02-08 15:08:40 +01:00
|
|
|
|
2010-11-29 18:44:22 +01:00
|
|
|
def get_keys(self, secret=False):
|
2010-02-08 15:08:40 +01:00
|
|
|
keys = {}
|
2010-11-29 18:44:22 +01:00
|
|
|
result = super(GnuPG, self).list_keys(secret=secret)
|
|
|
|
for key in result:
|
|
|
|
# Take first not empty uid
|
|
|
|
keys[key['keyid'][8:]] = [uid for uid in key['uids'] if uid][0]
|
2010-02-08 15:08:40 +01:00
|
|
|
return keys
|
|
|
|
|
|
|
|
def get_secret_keys(self):
|
|
|
|
return self.get_keys(True)
|
|
|
|
|
|
|
|
def _stripHeaderFooter(self, data):
|
|
|
|
"""
|
|
|
|
Remove header and footer from data
|
|
|
|
"""
|
|
|
|
if not data: return ''
|
2010-11-29 18:44:22 +01:00
|
|
|
lines = data.splitlines()
|
2010-02-08 15:08:40 +01:00
|
|
|
while lines[0] != '':
|
|
|
|
lines.remove(lines[0])
|
|
|
|
while lines[0] == '':
|
|
|
|
lines.remove(lines[0])
|
|
|
|
i = 0
|
|
|
|
for line in lines:
|
|
|
|
if line:
|
|
|
|
if line[0] == '-': break
|
|
|
|
i = i+1
|
|
|
|
line = '\n'.join(lines[0:i])
|
|
|
|
return line
|
|
|
|
|
|
|
|
def _addHeaderFooter(self, data, type_):
|
|
|
|
"""
|
|
|
|
Add header and footer from data
|
|
|
|
"""
|
2010-11-29 18:44:22 +01:00
|
|
|
out = "-----BEGIN PGP %s-----" % type_ + os.linesep
|
|
|
|
out = out + "Version: PGP" + os.linesep
|
|
|
|
out = out + os.linesep
|
|
|
|
out = out + data + os.linesep
|
|
|
|
out = out + "-----END PGP %s-----" % type_ + os.linesep
|
2010-02-08 15:08:40 +01:00
|
|
|
return out
|