1# -*- coding: utf-8 -*- 2 3from __future__ import absolute_import, print_function, unicode_literals 4 5import re 6import os 7import warnings 8import weakref 9 10from . import gpgme 11from .errors import errorcheck, GPGMEError 12from . import constants 13from . import errors 14from . import util 15 16del absolute_import, print_function, unicode_literals 17 18# Copyright (C) 2016-2018 g10 Code GmbH 19# Copyright (C) 2004, 2008 Igor Belyi <belyi@users.sourceforge.net> 20# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> 21# 22# This library is free software; you can redistribute it and/or 23# modify it under the terms of the GNU Lesser General Public 24# License as published by the Free Software Foundation; either 25# version 2.1 of the License, or (at your option) any later version. 26# 27# This library is distributed in the hope that it will be useful, 28# but WITHOUT ANY WARRANTY; without even the implied warranty of 29# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 30# Lesser General Public License for more details. 31# 32# You should have received a copy of the GNU Lesser General Public 33# License along with this library; if not, write to the Free Software 34# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 35"""Core functionality 36 37Core functionality of GPGME wrapped in a object-oriented fashion. 38Provides the 'Context' class for performing cryptographic operations, 39and the 'Data' class describing buffers of data. 40 41""" 42 43 44class GpgmeWrapper(object): 45 """Base wrapper class 46 47 Not to be instantiated directly. 48 49 """ 50 51 def __init__(self, wrapped): 52 self._callback_excinfo = None 53 self.wrapped = wrapped 54 55 def __repr__(self): 56 return '<{}/{!r}>'.format( 57 super(GpgmeWrapper, self).__repr__(), self.wrapped) 58 59 def __str__(self): 60 acc = ['{}.{}'.format(__name__, self.__class__.__name__)] 61 flags = [f for f in self._boolean_properties if getattr(self, f)] 62 if flags: 63 acc.append('({})'.format(' '.join(flags))) 64 65 return '<{}>'.format(' '.join(acc)) 66 67 def __hash__(self): 68 return hash(repr(self.wrapped)) 69 70 def __eq__(self, other): 71 if other is None: 72 return False 73 else: 74 return repr(self.wrapped) == repr(other.wrapped) 75 76 @property 77 def _ctype(self): 78 """The name of the c type wrapped by this class 79 80 Must be set by child classes. 81 82 """ 83 raise NotImplementedError() 84 85 @property 86 def _cprefix(self): 87 """The common prefix of c functions wrapped by this class 88 89 Must be set by child classes. 90 91 """ 92 raise NotImplementedError() 93 94 def _errorcheck(self, name): 95 """Must be implemented by child classes. 96 97 This function must return a trueish value for all c functions 98 returning gpgme_error_t.""" 99 raise NotImplementedError() 100 101 """The set of all boolean properties""" 102 _boolean_properties = set() 103 104 def __wrap_boolean_property(self, key, do_set=False, value=None): 105 get_func = getattr(gpgme, "{}get_{}".format(self._cprefix, key)) 106 set_func = getattr(gpgme, "{}set_{}".format(self._cprefix, key)) 107 108 def get(slf): 109 return bool(get_func(slf.wrapped)) 110 111 def set_(slf, value): 112 set_func(slf.wrapped, bool(value)) 113 114 p = property(get, set_, doc="{} flag".format(key)) 115 setattr(self.__class__, key, p) 116 117 if do_set: 118 set_(self, bool(value)) 119 else: 120 return get(self) 121 122 _munge_docstring = re.compile(r'gpgme_([^(]*)\(([^,]*), (.*\) -> .*)') 123 124 def __getattr__(self, key): 125 """On-the-fly generation of wrapper methods and properties""" 126 if key[0] == '_' or self._cprefix is None: 127 return None 128 129 if key in self._boolean_properties: 130 return self.__wrap_boolean_property(key) 131 132 name = self._cprefix + key 133 func = getattr(gpgme, name) 134 135 if self._errorcheck(name): 136 137 def _funcwrap(slf, *args): 138 result = func(slf.wrapped, *args) 139 if slf._callback_excinfo: 140 gpgme.gpg_raise_callback_exception(slf) 141 return errorcheck(result, name) 142 else: 143 144 def _funcwrap(slf, *args): 145 result = func(slf.wrapped, *args) 146 if slf._callback_excinfo: 147 gpgme.gpg_raise_callback_exception(slf) 148 return result 149 150 doc_orig = getattr(func, "__doc__") 151 if doc_orig: 152 doc = self._munge_docstring.sub(r'\2.\1(\3', doc_orig) 153 else: 154 doc = None 155 156 _funcwrap.__doc__ = doc 157 158 # Monkey-patch the class. 159 setattr(self.__class__, key, _funcwrap) 160 161 # Bind the method to 'self'. 162 def wrapper(*args): 163 return _funcwrap(self, *args) 164 165 wrapper.__doc__ = doc 166 167 return wrapper 168 169 def __setattr__(self, key, value): 170 """On-the-fly generation of properties""" 171 if key in self._boolean_properties: 172 self.__wrap_boolean_property(key, True, value) 173 else: 174 super(GpgmeWrapper, self).__setattr__(key, value) 175 176 177class Context(GpgmeWrapper): 178 """Context for cryptographic operations 179 180 All cryptographic operations in GPGME are performed within a 181 context, which contains the internal state of the operation as 182 well as configuration parameters. By using several contexts you 183 can run several cryptographic operations in parallel, with 184 different configuration. 185 186 Access to a context must be synchronized. 187 188 """ 189 190 def __init__(self, 191 armor=False, 192 textmode=False, 193 offline=False, 194 signers=[], 195 pinentry_mode=constants.PINENTRY_MODE_DEFAULT, 196 protocol=constants.PROTOCOL_OpenPGP, 197 wrapped=None, 198 home_dir=None): 199 """Construct a context object 200 201 Keyword arguments: 202 armor -- enable ASCII armoring (default False) 203 textmode -- enable canonical text mode (default False) 204 offline -- do not contact external key sources (default False) 205 signers -- list of keys used for signing (default []) 206 pinentry_mode -- pinentry mode (default PINENTRY_MODE_DEFAULT) 207 protocol -- protocol to use (default PROTOCOL_OpenPGP) 208 home_dir -- state directory (default is the engine default) 209 210 """ 211 if wrapped: 212 self.own = False 213 else: 214 tmp = gpgme.new_gpgme_ctx_t_p() 215 errorcheck(gpgme.gpgme_new(tmp)) 216 wrapped = gpgme.gpgme_ctx_t_p_value(tmp) 217 gpgme.delete_gpgme_ctx_t_p(tmp) 218 self.own = True 219 super(Context, self).__init__(wrapped) 220 self.armor = armor 221 self.textmode = textmode 222 self.offline = offline 223 self.signers = signers 224 self.pinentry_mode = pinentry_mode 225 self.protocol = protocol 226 self.home_dir = home_dir 227 228 def __read__(self, sink, data): 229 """Read helper 230 231 Helper function to retrieve the results of an operation, or 232 None if SINK is given. 233 """ 234 if sink or data is None: 235 return None 236 data.seek(0, os.SEEK_SET) 237 return data.read() 238 239 def __repr__(self): 240 return ("Context(armor={0.armor}, " 241 "textmode={0.textmode}, offline={0.offline}, " 242 "signers={0.signers}, pinentry_mode={0.pinentry_mode}, " 243 "protocol={0.protocol}, home_dir={0.home_dir}" 244 ")").format(self) 245 246 def encrypt(self, 247 plaintext, 248 recipients=[], 249 sign=True, 250 sink=None, 251 passphrase=None, 252 always_trust=False, 253 add_encrypt_to=False, 254 prepare=False, 255 expect_sign=False, 256 compress=True): 257 """Encrypt data 258 259 Encrypt the given plaintext for the given recipients. If the 260 list of recipients is empty, the data is encrypted 261 symmetrically with a passphrase. 262 263 The passphrase can be given as parameter, using a callback 264 registered at the context, or out-of-band via pinentry. 265 266 Keyword arguments: 267 recipients -- list of keys to encrypt to 268 sign -- sign plaintext (default True) 269 sink -- write result to sink instead of returning it 270 passphrase -- for symmetric encryption 271 always_trust -- always trust the keys (default False) 272 add_encrypt_to -- encrypt to configured additional keys (default False) 273 prepare -- (ui) prepare for encryption (default False) 274 expect_sign -- (ui) prepare for signing (default False) 275 compress -- compress plaintext (default True) 276 277 Returns: 278 ciphertext -- the encrypted data (or None if sink is given) 279 result -- additional information about the encryption 280 sign_result -- additional information about the signature(s) 281 282 Raises: 283 InvalidRecipients -- if encryption using a particular key failed 284 InvalidSigners -- if signing using a particular key failed 285 GPGMEError -- as signaled by the underlying library 286 287 """ 288 ciphertext = sink if sink else Data() 289 flags = 0 290 flags |= always_trust * constants.ENCRYPT_ALWAYS_TRUST 291 flags |= (not add_encrypt_to) * constants.ENCRYPT_NO_ENCRYPT_TO 292 flags |= prepare * constants.ENCRYPT_PREPARE 293 flags |= expect_sign * constants.ENCRYPT_EXPECT_SIGN 294 flags |= (not compress) * constants.ENCRYPT_NO_COMPRESS 295 296 if passphrase is not None: 297 old_pinentry_mode = self.pinentry_mode 298 old_passphrase_cb = getattr(self, '_passphrase_cb', None) 299 self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK 300 301 def passphrase_cb(hint, desc, prev_bad, hook=None): 302 return passphrase 303 304 self.set_passphrase_cb(passphrase_cb) 305 306 try: 307 if sign: 308 self.op_encrypt_sign(recipients, flags, plaintext, ciphertext) 309 else: 310 self.op_encrypt(recipients, flags, plaintext, ciphertext) 311 except errors.GPGMEError as e: 312 result = self.op_encrypt_result() 313 sig_result = self.op_sign_result() if sign else None 314 results = (self.__read__(sink, ciphertext), result, sig_result) 315 if e.getcode() == errors.UNUSABLE_PUBKEY: 316 if result.invalid_recipients: 317 raise errors.InvalidRecipients( 318 result.invalid_recipients, 319 error=e.error, 320 results=results) 321 if e.getcode() == errors.UNUSABLE_SECKEY: 322 sig_result = self.op_sign_result() 323 if sig_result.invalid_signers: 324 raise errors.InvalidSigners( 325 sig_result.invalid_signers, 326 error=e.error, 327 results=results) 328 # Otherwise, just raise the error, but attach the results 329 # first. 330 e.results = results 331 raise e 332 finally: 333 if passphrase is not None: 334 self.pinentry_mode = old_pinentry_mode 335 if old_passphrase_cb: 336 self.set_passphrase_cb(*old_passphrase_cb[1:]) 337 338 result = self.op_encrypt_result() 339 assert not result.invalid_recipients 340 sig_result = self.op_sign_result() if sign else None 341 assert not sig_result or not sig_result.invalid_signers 342 343 return self.__read__(sink, ciphertext), result, sig_result 344 345 def decrypt(self, ciphertext, sink=None, passphrase=None, verify=True): 346 """Decrypt data 347 348 Decrypt the given ciphertext and verify any signatures. If 349 VERIFY is an iterable of keys, the ciphertext must be signed 350 by all those keys, otherwise a MissingSignatures error is 351 raised. Note: if VERIFY is an empty iterable, that is treated 352 the same as passing verify=True (that is, verify signatures 353 and return data about any valid signatures found, but no 354 signatures are required and no MissingSignatures error will be 355 raised). 356 357 If the ciphertext is symmetrically encrypted using a 358 passphrase, that passphrase can be given as parameter, using a 359 callback registered at the context, or out-of-band via 360 pinentry. 361 362 Keyword arguments: 363 sink -- write result to sink instead of returning it 364 passphrase -- for symmetric decryption 365 verify -- check signatures (boolean or iterable of keys, 366 see above) (default True) 367 368 Returns: 369 plaintext -- the decrypted data (or None if sink is given) 370 result -- additional information about the decryption 371 verify_result -- additional information about the valid 372 signature(s) found 373 374 Raises: 375 UnsupportedAlgorithm -- if an unsupported algorithm was used 376 MissingSignatures -- if expected signatures are missing or bad 377 GPGMEError -- as signaled by the underlying library 378 379 """ 380 do_sig_verification = False 381 required_keys = None 382 plaintext = sink if sink else Data() 383 384 if passphrase is not None: 385 old_pinentry_mode = self.pinentry_mode 386 old_passphrase_cb = getattr(self, '_passphrase_cb', None) 387 self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK 388 389 def passphrase_cb(hint, desc, prev_bad, hook=None): 390 return passphrase 391 392 self.set_passphrase_cb(passphrase_cb) 393 394 try: 395 if isinstance(verify, bool): 396 do_sig_verification = verify 397 elif verify is None: 398 warnings.warn( 399 "ctx.decrypt called with verify=None, should be bool or iterable (treating as False).", 400 category=DeprecationWarning) 401 do_sig_verification = False 402 else: 403 # we hope this is an iterable: 404 required_keys = verify 405 do_sig_verification = True 406 407 if do_sig_verification: 408 self.op_decrypt_verify(ciphertext, plaintext) 409 else: 410 self.op_decrypt(ciphertext, plaintext) 411 except errors.GPGMEError as e: 412 result = self.op_decrypt_result() 413 if do_sig_verification: 414 verify_result = self.op_verify_result() 415 else: 416 verify_result = None 417 # Just raise the error, but attach the results first. 418 e.results = (self.__read__(sink, plaintext), result, verify_result) 419 raise e 420 finally: 421 if passphrase is not None: 422 self.pinentry_mode = old_pinentry_mode 423 if old_passphrase_cb: 424 self.set_passphrase_cb(*old_passphrase_cb[1:]) 425 426 result = self.op_decrypt_result() 427 428 if do_sig_verification: 429 verify_result = self.op_verify_result() 430 else: 431 verify_result = None 432 433 results = (self.__read__(sink, plaintext), result, verify_result) 434 435 if result.unsupported_algorithm: 436 raise errors.UnsupportedAlgorithm(result.unsupported_algorithm, 437 results=results) 438 439 if do_sig_verification: 440 # filter out all invalid signatures 441 verify_result.signatures = list(filter(lambda s: s.status == errors.NO_ERROR, verify_result.signatures)) 442 if required_keys is not None: 443 missing = [] 444 for key in required_keys: 445 ok = False 446 for subkey in key.subkeys: 447 for sig in verify_result.signatures: 448 if sig.summary & constants.SIGSUM_VALID == 0: 449 continue 450 if subkey.can_sign and subkey.fpr == sig.fpr: 451 ok = True 452 break 453 if ok: 454 break 455 if not ok: 456 missing.append(key) 457 if missing: 458 raise errors.MissingSignatures(verify_result, missing, 459 results=results) 460 461 return results 462 463 def sign(self, data, sink=None, mode=constants.SIG_MODE_NORMAL): 464 """Sign data 465 466 Sign the given data with either the configured default local 467 key, or the 'signers' keys of this context. 468 469 Keyword arguments: 470 mode -- signature mode (default: normal, see below) 471 sink -- write result to sink instead of returning it 472 473 Returns: 474 either 475 signed_data -- encoded data and signature (normal mode) 476 signature -- only the signature data (detached mode) 477 cleartext -- data and signature as text (cleartext mode) 478 (or None if sink is given) 479 result -- additional information about the signature(s) 480 481 Raises: 482 InvalidSigners -- if signing using a particular key failed 483 GPGMEError -- as signaled by the underlying library 484 485 """ 486 signeddata = sink if sink else Data() 487 488 try: 489 self.op_sign(data, signeddata, mode) 490 except errors.GPGMEError as e: 491 results = (self.__read__(sink, signeddata), self.op_sign_result()) 492 if e.getcode() == errors.UNUSABLE_SECKEY: 493 if results[1].invalid_signers: 494 raise errors.InvalidSigners( 495 results[1].invalid_signers, 496 error=e.error, 497 results=results) 498 e.results = results 499 raise e 500 501 result = self.op_sign_result() 502 assert not result.invalid_signers 503 504 return self.__read__(sink, signeddata), result 505 506 def verify(self, signed_data, signature=None, sink=None, verify=[]): 507 """Verify signatures 508 509 Verify signatures over data. If VERIFY is an iterable of 510 keys, the ciphertext must be signed by all those keys, 511 otherwise an error is raised. 512 513 Keyword arguments: 514 signature -- detached signature data 515 sink -- write result to sink instead of returning it 516 517 Returns: 518 data -- the plain data 519 (or None if sink is given, or we verified a detached signature) 520 result -- additional information about the signature(s) 521 522 Raises: 523 BadSignatures -- if a bad signature is encountered 524 MissingSignatures -- if expected signatures are missing or bad 525 GPGMEError -- as signaled by the underlying library 526 527 """ 528 if signature: 529 # Detached signature, we don't return the plain text. 530 data = None 531 else: 532 data = sink if sink else Data() 533 534 try: 535 if signature: 536 self.op_verify(signature, signed_data, None) 537 else: 538 self.op_verify(signed_data, None, data) 539 except errors.GPGMEError as e: 540 # Just raise the error, but attach the results first. 541 e.results = (self.__read__(sink, data), self.op_verify_result()) 542 raise e 543 544 results = (self.__read__(sink, data), self.op_verify_result()) 545 if any(s.status != errors.NO_ERROR for s in results[1].signatures): 546 raise errors.BadSignatures(results[1], results=results) 547 548 missing = list() 549 for key in verify: 550 ok = False 551 for subkey in key.subkeys: 552 for sig in results[1].signatures: 553 if sig.summary & constants.SIGSUM_VALID == 0: 554 continue 555 if subkey.can_sign and subkey.fpr == sig.fpr: 556 ok = True 557 break 558 if ok: 559 break 560 if not ok: 561 missing.append(key) 562 if missing: 563 raise errors.MissingSignatures( 564 results[1], missing, results=results) 565 566 return results 567 568 def key_import(self, data): 569 """Import data 570 571 Imports the given data into the Context. 572 573 Returns: 574 -- an object describing the results of imported or updated 575 keys 576 577 Raises: 578 TypeError -- Very rarely. 579 GPGMEError -- as signaled by the underlying library: 580 581 Import status errors, when they occur, will usually 582 be of NODATA. NO_PUBKEY indicates something 583 managed to run the function without any 584 arguments, while an argument of None triggers 585 the first NODATA of errors.GPGME in the 586 exception. 587 """ 588 try: 589 self.op_import(data) 590 result = self.op_import_result() 591 if result.considered == 0: 592 status = constants.STATUS_IMPORT_PROBLEM 593 else: 594 status = constants.STATUS_KEY_CONSIDERED 595 except Exception as e: 596 if e == errors.GPGMEError: 597 if e.code_str == "No data": 598 status = constants.STATUS_NODATA 599 else: 600 status = constants.STATUS_FILE_ERROR 601 elif e == TypeError and hasattr(data, "decode") is True: 602 status = constants.STATUS_NO_PUBKEY 603 elif e == TypeError and hasattr(data, "encode") is True: 604 status = constants.STATUS_FILE_ERROR 605 else: 606 status = constants.STATUS_ERROR 607 608 if status == constants.STATUS_KEY_CONSIDERED: 609 import_result = result 610 else: 611 import_result = status 612 613 return import_result 614 615 def key_export(self, pattern=None): 616 """Export keys. 617 618 Exports public keys matching the pattern specified. If no 619 pattern is specified then exports all available keys. 620 621 Keyword arguments: 622 pattern -- return keys matching pattern (default: all keys) 623 624 Returns: 625 -- A key block containing one or more OpenPGP keys in 626 either ASCII armoured or binary format as determined 627 by the Context(). If there are no matching keys it 628 returns None. 629 630 Raises: 631 GPGMEError -- as signaled by the underlying library. 632 """ 633 data = Data() 634 mode = 0 635 try: 636 self.op_export(pattern, mode, data) 637 data.seek(0, os.SEEK_SET) 638 pk_result = data.read() 639 except GPGMEError as e: 640 raise e 641 642 if len(pk_result) > 0: 643 result = pk_result 644 else: 645 result = None 646 647 return result 648 649 def key_export_minimal(self, pattern=None): 650 """Export keys. 651 652 Exports public keys matching the pattern specified in a 653 minimised format. If no pattern is specified then exports all 654 available keys. 655 656 Keyword arguments: 657 pattern -- return keys matching pattern (default: all keys) 658 659 Returns: 660 -- A key block containing one or more minimised OpenPGP 661 keys in either ASCII armoured or binary format as 662 determined by the Context(). If there are no matching 663 keys it returns None. 664 665 Raises: 666 GPGMEError -- as signaled by the underlying library. 667 """ 668 data = Data() 669 mode = gpgme.GPGME_EXPORT_MODE_MINIMAL 670 try: 671 self.op_export(pattern, mode, data) 672 data.seek(0, os.SEEK_SET) 673 pk_result = data.read() 674 except GPGMEError as e: 675 raise e 676 677 if len(pk_result) > 0: 678 result = pk_result 679 else: 680 result = None 681 682 return result 683 684 def key_export_secret(self, pattern=None): 685 """Export secret keys. 686 687 Exports secret keys matching the pattern specified. If no 688 pattern is specified then exports or attempts to export all 689 available secret keys. 690 691 IMPORTANT: Each secret key to be exported will prompt for its 692 passphrase via an invocation of pinentry and gpg-agent. If the 693 passphrase is not entered or does not match then no data will be 694 exported. This is the same result as when specifying a pattern 695 that is not matched by the available keys. 696 697 Keyword arguments: 698 pattern -- return keys matching pattern (default: all keys) 699 700 Returns: 701 -- On success a key block containing one or more OpenPGP 702 secret keys in either ASCII armoured or binary format 703 as determined by the Context(). 704 -- On failure while not raising an exception, returns None. 705 706 Raises: 707 GPGMEError -- as signaled by the underlying library. 708 """ 709 data = Data() 710 mode = gpgme.GPGME_EXPORT_MODE_SECRET 711 try: 712 self.op_export(pattern, mode, data) 713 data.seek(0, os.SEEK_SET) 714 sk_result = data.read() 715 except GPGMEError as e: 716 raise e 717 718 if len(sk_result) > 0: 719 result = sk_result 720 else: 721 result = None 722 723 return result 724 725 def keylist(self, 726 pattern=None, 727 secret=False, 728 mode=constants.keylist.mode.LOCAL, 729 source=None): 730 """List keys 731 732 Keyword arguments: 733 pattern -- return keys matching pattern (default: all keys) 734 secret -- return only secret keys (default: False) 735 mode -- keylist mode (default: list local keys) 736 source -- read keys from source instead from the keyring 737 (all other options are ignored in this case) 738 739 Returns: 740 -- an iterator returning key objects 741 742 Raises: 743 GPGMEError -- as signaled by the underlying library 744 """ 745 if not source: 746 self.set_keylist_mode(mode) 747 self.op_keylist_start(pattern, secret) 748 else: 749 # Automatic wrapping of SOURCE is not possible here, 750 # because the object must not be deallocated until the 751 # iteration over the results ends. 752 if not isinstance(source, Data): 753 source = Data(file=source) 754 self.op_keylist_from_data_start(source, 0) 755 756 key = self.op_keylist_next() 757 while key: 758 yield key 759 key = self.op_keylist_next() 760 self.op_keylist_end() 761 762 def create_key(self, 763 userid, 764 algorithm=None, 765 expires_in=0, 766 expires=True, 767 sign=False, 768 encrypt=False, 769 certify=False, 770 authenticate=False, 771 passphrase=None, 772 force=False): 773 """Create a primary key 774 775 Create a primary key for the user id USERID. 776 777 ALGORITHM may be used to specify the public key encryption 778 algorithm for the new key. By default, a reasonable default 779 is chosen. You may use "future-default" to select an 780 algorithm that will be the default in a future implementation 781 of the engine. ALGORITHM may be a string like "rsa", or 782 "rsa2048" to explicitly request an algorithm and a key size. 783 784 EXPIRES_IN specifies the expiration time of the key in number 785 of seconds since the keys creation. By default, a reasonable 786 expiration time is chosen. If you want to create a key that 787 does not expire, use the keyword argument EXPIRES. 788 789 SIGN, ENCRYPT, CERTIFY, and AUTHENTICATE can be used to 790 request the capabilities of the new key. If you don't request 791 any, a reasonable set of capabilities is selected, and in case 792 of OpenPGP, a subkey with a reasonable set of capabilities is 793 created. 794 795 If PASSPHRASE is None (the default), then the key will not be 796 protected with a passphrase. If PASSPHRASE is a string, it 797 will be used to protect the key. If PASSPHRASE is True, the 798 passphrase must be supplied using a passphrase callback or 799 out-of-band with a pinentry. 800 801 Keyword arguments: 802 algorithm -- public key algorithm, see above (default: reasonable) 803 expires_in -- expiration time in seconds (default: reasonable) 804 expires -- whether or not the key should expire (default: True) 805 sign -- request the signing capability (see above) 806 encrypt -- request the encryption capability (see above) 807 certify -- request the certification capability (see above) 808 authenticate -- request the authentication capability (see above) 809 passphrase -- protect the key with a passphrase (default: no 810 passphrase) 811 force -- force key creation even if a key with the same userid 812 exists (default: False) 813 814 Returns: 815 -- an object describing the result of the key creation 816 817 Raises: 818 GPGMEError -- as signaled by the underlying library 819 820 """ 821 if util.is_a_string(passphrase): 822 old_pinentry_mode = self.pinentry_mode 823 old_passphrase_cb = getattr(self, '_passphrase_cb', None) 824 self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK 825 826 def passphrase_cb(hint, desc, prev_bad, hook=None): 827 return passphrase 828 829 self.set_passphrase_cb(passphrase_cb) 830 831 try: 832 self.op_createkey( 833 userid, 834 algorithm, 835 0, # reserved 836 expires_in, 837 None, # extrakey 838 ((constants.create.SIGN if sign else 0) | 839 (constants.create.ENCR if encrypt else 0) | 840 (constants.create.CERT if certify else 0) | 841 (constants.create.AUTH if authenticate else 0) | 842 (constants.create.NOPASSWD if passphrase is None else 0) | 843 (0 if expires else constants.create.NOEXPIRE) | 844 (constants.create.FORCE if force else 0))) 845 finally: 846 if util.is_a_string(passphrase): 847 self.pinentry_mode = old_pinentry_mode 848 if old_passphrase_cb: 849 self.set_passphrase_cb(*old_passphrase_cb[1:]) 850 851 return self.op_genkey_result() 852 853 def create_subkey(self, 854 key, 855 algorithm=None, 856 expires_in=0, 857 expires=True, 858 sign=False, 859 encrypt=False, 860 authenticate=False, 861 passphrase=None): 862 """Create a subkey 863 864 Create a subkey for the given KEY. As subkeys are a concept 865 of OpenPGP, calling this is only valid for the OpenPGP 866 protocol. 867 868 ALGORITHM may be used to specify the public key encryption 869 algorithm for the new subkey. By default, a reasonable 870 default is chosen. You may use "future-default" to select an 871 algorithm that will be the default in a future implementation 872 of the engine. ALGORITHM may be a string like "rsa", or 873 "rsa2048" to explicitly request an algorithm and a key size. 874 875 EXPIRES_IN specifies the expiration time of the subkey in 876 number of seconds since the subkeys creation. By default, a 877 reasonable expiration time is chosen. If you want to create a 878 subkey that does not expire, use the keyword argument EXPIRES. 879 880 SIGN, ENCRYPT, and AUTHENTICATE can be used to request the 881 capabilities of the new subkey. If you don't request any, an 882 encryption subkey is generated. 883 884 If PASSPHRASE is None (the default), then the subkey will not 885 be protected with a passphrase. If PASSPHRASE is a string, it 886 will be used to protect the subkey. If PASSPHRASE is True, 887 the passphrase must be supplied using a passphrase callback or 888 out-of-band with a pinentry. 889 890 Keyword arguments: 891 algorithm -- public key algorithm, see above (default: reasonable) 892 expires_in -- expiration time in seconds (default: reasonable) 893 expires -- whether or not the subkey should expire (default: True) 894 sign -- request the signing capability (see above) 895 encrypt -- request the encryption capability (see above) 896 authenticate -- request the authentication capability (see above) 897 passphrase -- protect the subkey with a passphrase (default: no 898 passphrase) 899 900 Returns: 901 -- an object describing the result of the subkey creation 902 903 Raises: 904 GPGMEError -- as signaled by the underlying library 905 906 """ 907 if util.is_a_string(passphrase): 908 old_pinentry_mode = self.pinentry_mode 909 old_passphrase_cb = getattr(self, '_passphrase_cb', None) 910 self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK 911 912 def passphrase_cb(hint, desc, prev_bad, hook=None): 913 return passphrase 914 915 self.set_passphrase_cb(passphrase_cb) 916 917 try: 918 self.op_createsubkey( 919 key, 920 algorithm, 921 0, # reserved 922 expires_in, 923 ((constants.create.SIGN if sign else 0) | 924 (constants.create.ENCR if encrypt else 0) | 925 (constants.create.AUTH if authenticate else 0) | 926 (constants.create.NOPASSWD if passphrase is None else 0) | 927 (0 if expires else constants.create.NOEXPIRE))) 928 finally: 929 if util.is_a_string(passphrase): 930 self.pinentry_mode = old_pinentry_mode 931 if old_passphrase_cb: 932 self.set_passphrase_cb(*old_passphrase_cb[1:]) 933 934 return self.op_genkey_result() 935 936 def key_add_uid(self, key, uid): 937 """Add a UID 938 939 Add the uid UID to the given KEY. Calling this function is 940 only valid for the OpenPGP protocol. 941 942 Raises: 943 GPGMEError -- as signaled by the underlying library 944 945 """ 946 self.op_adduid(key, uid, 0) 947 948 def key_revoke_uid(self, key, uid): 949 """Revoke a UID 950 951 Revoke the uid UID from the given KEY. Calling this function 952 is only valid for the OpenPGP protocol. 953 954 Raises: 955 GPGMEError -- as signaled by the underlying library 956 957 """ 958 self.op_revuid(key, uid, 0) 959 960 def key_sign(self, key, uids=None, expires_in=False, local=False): 961 """Sign a key 962 963 Sign a key with the current set of signing keys. Calling this 964 function is only valid for the OpenPGP protocol. 965 966 If UIDS is None (the default), then all UIDs are signed. If 967 it is a string, then only the matching UID is signed. If it 968 is a list of strings, then all matching UIDs are signed. Note 969 that a case-sensitive exact string comparison is done. 970 971 EXPIRES_IN specifies the expiration time of the signature in 972 seconds. If EXPIRES_IN is False, the signature does not 973 expire. 974 975 Keyword arguments: 976 uids -- user ids to sign, see above (default: sign all) 977 expires_in -- validity period of the signature in seconds 978 (default: do not expire) 979 local -- create a local, non-exportable signature 980 (default: False) 981 982 Raises: 983 GPGMEError -- as signaled by the underlying library 984 985 """ 986 flags = 0 987 if uids is None or util.is_a_string(uids): 988 pass # through unchanged 989 else: 990 flags |= constants.keysign.LFSEP 991 uids = "\n".join(uids) 992 993 if not expires_in: 994 flags |= constants.keysign.NOEXPIRE 995 996 if local: 997 flags |= constants.keysign.LOCAL 998 999 self.op_keysign(key, uids, expires_in, flags) 1000 1001 def key_tofu_policy(self, key, policy): 1002 """Set a keys' TOFU policy 1003 1004 Set the TOFU policy associated with KEY to POLICY. Calling 1005 this function is only valid for the OpenPGP protocol. 1006 1007 Raises: 1008 GPGMEError -- as signaled by the underlying library 1009 1010 """ 1011 self.op_tofu_policy(key, policy) 1012 1013 def assuan_transact(self, 1014 command, 1015 data_cb=None, 1016 inquire_cb=None, 1017 status_cb=None): 1018 """Issue a raw assuan command 1019 1020 This function can be used to issue a raw assuan command to the 1021 engine. 1022 1023 If command is a string or bytes, it will be used as-is. If it 1024 is an iterable of strings, it will be properly escaped and 1025 joined into an well-formed assuan command. 1026 1027 Keyword arguments: 1028 data_cb -- a callback receiving data lines 1029 inquire_cb -- a callback providing more information 1030 status_cb -- a callback receiving status lines 1031 1032 Returns: 1033 result -- the result of command as GPGMEError 1034 1035 Raises: 1036 GPGMEError -- as signaled by the underlying library 1037 1038 """ 1039 1040 if util.is_a_string(command) or isinstance(command, bytes): 1041 cmd = command 1042 else: 1043 cmd = " ".join(util.percent_escape(f) for f in command) 1044 1045 errptr = gpgme.new_gpgme_error_t_p() 1046 1047 err = gpgme.gpgme_op_assuan_transact_ext( 1048 self.wrapped, cmd, (weakref.ref(self), data_cb) 1049 if data_cb else None, (weakref.ref(self), inquire_cb) 1050 if inquire_cb else None, (weakref.ref(self), status_cb) 1051 if status_cb else None, errptr) 1052 1053 if self._callback_excinfo: 1054 gpgme.gpg_raise_callback_exception(self) 1055 1056 errorcheck(err) 1057 1058 status = gpgme.gpgme_error_t_p_value(errptr) 1059 gpgme.delete_gpgme_error_t_p(errptr) 1060 1061 return GPGMEError(status) if status != 0 else None 1062 1063 def interact(self, key, func, sink=None, flags=0, fnc_value=None): 1064 """Interact with the engine 1065 1066 This method can be used to edit keys and cards interactively. 1067 KEY is the key to edit, FUNC is called repeatedly with two 1068 unicode arguments, 'keyword' and 'args'. See the GPGME manual 1069 for details. 1070 1071 Keyword arguments: 1072 sink -- if given, additional output is written here 1073 flags -- use constants.INTERACT_CARD to edit a card 1074 1075 Raises: 1076 GPGMEError -- as signaled by the underlying library 1077 1078 """ 1079 if key is None: 1080 raise ValueError("First argument cannot be None") 1081 1082 if sink is None: 1083 sink = Data() 1084 1085 if fnc_value: 1086 opaquedata = (weakref.ref(self), func, fnc_value) 1087 else: 1088 opaquedata = (weakref.ref(self), func) 1089 1090 result = gpgme.gpgme_op_interact(self.wrapped, key, flags, opaquedata, 1091 sink) 1092 if self._callback_excinfo: 1093 gpgme.gpg_raise_callback_exception(self) 1094 errorcheck(result) 1095 1096 @property 1097 def signers(self): 1098 """Keys used for signing""" 1099 return [self.signers_enum(i) for i in range(self.signers_count())] 1100 1101 @signers.setter 1102 def signers(self, signers): 1103 old = self.signers 1104 self.signers_clear() 1105 try: 1106 for key in signers: 1107 self.signers_add(key) 1108 except: 1109 self.signers = old 1110 raise 1111 1112 @property 1113 def pinentry_mode(self): 1114 """Pinentry mode""" 1115 return self.get_pinentry_mode() 1116 1117 @pinentry_mode.setter 1118 def pinentry_mode(self, value): 1119 self.set_pinentry_mode(value) 1120 1121 @property 1122 def protocol(self): 1123 """Protocol to use""" 1124 return self.get_protocol() 1125 1126 @protocol.setter 1127 def protocol(self, value): 1128 errorcheck(gpgme.gpgme_engine_check_version(value)) 1129 self.set_protocol(value) 1130 1131 @property 1132 def home_dir(self): 1133 """Engine's home directory""" 1134 return self.engine_info.home_dir 1135 1136 @home_dir.setter 1137 def home_dir(self, value): 1138 self.set_engine_info(self.protocol, home_dir=value) 1139 1140 _ctype = 'gpgme_ctx_t' 1141 _cprefix = 'gpgme_' 1142 1143 def _errorcheck(self, name): 1144 """This function should list all functions returning gpgme_error_t""" 1145 # The list of functions is created using: 1146 # 1147 # $ grep '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \ 1148 # | grep -v _op_ | awk "/\(gpgme_ctx/ { printf (\"'%s',\\n\", \$2) } " 1149 return ((name.startswith('gpgme_op_') and not 1150 name.endswith('_result')) or name in { 1151 'gpgme_new', 'gpgme_set_ctx_flag', 'gpgme_set_protocol', 1152 'gpgme_set_sub_protocol', 'gpgme_set_keylist_mode', 1153 'gpgme_set_pinentry_mode', 'gpgme_set_locale', 1154 'gpgme_ctx_set_engine_info', 'gpgme_signers_add', 1155 'gpgme_sig_notation_add', 'gpgme_set_sender', 1156 'gpgme_cancel', 'gpgme_cancel_async', 'gpgme_get_key', 1157 'gpgme_get_sig_key', 1158 }) 1159 1160 _boolean_properties = {'armor', 'textmode', 'offline'} 1161 1162 def __del__(self): 1163 if not gpgme: 1164 # At interpreter shutdown, gpgme is set to NONE. 1165 return 1166 1167 self._free_passcb() 1168 self._free_progresscb() 1169 self._free_statuscb() 1170 if self.own and self.wrapped and gpgme.gpgme_release: 1171 gpgme.gpgme_release(self.wrapped) 1172 self.wrapped = None 1173 1174 # Implement the context manager protocol. 1175 def __enter__(self): 1176 return self 1177 1178 def __exit__(self, type, value, tb): 1179 self.__del__() 1180 1181 def op_keylist_all(self, *args, **kwargs): 1182 self.op_keylist_start(*args, **kwargs) 1183 key = self.op_keylist_next() 1184 while key: 1185 yield key 1186 key = self.op_keylist_next() 1187 self.op_keylist_end() 1188 1189 def op_keylist_next(self): 1190 """Returns the next key in the list created 1191 by a call to op_keylist_start(). The object returned 1192 is of type Key.""" 1193 ptr = gpgme.new_gpgme_key_t_p() 1194 try: 1195 errorcheck(gpgme.gpgme_op_keylist_next(self.wrapped, ptr)) 1196 key = gpgme.gpgme_key_t_p_value(ptr) 1197 except errors.GPGMEError as excp: 1198 key = None 1199 if excp.getcode() != errors.EOF: 1200 raise excp 1201 gpgme.delete_gpgme_key_t_p(ptr) 1202 if key: 1203 key.__del__ = lambda self: gpgme.gpgme_key_unref(self) 1204 return key 1205 1206 def get_key(self, fpr, secret=False): 1207 """Get a key given a fingerprint 1208 1209 Keyword arguments: 1210 secret -- to request a secret key 1211 1212 Returns: 1213 -- the matching key 1214 1215 Raises: 1216 KeyError -- if the key was not found 1217 GPGMEError -- as signaled by the underlying library 1218 1219 """ 1220 ptr = gpgme.new_gpgme_key_t_p() 1221 1222 try: 1223 errorcheck(gpgme.gpgme_get_key(self.wrapped, fpr, ptr, secret)) 1224 except errors.GPGMEError as e: 1225 if e.getcode() == errors.EOF: 1226 raise errors.KeyNotFound(fpr) 1227 raise e 1228 1229 key = gpgme.gpgme_key_t_p_value(ptr) 1230 gpgme.delete_gpgme_key_t_p(ptr) 1231 assert key 1232 key.__del__ = lambda self: gpgme.gpgme_key_unref(self) 1233 return key 1234 1235 def op_trustlist_all(self, *args, **kwargs): 1236 self.op_trustlist_start(*args, **kwargs) 1237 trust = self.op_trustlist_next() 1238 while trust: 1239 yield trust 1240 trust = self.op_trustlist_next() 1241 self.op_trustlist_end() 1242 1243 def op_trustlist_next(self): 1244 """Returns the next trust item in the list created 1245 by a call to op_trustlist_start(). The object returned 1246 is of type TrustItem.""" 1247 ptr = gpgme.new_gpgme_trust_item_t_p() 1248 try: 1249 errorcheck(gpgme.gpgme_op_trustlist_next(self.wrapped, ptr)) 1250 trust = gpgme.gpgme_trust_item_t_p_value(ptr) 1251 except errors.GPGMEError as excp: 1252 trust = None 1253 if excp.getcode() != errors.EOF: 1254 raise 1255 gpgme.delete_gpgme_trust_item_t_p(ptr) 1256 return trust 1257 1258 def set_passphrase_cb(self, func, hook=None): 1259 """Sets the passphrase callback to the function specified by func. 1260 1261 When the system needs a passphrase, it will call func with three args: 1262 hint, a string describing the key it needs the passphrase for; 1263 desc, a string describing the passphrase it needs; 1264 prev_bad, a boolean equal True if this is a call made after 1265 unsuccessful previous attempt. 1266 1267 If hook has a value other than None it will be passed into the func 1268 as a forth argument. 1269 1270 Please see the GPGME manual for more information. 1271 """ 1272 if func is None: 1273 hookdata = None 1274 else: 1275 if hook is None: 1276 hookdata = (weakref.ref(self), func) 1277 else: 1278 hookdata = (weakref.ref(self), func, hook) 1279 gpgme.gpg_set_passphrase_cb(self, hookdata) 1280 1281 def _free_passcb(self): 1282 if gpgme.gpg_set_passphrase_cb: 1283 self.set_passphrase_cb(None) 1284 1285 def set_progress_cb(self, func, hook=None): 1286 """Sets the progress meter callback to the function specified by FUNC. 1287 If FUNC is None, the callback will be cleared. 1288 1289 This function will be called to provide an interactive update 1290 of the system's progress. The function will be called with 1291 three arguments, type, total, and current. If HOOK is not 1292 None, it will be supplied as fourth argument. 1293 1294 Please see the GPGME manual for more information. 1295 1296 """ 1297 if func is None: 1298 hookdata = None 1299 else: 1300 if hook is None: 1301 hookdata = (weakref.ref(self), func) 1302 else: 1303 hookdata = (weakref.ref(self), func, hook) 1304 gpgme.gpg_set_progress_cb(self, hookdata) 1305 1306 def _free_progresscb(self): 1307 if gpgme.gpg_set_progress_cb: 1308 self.set_progress_cb(None) 1309 1310 def set_status_cb(self, func, hook=None): 1311 """Sets the status callback to the function specified by FUNC. If 1312 FUNC is None, the callback will be cleared. 1313 1314 The function will be called with two arguments, keyword and 1315 args. If HOOK is not None, it will be supplied as third 1316 argument. 1317 1318 Please see the GPGME manual for more information. 1319 1320 """ 1321 if func is None: 1322 hookdata = None 1323 else: 1324 if hook is None: 1325 hookdata = (weakref.ref(self), func) 1326 else: 1327 hookdata = (weakref.ref(self), func, hook) 1328 gpgme.gpg_set_status_cb(self, hookdata) 1329 1330 def _free_statuscb(self): 1331 if gpgme.gpg_set_status_cb: 1332 self.set_status_cb(None) 1333 1334 @property 1335 def engine_info(self): 1336 """Configuration of the engine currently in use""" 1337 p = self.protocol 1338 infos = [i for i in self.get_engine_info() if i.protocol == p] 1339 assert len(infos) == 1 1340 return infos[0] 1341 1342 def get_engine_info(self): 1343 """Get engine configuration 1344 1345 Returns information about all configured and installed 1346 engines. 1347 1348 Returns: 1349 infos -- a list of engine infos 1350 1351 """ 1352 return gpgme.gpgme_ctx_get_engine_info(self.wrapped) 1353 1354 def set_engine_info(self, proto, file_name=None, home_dir=None): 1355 """Change engine configuration 1356 1357 Changes the configuration of the crypto engine implementing 1358 the protocol 'proto' for the context. 1359 1360 Keyword arguments: 1361 file_name -- engine program file name (unchanged if None) 1362 home_dir -- configuration directory (unchanged if None) 1363 1364 """ 1365 self.ctx_set_engine_info(proto, file_name, home_dir) 1366 1367 def wait(self, hang): 1368 """Wait for asynchronous call to finish. Wait forever if hang is True. 1369 Raises an exception on errors. 1370 1371 Please read the GPGME manual for more information. 1372 1373 """ 1374 ptr = gpgme.new_gpgme_error_t_p() 1375 gpgme.gpgme_wait(self.wrapped, ptr, hang) 1376 status = gpgme.gpgme_error_t_p_value(ptr) 1377 gpgme.delete_gpgme_error_t_p(ptr) 1378 errorcheck(status) 1379 1380 def op_edit(self, key, func, fnc_value, out): 1381 """Start key editing using supplied callback function 1382 1383 Note: This interface is deprecated and will be removed with 1384 GPGME 1.8. Please use .interact instead. Furthermore, we 1385 implement this using gpgme_op_interact, so callbacks will get 1386 called with string keywords instead of numeric status 1387 messages. Code that is using constants.STATUS_X or 1388 constants.status.X will continue to work, whereas code using 1389 magic numbers will break as a result. 1390 1391 """ 1392 warnings.warn( 1393 "Call to deprecated method op_edit.", category=DeprecationWarning) 1394 return self.interact(key, func, sink=out, fnc_value=fnc_value) 1395 1396 1397class Data(GpgmeWrapper): 1398 """Data buffer 1399 1400 A lot of data has to be exchanged between the user and the crypto 1401 engine, like plaintext messages, ciphertext, signatures and 1402 information about the keys. The technical details about 1403 exchanging the data information are completely abstracted by 1404 GPGME. The user provides and receives the data via `gpgme_data_t' 1405 objects, regardless of the communication protocol between GPGME 1406 and the crypto engine in use. 1407 1408 This Data class is the implementation of the GpgmeData objects. 1409 1410 Please see the information about __init__ for instantiation. 1411 1412 """ 1413 1414 _ctype = 'gpgme_data_t' 1415 _cprefix = 'gpgme_data_' 1416 1417 def _errorcheck(self, name): 1418 """This function should list all functions returning gpgme_error_t""" 1419 # This list is compiled using 1420 # 1421 # $ grep -v '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \ 1422 # | awk "/\(gpgme_data_t/ { printf (\"'%s',\\n\", \$2) } " \ 1423 # | sed "s/'\\*/'/" 1424 return name not in { 1425 'gpgme_data_read', 1426 'gpgme_data_write', 1427 'gpgme_data_seek', 1428 'gpgme_data_release', 1429 'gpgme_data_release_and_get_mem', 1430 'gpgme_data_get_encoding', 1431 'gpgme_data_get_file_name', 1432 'gpgme_data_set_flag', 1433 'gpgme_data_identify', 1434 } 1435 1436 def __init__(self, 1437 string=None, 1438 file=None, 1439 offset=None, 1440 length=None, 1441 cbs=None, 1442 copy=True): 1443 """Initialize a new gpgme_data_t object. 1444 1445 If no args are specified, make it an empty object. 1446 1447 If string alone is specified, initialize it with the data 1448 contained there. 1449 1450 If file, offset, and length are all specified, file must 1451 be either a filename or a file-like object, and the object 1452 will be initialized by reading the specified chunk from the file. 1453 1454 If cbs is specified, it MUST be a tuple of the form: 1455 1456 (read_cb, write_cb, seek_cb, release_cb[, hook]) 1457 1458 where the first four items are functions implementing reading, 1459 writing, seeking the data, and releasing any resources once 1460 the data object is deallocated. The functions must match the 1461 following prototypes: 1462 1463 def read(amount, hook=None): 1464 return <a b"bytes" object> 1465 1466 def write(data, hook=None): 1467 return <the number of bytes written> 1468 1469 def seek(offset, whence, hook=None): 1470 return <the new file position> 1471 1472 def release(hook=None): 1473 <return value and exceptions are ignored> 1474 1475 The functions may be bound methods. In that case, you can 1476 simply use the 'self' reference instead of using a hook. 1477 1478 If file is specified without any other arguments, then 1479 it must be a filename, and the object will be initialized from 1480 that file. 1481 1482 """ 1483 super(Data, self).__init__(None) 1484 self.data_cbs = None 1485 1486 if cbs is not None: 1487 self.new_from_cbs(*cbs) 1488 elif string is not None: 1489 self.new_from_mem(string, copy) 1490 elif file is not None and offset is not None and length is not None: 1491 self.new_from_filepart(file, offset, length) 1492 elif file is not None: 1493 if util.is_a_string(file): 1494 self.new_from_file(file, copy) 1495 else: 1496 self.new_from_fd(file) 1497 else: 1498 self.new() 1499 1500 def __del__(self): 1501 if not gpgme: 1502 # At interpreter shutdown, gpgme is set to NONE. 1503 return 1504 1505 if self.wrapped is not None and gpgme.gpgme_data_release: 1506 gpgme.gpgme_data_release(self.wrapped) 1507 if self._callback_excinfo: 1508 gpgme.gpg_raise_callback_exception(self) 1509 self.wrapped = None 1510 self._free_datacbs() 1511 1512 # Implement the context manager protocol. 1513 def __enter__(self): 1514 return self 1515 1516 def __exit__(self, type, value, tb): 1517 self.__del__() 1518 1519 def _free_datacbs(self): 1520 self._data_cbs = None 1521 1522 def new(self): 1523 tmp = gpgme.new_gpgme_data_t_p() 1524 errorcheck(gpgme.gpgme_data_new(tmp)) 1525 self.wrapped = gpgme.gpgme_data_t_p_value(tmp) 1526 gpgme.delete_gpgme_data_t_p(tmp) 1527 1528 def new_from_mem(self, string, copy=True): 1529 tmp = gpgme.new_gpgme_data_t_p() 1530 errorcheck( 1531 gpgme.gpgme_data_new_from_mem(tmp, string, len(string), copy)) 1532 self.wrapped = gpgme.gpgme_data_t_p_value(tmp) 1533 gpgme.delete_gpgme_data_t_p(tmp) 1534 1535 def new_from_file(self, filename, copy=True): 1536 tmp = gpgme.new_gpgme_data_t_p() 1537 try: 1538 errorcheck(gpgme.gpgme_data_new_from_file(tmp, filename, copy)) 1539 except errors.GPGMEError as e: 1540 if e.getcode() == errors.INV_VALUE and not copy: 1541 raise ValueError("delayed reads are not yet supported") 1542 else: 1543 raise e 1544 self.wrapped = gpgme.gpgme_data_t_p_value(tmp) 1545 gpgme.delete_gpgme_data_t_p(tmp) 1546 1547 def new_from_cbs(self, read_cb, write_cb, seek_cb, release_cb, hook=None): 1548 tmp = gpgme.new_gpgme_data_t_p() 1549 if hook is not None: 1550 hookdata = (weakref.ref(self), read_cb, write_cb, seek_cb, 1551 release_cb, hook) 1552 else: 1553 hookdata = (weakref.ref(self), read_cb, write_cb, seek_cb, 1554 release_cb) 1555 gpgme.gpg_data_new_from_cbs(self, hookdata, tmp) 1556 self.wrapped = gpgme.gpgme_data_t_p_value(tmp) 1557 gpgme.delete_gpgme_data_t_p(tmp) 1558 1559 def new_from_filepart(self, file, offset, length): 1560 """This wraps the GPGME gpgme_data_new_from_filepart() function. 1561 The argument "file" may be: 1562 1563 * a string specifying a file name, or 1564 * a file-like object supporting the fileno() and the mode attribute. 1565 1566 """ 1567 1568 tmp = gpgme.new_gpgme_data_t_p() 1569 filename = None 1570 fp = None 1571 1572 if util.is_a_string(file): 1573 filename = file 1574 else: 1575 fp = gpgme.fdopen(file.fileno(), file.mode) 1576 if fp is None: 1577 raise ValueError("Failed to open file from %s arg %s" % (str( 1578 type(file)), str(file))) 1579 1580 errorcheck( 1581 gpgme.gpgme_data_new_from_filepart(tmp, filename, fp, offset, 1582 length)) 1583 self.wrapped = gpgme.gpgme_data_t_p_value(tmp) 1584 gpgme.delete_gpgme_data_t_p(tmp) 1585 1586 def new_from_fd(self, file): 1587 """This wraps the GPGME gpgme_data_new_from_fd() function. The 1588 argument "file" must be a file-like object, supporting the 1589 fileno() method. 1590 1591 """ 1592 tmp = gpgme.new_gpgme_data_t_p() 1593 errorcheck(gpgme.gpgme_data_new_from_fd(tmp, file.fileno())) 1594 self.wrapped = gpgme.gpgme_data_t_p_value(tmp) 1595 gpgme.delete_gpgme_data_t_p(tmp) 1596 1597 def new_from_stream(self, file): 1598 """This wrap around gpgme_data_new_from_stream is an alias for 1599 new_from_fd() method since in python there's no difference 1600 between file stream and file descriptor.""" 1601 self.new_from_fd(file) 1602 1603 def new_from_estream(self, file): 1604 """This wrap around gpgme_data_new_from_estream is an alias for 1605 new_from_fd() method since in python there's no difference 1606 between file stream and file descriptor, but using fd broke.""" 1607 self.new_from_stream(file) 1608 1609 def write(self, buffer): 1610 """Write buffer given as string or bytes. 1611 1612 If a string is given, it is implicitly encoded using UTF-8.""" 1613 written = gpgme.gpgme_data_write(self.wrapped, buffer) 1614 if written < 0: 1615 if self._callback_excinfo: 1616 gpgme.gpg_raise_callback_exception(self) 1617 else: 1618 raise GPGMEError.fromSyserror() 1619 return written 1620 1621 def read(self, size=-1): 1622 """Read at most size bytes, returned as bytes. 1623 1624 If the size argument is negative or omitted, read until EOF is reached. 1625 1626 Returns the data read, or the empty string if there was no data 1627 to read before EOF was reached.""" 1628 1629 if size == 0: 1630 return '' 1631 1632 if size > 0: 1633 try: 1634 result = gpgme.gpgme_data_read(self.wrapped, size) 1635 except: 1636 if self._callback_excinfo: 1637 gpgme.gpg_raise_callback_exception(self) 1638 else: 1639 raise 1640 return result 1641 else: 1642 chunks = [] 1643 while True: 1644 try: 1645 result = gpgme.gpgme_data_read(self.wrapped, 4096) 1646 except: 1647 if self._callback_excinfo: 1648 gpgme.gpg_raise_callback_exception(self) 1649 else: 1650 raise 1651 if len(result) == 0: 1652 break 1653 chunks.append(result) 1654 return b''.join(chunks) 1655 1656 1657def pubkey_algo_string(subkey): 1658 """Return short algorithm string 1659 1660 Return a public key algorithm string (e.g. "rsa2048") for a given 1661 SUBKEY. 1662 1663 Returns: 1664 algo - a string 1665 1666 """ 1667 return gpgme.gpgme_pubkey_algo_string(subkey) 1668 1669 1670def pubkey_algo_name(algo): 1671 """Return name of public key algorithm 1672 1673 Return the name of the public key algorithm for a given numeric 1674 algorithm id ALGO (cf. RFC4880). 1675 1676 Returns: 1677 algo - a string 1678 1679 """ 1680 return gpgme.gpgme_pubkey_algo_name(algo) 1681 1682 1683def hash_algo_name(algo): 1684 """Return name of hash algorithm 1685 1686 Return the name of the hash algorithm for a given numeric 1687 algorithm id ALGO (cf. RFC4880). 1688 1689 Returns: 1690 algo - a string 1691 1692 """ 1693 return gpgme.gpgme_hash_algo_name(algo) 1694 1695 1696def get_protocol_name(proto): 1697 """Get protocol description 1698 1699 Get the string describing protocol PROTO. 1700 1701 Returns: 1702 proto - a string 1703 1704 """ 1705 return gpgme.gpgme_get_protocol_name(proto) 1706 1707 1708def addrspec_from_uid(uid): 1709 """Return the address spec 1710 1711 Return the addr-spec (cf. RFC2822 section 4.3) from a user id UID. 1712 1713 Returns: 1714 addr_spec - a string 1715 1716 """ 1717 return gpgme.gpgme_addrspec_from_uid(uid) 1718 1719 1720def check_version(version=None): 1721 return gpgme.gpgme_check_version(version) 1722 1723 1724# check_version also makes sure that several subsystems are properly 1725# initialized, and it must be run at least once before invoking any 1726# other function. We do it here so that the user does not have to do 1727# it unless she really wants to check for a certain version. 1728check_version() 1729 1730 1731def engine_check_version(proto): 1732 try: 1733 errorcheck(gpgme.gpgme_engine_check_version(proto)) 1734 return True 1735 except errors.GPGMEError: 1736 return False 1737 1738 1739def get_engine_info(): 1740 ptr = gpgme.new_gpgme_engine_info_t_p() 1741 try: 1742 errorcheck(gpgme.gpgme_get_engine_info(ptr)) 1743 info = gpgme.gpgme_engine_info_t_p_value(ptr) 1744 except errors.GPGMEError: 1745 info = None 1746 gpgme.delete_gpgme_engine_info_t_p(ptr) 1747 return info 1748 1749 1750def set_engine_info(proto, file_name, home_dir=None): 1751 """Changes the default configuration of the crypto engine implementing 1752 the protocol 'proto'. 'file_name' is the file name of 1753 the executable program implementing this protocol. 'home_dir' is the 1754 directory name of the configuration directory (engine's default is 1755 used if omitted).""" 1756 errorcheck(gpgme.gpgme_set_engine_info(proto, file_name, home_dir)) 1757 1758 1759def set_locale(category, value): 1760 """Sets the default locale used by contexts""" 1761 errorcheck(gpgme.gpgme_set_locale(None, category, value)) 1762 1763 1764def wait(hang): 1765 """Wait for asynchronous call on any Context to finish. 1766 Wait forever if hang is True. 1767 1768 For finished anynch calls it returns a tuple (status, context): 1769 status - status return by asnynchronous call. 1770 context - context which caused this call to return. 1771 1772 Please read the GPGME manual of more information.""" 1773 ptr = gpgme.new_gpgme_error_t_p() 1774 context = gpgme.gpgme_wait(None, ptr, hang) 1775 status = gpgme.gpgme_error_t_p_value(ptr) 1776 gpgme.delete_gpgme_error_t_p(ptr) 1777 if context is None: 1778 errorcheck(status) 1779 else: 1780 context = Context(context) 1781 return (status, context) 1782