Conflicts: docs/releases/index.rst mayan/__init__.py mayan/apps/acls/south_migrations/0001_initial.py mayan/apps/acls/south_migrations/0002_auto__del_field_creatorsingleton_lock_id.py mayan/apps/checkouts/south_migrations/0001_initial.py mayan/apps/checkouts/south_migrations/0002_auto__add_field_documentcheckout_user_content_type__add_field_document.py mayan/apps/checkouts/south_migrations/0003_auto__chg_field_documentcheckout_checkout_datetime.py mayan/apps/checkouts/urls.py mayan/apps/common/forms.py mayan/apps/common/locale/ar/LC_MESSAGES/django.po mayan/apps/common/locale/bg/LC_MESSAGES/django.po mayan/apps/common/locale/bs_BA/LC_MESSAGES/django.po mayan/apps/common/locale/da/LC_MESSAGES/django.po mayan/apps/common/locale/de_CH/LC_MESSAGES/django.po mayan/apps/common/locale/de_DE/LC_MESSAGES/django.po mayan/apps/common/locale/en/LC_MESSAGES/django.po mayan/apps/common/locale/es/LC_MESSAGES/django.po mayan/apps/common/locale/fa/LC_MESSAGES/django.po mayan/apps/common/locale/fr/LC_MESSAGES/django.po mayan/apps/common/locale/hr_HR/LC_MESSAGES/django.po mayan/apps/common/locale/hu/LC_MESSAGES/django.po mayan/apps/common/locale/id/LC_MESSAGES/django.po mayan/apps/common/locale/it/LC_MESSAGES/django.po mayan/apps/common/locale/lv/LC_MESSAGES/django.po mayan/apps/common/locale/nb/LC_MESSAGES/django.po mayan/apps/common/locale/nl_NL/LC_MESSAGES/django.po mayan/apps/common/locale/pl/LC_MESSAGES/django.po mayan/apps/common/locale/pt/LC_MESSAGES/django.po mayan/apps/common/locale/pt_BR/LC_MESSAGES/django.po mayan/apps/common/locale/ro_RO/LC_MESSAGES/django.po mayan/apps/common/locale/ru/LC_MESSAGES/django.po mayan/apps/common/locale/sl_SI/LC_MESSAGES/django.po mayan/apps/common/locale/sq/LC_MESSAGES/django.po mayan/apps/common/locale/tr_TR/LC_MESSAGES/django.po mayan/apps/common/locale/vi_VN/LC_MESSAGES/django.po mayan/apps/common/locale/zh_CN/LC_MESSAGES/django.po mayan/apps/common/locale/zh_TW/LC_MESSAGES/django.po mayan/apps/common/south_migrations/0001_initial.py mayan/apps/common/south_migrations/0002_auto__add_autoadminsingleton.py mayan/apps/common/south_migrations/0003_auto__del_field_autoadminsingleton_original_auto_admin_password__del_f.py mayan/apps/common/south_migrations/0004_auto__del_field_autoadminsingleton_auto_admin_password__del_field_auto.py mayan/apps/common/south_migrations/0005_auto__del_field_autoadminsingleton_lock_id__del_field_anonymoususersin.py mayan/apps/common/south_migrations/0006_auto__add_shareduploadedfile.py mayan/apps/common/south_migrations/0007_auto__add_field_shareduploadedfile_filename.py mayan/apps/common/south_migrations/0008_auto__add_field_shareduploadedfile_datatime.py mayan/apps/common/south_migrations/0009_auto__add_userlocaleprofile.py mayan/apps/common/south_migrations/0010_create_locale_profiles.py mayan/apps/common/urls.py mayan/apps/common/views.py mayan/apps/converter/models.py mayan/apps/document_comments/models.py mayan/apps/document_indexing/south_migrations/0004_auto__add_documentrenamecount.py mayan/apps/document_indexing/south_migrations/0005_auto__add_unique_index_name__add_unique_index_title.py mayan/apps/document_indexing/south_migrations/0007_auto__del_documentrenamecount.py mayan/apps/document_signatures/south_migrations/0001_initial.py mayan/apps/document_signatures/south_migrations/0002_move_signatures_to_new_app.py mayan/apps/document_signatures/south_migrations/0003_auto__add_field_documentversionsignature_has_embedded_signature.py mayan/apps/document_signatures/south_migrations/0004_embedded_signature_state_copy.py mayan/apps/document_signatures/south_migrations/0005_auto__del_field_documentversionsignature_signature_state.py mayan/apps/document_states/__init__.py mayan/apps/document_states/south_migrations/0001_initial.py mayan/apps/document_states/south_migrations/0002_auto__add_field_workflowtransition_workflow.py mayan/apps/document_states/south_migrations/0003_auto__add_unique_workflowtransition_workflow_origin_state_destination_.py mayan/apps/document_states/south_migrations/0004_auto__del_field_workflowinstancelogentry_document__del_field_workflowi.py mayan/apps/document_states/south_migrations/0005_auto__del_unique_workflowstate_label__add_unique_workflowstate_workflo.py mayan/apps/document_states/south_migrations/0006_auto__del_unique_workflowtransition_label__del_unique_workflowtransiti.py mayan/apps/document_states/south_migrations/0008_auto__add_field_workflowinstancelogentry_user__add_field_workflowinsta.py mayan/apps/document_states/south_migrations/0009_auto__add_index_workflowinstancelogentry_datetime.py mayan/apps/document_states/urls.py mayan/apps/documents/__init__.py mayan/apps/documents/links.py mayan/apps/documents/south_migrations/0001_initial.py mayan/apps/documents/south_migrations/0002_filename_extension_merge.py mayan/apps/documents/south_migrations/0003_auto__del_field_document_file_extension.py mayan/apps/documents/south_migrations/0004_auto__add_documentversion__add_unique_documentversion_document_mayor_m.py mayan/apps/documents/south_migrations/0005_document_versions.py mayan/apps/documents/south_migrations/0006_fix_invalid_document_version_id_keys.py mayan/apps/documents/south_migrations/0007_remove_old_file_fields.py mayan/apps/documents/south_migrations/0008_fix_mayor_field_name.py mayan/apps/documents/south_migrations/0009_add_comment_field.py mayan/apps/documents/south_migrations/0010_auto__chg_field_document_date_added.py mayan/apps/documents/south_migrations/0011_auto__add_field_documentversion_signature_state.py mayan/apps/documents/south_migrations/0012_auto__add_field_documentversion_signature_file.py mayan/apps/documents/south_migrations/0013_auto__del_field_documentversion_signature_file__del_field_documentvers.py mayan/apps/documents/south_migrations/0014_change_document_mimetype_encoding_null.py mayan/apps/documents/south_migrations/0015_auto__add_unique_documenttype_name.py mayan/apps/documents/south_migrations/0017_auto__chg_field_documentversion_mimetype.py mayan/apps/documents/south_migrations/0018_auto__chg_field_documentpage_page_label.py mayan/apps/documents/south_migrations/0019_auto__add_index_documentversion_timestamp.py mayan/apps/documents/south_migrations/0020_auto__chg_field_recentdocument_datetime_accessed__chg_field_documentve.py mayan/apps/documents/south_migrations/0021_auto__del_field_documentversion_serial__del_field_documentversion_rele.py mayan/apps/documents/south_migrations/0022_set_doc_type.py mayan/apps/documents/south_migrations/0023_auto__chg_field_document_document_type.py mayan/apps/documents/south_migrations/0024_auto__add_field_documenttype_ocr.py mayan/apps/documents/south_migrations/0025_auto__add_field_document_language.py mayan/apps/documents/south_migrations/0026_auto__add_field_document_label.py mayan/apps/documents/south_migrations/0027_move_filename_to_label.py mayan/apps/documents/south_migrations/0028_auto__del_field_documentversion_filename.py mayan/apps/documents/south_migrations/0029_auto__del_field_documentversion_major__del_field_documentversion_micro.py mayan/apps/documents/south_migrations/0030_auto__add_unique_documenttypefilename_document_type_filename.py mayan/apps/documents/south_migrations/0031_remove_orphan_documents.py mayan/apps/dynamic_search/south_migrations/0001_initial.py mayan/apps/dynamic_search/south_migrations/0002_auto__chg_field_recentsearch_datetime_created__add_index_recentsearch_.py mayan/apps/dynamic_search/templatetags/search_tags.py mayan/apps/events/south_migrations/0001_initial.py mayan/apps/events/south_migrations/0002_migrate_history_data.py mayan/apps/folders/models.py mayan/apps/folders/south_migrations/0001_initial.py mayan/apps/folders/south_migrations/0002_increase_title_size.py mayan/apps/folders/south_migrations/0004_m2m_fields.py mayan/apps/folders/south_migrations/0005_auto__del_folderdocument.py mayan/apps/folders/south_migrations/0006_auto__chg_field_folder_datetime_created.py mayan/apps/history/models.py mayan/apps/history/south_migrations/0001_initial.py mayan/apps/history/south_migrations/0002_auto__chg_field_history_datetime.py mayan/apps/history/south_migrations/0003_auto__del_history__del_historytype__del_unique_historytype_namespace_n.py mayan/apps/installation/__init__.py mayan/apps/installation/models.py mayan/apps/installation/south_migrations/0001_initial.py mayan/apps/installation/south_migrations/0002_auto__del_field_installation_lock_id.py mayan/apps/installation/south_migrations/0003_auto__del_field_installation_is_first_run.py mayan/apps/linking/south_migrations/0001_initial.py mayan/apps/linking/south_migrations/0003_auto__chg_field_smartlinkcondition_foreign_document_data.py mayan/apps/linking/urls.py mayan/apps/lock_manager/south_migrations/0001_initial.py mayan/apps/lock_manager/south_migrations/0002_auto__chg_field_lock_creation_datetime.py mayan/apps/mailer/models.py mayan/apps/main/locale/ar/LC_MESSAGES/django.po mayan/apps/main/locale/bg/LC_MESSAGES/django.po mayan/apps/main/locale/bs_BA/LC_MESSAGES/django.po mayan/apps/main/locale/da/LC_MESSAGES/django.po mayan/apps/main/locale/de_CH/LC_MESSAGES/django.po mayan/apps/main/locale/de_DE/LC_MESSAGES/django.po mayan/apps/main/locale/en/LC_MESSAGES/django.po mayan/apps/main/locale/es/LC_MESSAGES/django.po mayan/apps/main/locale/fa/LC_MESSAGES/django.po mayan/apps/main/locale/fr/LC_MESSAGES/django.po mayan/apps/main/locale/hr_HR/LC_MESSAGES/django.po mayan/apps/main/locale/hu/LC_MESSAGES/django.po mayan/apps/main/locale/id/LC_MESSAGES/django.po mayan/apps/main/locale/it/LC_MESSAGES/django.po mayan/apps/main/locale/lv/LC_MESSAGES/django.po mayan/apps/main/locale/nb/LC_MESSAGES/django.po mayan/apps/main/locale/nl_NL/LC_MESSAGES/django.po mayan/apps/main/locale/pl/LC_MESSAGES/django.po mayan/apps/main/locale/pt/LC_MESSAGES/django.po mayan/apps/main/locale/pt_BR/LC_MESSAGES/django.po mayan/apps/main/locale/ro_RO/LC_MESSAGES/django.po mayan/apps/main/locale/ru/LC_MESSAGES/django.po mayan/apps/main/locale/sl_SI/LC_MESSAGES/django.po mayan/apps/main/locale/sq/LC_MESSAGES/django.po mayan/apps/main/locale/tr_TR/LC_MESSAGES/django.po mayan/apps/main/locale/vi_VN/LC_MESSAGES/django.po mayan/apps/main/locale/zh_CN/LC_MESSAGES/django.po mayan/apps/main/locale/zh_TW/LC_MESSAGES/django.po mayan/apps/main/models.py mayan/apps/main/templates/main/about.html mayan/apps/main/templates/main/generic_list_horizontal_subtemplate.html mayan/apps/main/urls.py mayan/apps/metadata/south_migrations/0002_auto__add_unique_metadataset_title.py mayan/apps/metadata/south_migrations/0003_auto__chg_field_metadatatype_lookup.py mayan/apps/metadata/south_migrations/0005_auto__chg_field_documentmetadata_value.py mayan/apps/metadata/south_migrations/0007_auto__del_documenttypedefaults__del_documenttypemetadatatypeoptions__a.py mayan/apps/metadata/south_migrations/0008_auto__add_unique_documenttypemetadatatype_document_type_metadata_type.py mayan/apps/metadata/south_migrations/0009_auto__chg_field_metadatatype_title.py mayan/apps/metadata/south_migrations/0010_auto__add_unique_documentmetadata_document_metadata_type.py mayan/apps/metadata/south_migrations/0011_auto__add_field_metadatatype_validation.py mayan/apps/mimetype/models.py mayan/apps/navigation/classes.py mayan/apps/navigation/forms.py mayan/apps/navigation/models.py mayan/apps/ocr/api.py mayan/apps/ocr/south_migrations/0001_initial.py mayan/apps/ocr/south_migrations/0002_auto__del_field_documentqueue_state__del_field_queuedocument_delay__de.py mayan/apps/ocr/south_migrations/0003_auto__chg_field_queuedocument_node_name__chg_field_queuedocument_datet.py mayan/apps/ocr/south_migrations/0004_auto__del_documentqueue__del_queuedocument__add_documentversionocrerro.py mayan/apps/permissions/south_migrations/0001_initial.py mayan/apps/permissions/south_migrations/0002_auto__add_storedpermission__add_unique_storedpermission_namespace_name.py mayan/apps/permissions/south_migrations/0003_clear_permission_holders.py mayan/apps/permissions/south_migrations/0004_auto__del_permission__del_unique_permission_namespace_name.py mayan/apps/permissions/widgets.py mayan/apps/project_setup/__init__.py mayan/apps/project_setup/locale/ar/LC_MESSAGES/django.po mayan/apps/project_setup/locale/bg/LC_MESSAGES/django.po mayan/apps/project_setup/locale/bs_BA/LC_MESSAGES/django.po mayan/apps/project_setup/locale/da/LC_MESSAGES/django.po mayan/apps/project_setup/locale/de_CH/LC_MESSAGES/django.po mayan/apps/project_setup/locale/de_DE/LC_MESSAGES/django.po mayan/apps/project_setup/locale/en/LC_MESSAGES/django.po mayan/apps/project_setup/locale/es/LC_MESSAGES/django.po mayan/apps/project_setup/locale/fa/LC_MESSAGES/django.po mayan/apps/project_setup/locale/fr/LC_MESSAGES/django.po mayan/apps/project_setup/locale/hr_HR/LC_MESSAGES/django.po mayan/apps/project_setup/locale/hu/LC_MESSAGES/django.po mayan/apps/project_setup/locale/id/LC_MESSAGES/django.po mayan/apps/project_setup/locale/it/LC_MESSAGES/django.po mayan/apps/project_setup/locale/lv/LC_MESSAGES/django.po mayan/apps/project_setup/locale/nb/LC_MESSAGES/django.po mayan/apps/project_setup/locale/nl_NL/LC_MESSAGES/django.po mayan/apps/project_setup/locale/pl/LC_MESSAGES/django.po mayan/apps/project_setup/locale/pt/LC_MESSAGES/django.po mayan/apps/project_setup/locale/pt_BR/LC_MESSAGES/django.po mayan/apps/project_setup/locale/ro_RO/LC_MESSAGES/django.po mayan/apps/project_setup/locale/ru/LC_MESSAGES/django.po mayan/apps/project_setup/locale/sl_SI/LC_MESSAGES/django.po mayan/apps/project_setup/locale/sq/LC_MESSAGES/django.po mayan/apps/project_setup/locale/tr_TR/LC_MESSAGES/django.po mayan/apps/project_setup/locale/vi_VN/LC_MESSAGES/django.po mayan/apps/project_setup/locale/zh_CN/LC_MESSAGES/django.po mayan/apps/project_setup/locale/zh_TW/LC_MESSAGES/django.po mayan/apps/project_setup/models.py mayan/apps/project_setup/urls.py mayan/apps/project_tools/__init__.py mayan/apps/project_tools/locale/ar/LC_MESSAGES/django.po mayan/apps/project_tools/locale/bg/LC_MESSAGES/django.po mayan/apps/project_tools/locale/bs_BA/LC_MESSAGES/django.po mayan/apps/project_tools/locale/da/LC_MESSAGES/django.po mayan/apps/project_tools/locale/de_CH/LC_MESSAGES/django.po mayan/apps/project_tools/locale/de_DE/LC_MESSAGES/django.po mayan/apps/project_tools/locale/en/LC_MESSAGES/django.po mayan/apps/project_tools/locale/es/LC_MESSAGES/django.po mayan/apps/project_tools/locale/fa/LC_MESSAGES/django.po mayan/apps/project_tools/locale/fr/LC_MESSAGES/django.po mayan/apps/project_tools/locale/hr_HR/LC_MESSAGES/django.po mayan/apps/project_tools/locale/hu/LC_MESSAGES/django.po mayan/apps/project_tools/locale/id/LC_MESSAGES/django.po mayan/apps/project_tools/locale/it/LC_MESSAGES/django.po mayan/apps/project_tools/locale/lv/LC_MESSAGES/django.po mayan/apps/project_tools/locale/nb/LC_MESSAGES/django.po mayan/apps/project_tools/locale/nl_NL/LC_MESSAGES/django.po mayan/apps/project_tools/locale/pl/LC_MESSAGES/django.po mayan/apps/project_tools/locale/pt/LC_MESSAGES/django.po mayan/apps/project_tools/locale/pt_BR/LC_MESSAGES/django.po mayan/apps/project_tools/locale/ro_RO/LC_MESSAGES/django.po mayan/apps/project_tools/locale/ru/LC_MESSAGES/django.po mayan/apps/project_tools/locale/sl_SI/LC_MESSAGES/django.po mayan/apps/project_tools/locale/sq/LC_MESSAGES/django.po mayan/apps/project_tools/locale/tr_TR/LC_MESSAGES/django.po mayan/apps/project_tools/locale/vi_VN/LC_MESSAGES/django.po mayan/apps/project_tools/locale/zh_CN/LC_MESSAGES/django.po mayan/apps/project_tools/locale/zh_TW/LC_MESSAGES/django.po mayan/apps/project_tools/models.py mayan/apps/project_tools/urls.py mayan/apps/rest_api/models.py mayan/apps/smart_settings/models.py mayan/apps/sources/south_migrations/0001_initial.py mayan/apps/sources/south_migrations/0002_preview_width_required.py mayan/apps/sources/south_migrations/0003_auto__del_field_stagingfolder_icon__del_field_webform_icon.py mayan/apps/sources/south_migrations/0004_auto__del_stagingfolder__del_webform__del_watchfolder__del_outofproces.py mayan/apps/sources/south_migrations/0005_auto__add_imapemail__add_intervalbasemodel__add_pop3email__add_emailba.py mayan/apps/sources/south_migrations/0006_auto__del_field_source_whitelist__del_field_source_blacklist.py mayan/apps/sources/south_migrations/0007_set_doc_type.py mayan/apps/sources/south_migrations/0008_auto__chg_field_intervalbasemodel_document_type.py mayan/apps/sources/south_migrations/0009_auto__del_watchfoldersource__chg_field_intervalbasemodel_document_type.py mayan/apps/sources/south_migrations/0010_auto__add_watchfoldersource.py mayan/apps/sources/south_migrations/0011_auto__del_field_intervalbasemodel_document_type.py mayan/apps/sources/south_migrations/0012_auto__add_field_intervalbasemodel_document_type.py mayan/apps/sources/south_migrations/0013_auto__del_field_watchfoldersource_delete_after_upload.py mayan/apps/storage/models.py mayan/apps/tags/south_migrations/0001_initial.py mayan/apps/tags/south_migrations/0003_remove_taggit.py mayan/apps/tags/south_migrations/0005_auto__add_unique_tag_label.py mayan/apps/tags/south_migrations/0006_auto__del_tagproperties.py mayan/apps/user_management/models.py mayan/settings/base.py mayan/urls.py requirements/common.txt
290 lines
8.7 KiB
Python
290 lines
8.7 KiB
Python
from __future__ import unicode_literals
|
|
|
|
import logging
|
|
import os
|
|
import tempfile
|
|
|
|
try:
|
|
from cStringIO import StringIO
|
|
except ImportError:
|
|
from StringIO import StringIO
|
|
|
|
from hkp import KeyServer
|
|
import gnupg
|
|
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from .exceptions import * # NOQA
|
|
from .literals import KEY_TYPES
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Key(object):
|
|
@staticmethod
|
|
def get_key_id(fingerprint):
|
|
return fingerprint[-16:]
|
|
|
|
@classmethod
|
|
def get_all(cls, gpg, secret=False, exclude=None):
|
|
result = []
|
|
keys = gpg.gpg.list_keys(secret=secret)
|
|
if exclude:
|
|
excluded_id = exclude.key_id
|
|
else:
|
|
excluded_id = ''
|
|
for key in keys:
|
|
if not key['keyid'] in excluded_id:
|
|
key_instance = Key(
|
|
fingerprint=key['fingerprint'],
|
|
uids=key['uids'],
|
|
type=key['type'],
|
|
data=gpg.gpg.export_keys([key['keyid']], secret=secret)
|
|
)
|
|
result.append(key_instance)
|
|
|
|
return result
|
|
|
|
@classmethod
|
|
def get(cls, gpg, key_id, secret=False, search_keyservers=False):
|
|
if len(key_id) > 16:
|
|
# key_id is a fingerprint
|
|
key_id = Key.get_key_id(key_id)
|
|
|
|
keys = gpg.gpg.list_keys(secret=secret)
|
|
key = next((key for key in keys if key['keyid'] == key_id), None)
|
|
if not key:
|
|
if search_keyservers and secret is False:
|
|
try:
|
|
gpg.receive_key(key_id)
|
|
return Key(gpg, key_id)
|
|
except KeyFetchingError:
|
|
raise KeyDoesNotExist
|
|
else:
|
|
raise KeyDoesNotExist
|
|
|
|
key_instance = Key(
|
|
fingerprint=key['fingerprint'],
|
|
uids=key['uids'],
|
|
type=key['type'],
|
|
data=gpg.gpg.export_keys([key['keyid']], secret=secret)
|
|
)
|
|
|
|
return key_instance
|
|
|
|
def __init__(self, fingerprint, uids, type, data):
|
|
self.fingerprint = fingerprint
|
|
self.uids = uids
|
|
self.type = type
|
|
self.data = data
|
|
|
|
@property
|
|
def key_id(self):
|
|
return Key.get_key_id(self.fingerprint)
|
|
|
|
@property
|
|
def user_ids(self):
|
|
return ', '.join(self.uids)
|
|
|
|
def __str__(self):
|
|
return '%s "%s" (%s)' % (self.key_id, self.user_ids, KEY_TYPES.get(self.type, _('Unknown')))
|
|
|
|
def __unicode__(self):
|
|
return unicode(self.__str__())
|
|
|
|
def __repr__(self):
|
|
return self.__unicode__()
|
|
|
|
|
|
class GPG(object):
|
|
@staticmethod
|
|
def get_descriptor(file_input):
|
|
try:
|
|
# Is it a file like object?
|
|
file_input.seek(0)
|
|
except AttributeError:
|
|
# If not, try open it.
|
|
return open(file_input, 'rb')
|
|
else:
|
|
return file_input
|
|
|
|
def __init__(self, binary_path=None, home=None, keyring=None, keyservers=None):
|
|
kwargs = {}
|
|
if binary_path:
|
|
kwargs['gpgbinary'] = binary_path
|
|
|
|
if home:
|
|
kwargs['gnupghome'] = home
|
|
|
|
if keyring:
|
|
kwargs['keyring'] = keyring
|
|
|
|
self.keyservers = keyservers
|
|
|
|
try:
|
|
self.gpg = gnupg.GPG(**kwargs)
|
|
except OSError as exception:
|
|
raise GPGException('ERROR: GPG initialization error; Make sure the GPG binary is properly installed; %s' % exception)
|
|
except Exception as exception:
|
|
raise GPGException('ERROR: GPG initialization error; %s' % exception)
|
|
|
|
def verify_file(self, file_input, detached_signature=None, fetch_key=False):
|
|
"""
|
|
Verify the signature of a file.
|
|
"""
|
|
|
|
input_descriptor = GPG.get_descriptor(file_input)
|
|
|
|
if detached_signature:
|
|
# Save the original data and invert the argument order
|
|
# Signature first, file second
|
|
file_descriptor, filename = tempfile.mkstemp(prefix='django_gpg')
|
|
os.write(file_descriptor, input_descriptor.read())
|
|
os.close(file_descriptor)
|
|
|
|
detached_signature = GPG.get_descriptor(detached_signature)
|
|
signature_file = StringIO()
|
|
signature_file.write(detached_signature.read())
|
|
signature_file.seek(0)
|
|
verify = self.gpg.verify_file(signature_file, data_filename=filename)
|
|
signature_file.close()
|
|
else:
|
|
verify = self.gpg.verify_file(input_descriptor)
|
|
|
|
logger.debug('verify.status: %s', getattr(verify, 'status', None))
|
|
if verify:
|
|
logger.debug('verify ok')
|
|
return verify
|
|
elif getattr(verify, 'status', None) == 'no public key':
|
|
# Exception to the rule, to be able to query the keyservers
|
|
if fetch_key:
|
|
try:
|
|
self.receive_key(verify.key_id)
|
|
return self.verify_file(input_descriptor, detached_signature, fetch_key=False)
|
|
except KeyFetchingError:
|
|
return verify
|
|
else:
|
|
return verify
|
|
else:
|
|
logger.debug('No verify')
|
|
raise GPGVerificationError()
|
|
|
|
def verify(self, data):
|
|
# TODO: try to merge with verify_file
|
|
verify = self.gpg.verify(data)
|
|
|
|
if verify:
|
|
return verify
|
|
else:
|
|
raise GPGVerificationError(verify.status)
|
|
|
|
def sign_file(self, file_input, key=None, destination=None, key_id=None, passphrase=None, clearsign=False):
|
|
"""
|
|
Signs a filename, storing the signature and the original file
|
|
in the destination filename provided (the destination file is
|
|
overrided if it already exists), if no destination file name is
|
|
provided the signature is returned.
|
|
"""
|
|
|
|
kwargs = {}
|
|
kwargs['clearsign'] = clearsign
|
|
|
|
if key_id:
|
|
kwargs['keyid'] = key_id
|
|
|
|
if key:
|
|
kwargs['keyid'] = key.key_id
|
|
|
|
if passphrase:
|
|
kwargs['passphrase'] = passphrase
|
|
|
|
input_descriptor = GPG.get_descriptor(file_input)
|
|
|
|
if destination:
|
|
output_descriptor = open(destination, 'wb')
|
|
|
|
signed_data = self.gpg.sign_file(input_descriptor, **kwargs)
|
|
if not signed_data.fingerprint:
|
|
raise GPGSigningError('Unable to sign file')
|
|
|
|
if destination:
|
|
output_descriptor.write(signed_data.data)
|
|
|
|
input_descriptor.close()
|
|
|
|
if destination:
|
|
output_descriptor.close()
|
|
|
|
if not destination:
|
|
return signed_data
|
|
|
|
def has_embedded_signature(self, *args, **kwargs):
|
|
try:
|
|
self.decrypt_file(*args, **kwargs)
|
|
except GPGDecryptionError:
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
def decrypt_file(self, file_input, close_descriptor=True):
|
|
input_descriptor = GPG.get_descriptor(file_input)
|
|
|
|
result = self.gpg.decrypt_file(input_descriptor)
|
|
if close_descriptor:
|
|
input_descriptor.close()
|
|
|
|
if not result.status:
|
|
raise GPGDecryptionError('Unable to decrypt file')
|
|
|
|
return result
|
|
|
|
def create_key(self, *args, **kwargs):
|
|
if kwargs.get('passphrase') == '':
|
|
kwargs.pop('passphrase')
|
|
|
|
input_data = self.gpg.gen_key_input(**kwargs)
|
|
key = self.gpg.gen_key(input_data)
|
|
if not key:
|
|
raise KeyGenerationError('Unable to generate key')
|
|
|
|
return Key.get(self, key.fingerprint)
|
|
|
|
def delete_key(self, key):
|
|
status = self.gpg.delete_keys(key.fingerprint, key.type == 'sec').status
|
|
if status == 'Must delete secret key first':
|
|
self.delete_key(Key.get(self, key.fingerprint, secret=True))
|
|
self.delete_key(key)
|
|
elif status != 'ok':
|
|
raise KeyDeleteError('Unable to delete key')
|
|
|
|
def receive_key(self, key_id):
|
|
for keyserver in self.keyservers:
|
|
import_result = self.gpg.recv_keys(keyserver, key_id)
|
|
if import_result:
|
|
return Key.get(self, import_result.fingerprints[0], secret=False)
|
|
|
|
raise KeyFetchingError
|
|
|
|
def query(self, term):
|
|
results = {}
|
|
for keyserver in self.keyservers:
|
|
url = 'http://%s' % keyserver
|
|
server = KeyServer(url)
|
|
try:
|
|
key_list = server.search(term)
|
|
for key in key_list:
|
|
results[key.keyid] = key
|
|
except:
|
|
pass
|
|
|
|
return results.values()
|
|
|
|
def import_key(self, key_data):
|
|
import_result = self.gpg.import_keys(key_data)
|
|
logger.debug('import_result: %s', import_result)
|
|
|
|
if import_result:
|
|
return Key.get(self, import_result.fingerprints[0], secret=False)
|
|
|
|
raise KeyImportError(import_result.results)
|