def encrypt(message, recipients, gpg, **kwargs): r"""Encrypt a ``Message``, returning the encrypted version. using gpg.encrypt() others, mostly, taken from W. T. King """ flattenedMsg = _flatten(message) eResult = gpg.encrypt(flattenedMsg, recipients, **kwargs) assert eResult.ok == True, (recipients, kwargs) encrypted = eResult.data enc = _MIMEApplication( _data=encrypted, _subtype='octet-stream; name="encrypted.asc"', _encoder=_encode_7or8bit) enc['Content-Description'] = 'OpenPGP encrypted message' enc.set_charset('us-ascii') control = _MIMEApplication( _data='Version: 1\n', _subtype='pgp-encrypted', _encoder=_encode_7or8bit) control.set_charset('us-ascii') msg = _MIMEMultipart( 'encrypted', micalg='pgp-sha1', protocol='application/pgp-encrypted') msg.attach(control) msg.attach(enc) msg['Content-Disposition'] = 'inline' return msg
def load_attachment(filename, encoding='us-ascii'): mimetype,content_encoding = _mimetypes.guess_type(filename) if mimetype is None or content_encoding is not None: mimetype = 'application/octet-stream' maintype,subtype = mimetype.split('/', 1) _pgp_mime.LOG.info('loading attachment {} as {} ({})'.format( filename, mimetype, content_encoding)) if maintype == 'text': text = read_file(filename=filename, encoding=encoding) attachment = _pgp_mime.encodedMIMEText(text) del attachment['content-disposition'] else: data = open(filename, 'rb').read() if maintype == 'application': attachment = _MIMEApplication(data, subtype) elif maintype == 'audio': attachment = _MIMEAudio(data) elif maintype == 'image': attachment = _MIMEImage(data) else: attachment = _MIMENonMultipary(maintype, subtype) attachment.set_payload(data, _encode_base64) attachment.add_header( 'Content-Disposition', 'attachment', filename=filename) return attachment
def sign(message, gpg, **kwargs): r"""Sign a ``Message``, returning the signed version. using gpg.sign() others, mostly, taken from W. T. King """ # should use replace, otherwise it does NOT work # READ ---- page 5 of RFC 3156 flattenedMsg = _flatten(message).replace('\n', '\r\n') assert kwargs signature = str( gpg.sign(flattenedMsg, detach=True, **kwargs) ) assert signature sig = _MIMEApplication( _data=signature, _subtype='pgp-signature; name="signature.asc"', _encoder=_encode_7or8bit) sig['Content-Description'] = 'OpenPGP digital signature' sig.set_charset('us-ascii') msg = _MIMEMultipart( 'signed', micalg='pgp-sha1', protocol='application/pgp-signature') msg.attach(message) msg.attach(sig) msg['Content-Disposition'] = 'inline' return msg
def load_attachment(filename, encoding='us-ascii'): mimetype, content_encoding = _mimetypes.guess_type(filename) if mimetype is None or content_encoding is not None: mimetype = 'application/octet-stream' maintype, subtype = mimetype.split('/', 1) _pgp_mime.LOG.info('loading attachment {} as {} ({})'.format( filename, mimetype, content_encoding)) if maintype == 'text': text = read_file(filename=filename, encoding=encoding) attachment = _pgp_mime.encodedMIMEText(text) del attachment['content-disposition'] else: data = open(filename, 'rb').read() if maintype == 'application': attachment = _MIMEApplication(data, subtype) elif maintype == 'audio': attachment = _MIMEAudio(data) elif maintype == 'image': attachment = _MIMEImage(data) else: attachment = _MIMENonMultipary(maintype, subtype) attachment.set_payload(data, _encode_base64) attachment.add_header('Content-Disposition', 'attachment', filename=filename) return attachment
def sign(message, **kwargs): r"""Sign a ``Message``, returning the signed version. multipart/signed +-> text/plain (body) +-> application/pgp-signature (signature) >>> from pgp_mime.email import encodedMIMEText >>> message = encodedMIMEText('Hi\nBye') >>> signed = sign(message, signers=['*****@*****.**']) >>> signed.set_boundary('boundsep') >>> print(signed.as_string().replace( ... 'micalg="pgp-sha1"; protocol="application/pgp-signature"', ... 'protocol="application/pgp-signature"; micalg="pgp-sha1"')) ... # doctest: +ELLIPSIS, +REPORT_UDIFF Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg="pgp-sha1"; boundary="boundsep" MIME-Version: 1.0 Content-Disposition: inline <BLANKLINE> --boundsep Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline <BLANKLINE> Hi Bye --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Description: OpenPGP digital signature Content-Type: application/pgp-signature; name="signature.asc"; charset="us-ascii" <BLANKLINE> -----BEGIN PGP SIGNATURE----- Version: GnuPG... -----END PGP SIGNATURE----- <BLANKLINE> --boundsep-- >>> from email.mime.multipart import MIMEMultipart >>> message = MIMEMultipart() >>> message.attach(encodedMIMEText('Part A')) >>> message.attach(encodedMIMEText('Part B')) >>> signed = sign(message, signers=['*****@*****.**']) >>> signed.set_boundary('boundsep') >>> print(signed.as_string().replace( ... 'micalg="pgp-sha1"; protocol="application/pgp-signature"', ... 'protocol="application/pgp-signature"; micalg="pgp-sha1"')) ... # doctest: +ELLIPSIS, +REPORT_UDIFF Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg="pgp-sha1"; boundary="boundsep" MIME-Version: 1.0 Content-Disposition: inline <BLANKLINE> --boundsep Content-Type: multipart/mixed; boundary="===============...==" MIME-Version: 1.0 <BLANKLINE> --===============...== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline <BLANKLINE> Part A --===============...== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline <BLANKLINE> Part B --===============...==-- --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Description: OpenPGP digital signature Content-Type: application/pgp-signature; name="signature.asc"; charset="us-ascii" <BLANKLINE> -----BEGIN PGP SIGNATURE----- Version: GnuPG... -----END PGP SIGNATURE----- <BLANKLINE> --boundsep-- """ body = _flatten(message) signature = str(_sign_and_encrypt_bytes(data=body, **kwargs), 'us-ascii') sig = _MIMEApplication( _data=signature, _subtype='pgp-signature; name="signature.asc"', _encoder=_encode_7or8bit) sig['Content-Description'] = 'OpenPGP digital signature' sig.set_charset('us-ascii') msg = _MIMEMultipart( 'signed', micalg='pgp-sha1', protocol='application/pgp-signature') msg.attach(message) msg.attach(sig) msg['Content-Disposition'] = 'inline' return msg
def sign_and_encrypt(message, signers=None, recipients=None, **kwargs): r"""Sign and encrypt a ``Message``, returning the encrypted version. multipart/encrypted +-> application/pgp-encrypted (control information) +-> application/octet-stream (body) >>> from pgp_mime.email import encodedMIMEText >>> message = encodedMIMEText('Hi\nBye') >>> message['To'] = 'pgp-mime-test <*****@*****.**>' >>> encrypted = sign_and_encrypt( ... message, signers=['*****@*****.**'], always_trust=True) >>> encrypted.set_boundary('boundsep') >>> print(encrypted.as_string().replace( ... 'micalg="pgp-sha1"; protocol="application/pgp-encrypted"', ... 'protocol="application/pgp-encrypted"; micalg="pgp-sha1"')) ... # doctest: +ELLIPSIS, +REPORT_UDIFF Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; micalg="pgp-sha1"; boundary="boundsep" MIME-Version: 1.0 Content-Disposition: inline <BLANKLINE> --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: application/pgp-encrypted; charset="us-ascii" <BLANKLINE> Version: 1 <BLANKLINE> --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Description: OpenPGP encrypted message Content-Type: application/octet-stream; name="encrypted.asc"; charset="us-ascii" <BLANKLINE> -----BEGIN PGP MESSAGE----- Version: GnuPG... -----END PGP MESSAGE----- <BLANKLINE> --boundsep-- >>> from email.mime.multipart import MIMEMultipart >>> message = MIMEMultipart() >>> message.attach(encodedMIMEText('Part A')) >>> message.attach(encodedMIMEText('Part B')) >>> encrypted = sign_and_encrypt( ... message, signers=['*****@*****.**'], ... recipients=['*****@*****.**'], always_trust=True) >>> encrypted.set_boundary('boundsep') >>> print(encrypted.as_string().replace( ... 'micalg="pgp-sha1"; protocol="application/pgp-encrypted"', ... 'protocol="application/pgp-encrypted"; micalg="pgp-sha1"')) ... # doctest: +ELLIPSIS, +REPORT_UDIFF Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; micalg="pgp-sha1"; boundary="boundsep" MIME-Version: 1.0 Content-Disposition: inline <BLANKLINE> --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: application/pgp-encrypted; charset="us-ascii" <BLANKLINE> Version: 1 <BLANKLINE> --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Description: OpenPGP encrypted message Content-Type: application/octet-stream; name="encrypted.asc"; charset="us-ascii" <BLANKLINE> -----BEGIN PGP MESSAGE----- Version: GnuPG... -----END PGP MESSAGE----- <BLANKLINE> --boundsep-- """ _strip_bcc(message=message) body = _flatten(message) if recipients is None: recipients = [email for name,email in _email_targets(message)] _LOG.debug('extracted encryption recipients: {}'.format(recipients)) encrypted = str( _sign_and_encrypt_bytes( data=body, signers=signers, recipients=recipients, **kwargs), 'us-ascii') enc = _MIMEApplication( _data=encrypted, _subtype='octet-stream; name="encrypted.asc"', _encoder=_encode_7or8bit) enc['Content-Description'] = 'OpenPGP encrypted message' enc.set_charset('us-ascii') control = _MIMEApplication( _data='Version: 1\n', _subtype='pgp-encrypted', _encoder=_encode_7or8bit) control.set_charset('us-ascii') msg = _MIMEMultipart( 'encrypted', micalg='pgp-sha1', protocol='application/pgp-encrypted') msg.attach(control) msg.attach(enc) msg['Content-Disposition'] = 'inline' return msg