def verify_passphrase(self): '''Verify a passpharse gotten from get_passpharse().''' magic_string = 'test1234' filename = self._tmpfile_path('pius_tmp') filename_enc = self._tmpfile_path('pius_tmp.gpg') filename_dec = self._tmpfile_path('pius_tmp2') clean_files([filename, filename_enc, filename_dec]) tfile = open(filename, 'w') tfile.write(magic_string) tfile.close() cmd = [self.gpg] + self.gpg_base_opts + self.gpg_quiet_opts + [ '--no-armor', '--always-trust', '-r', self.signer, '-e', filename, ] logcmd(cmd) subprocess.call(cmd, stdout=self.null, stderr=self.null, close_fds=True) cmd = [self.gpg] + self.gpg_base_opts + self.gpg_quiet_opts + \ self.gpg_fd_opts + [ '--output', filename_dec, '-d', filename_enc, ] logcmd(cmd) gpg = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=self.null, close_fds=True) debug('Sending passphrase') gpg.stdin.write('%s\n' % self.passphrase) line = gpg.stdout.read() debug('wait()ing on gpg') retval = gpg.wait() if retval != 0: debug('gpg decrypt return code %s' % retval) clean_files([filename, filename_enc, filename_dec]) return False if not os.path.exists(filename_dec): debug('Resulting file %s not found' % filename_dec) clean_files([filename, filename_enc, filename_dec]) return False tfile = open(filename_dec, 'r') line = tfile.readline() tfile.close() clean_files([filename, filename_enc, filename_dec]) if line == magic_string: return True debug('File does not contain magic string') return False
def verify_passphrase(self): '''Verify a passpharse gotten from get_passpharse().''' magic_string = 'test1234' filename = self._tmpfile_path('pius_tmp') filename_enc = self._tmpfile_path('pius_tmp.gpg') filename_dec = self._tmpfile_path('pius_tmp2') clean_files([filename, filename_enc, filename_dec]) tfile = open(filename, 'w') tfile.write(magic_string) tfile.close() cmd = [self.gpg] + self.gpg_base_opts + self.gpg_quiet_opts + [ '--no-armor', '--always-trust', '-r', self.signer, '-e', filename, ] debug(cmd) subprocess.call(cmd, stdout=self.null, stderr=self.null, close_fds=True) cmd = [self.gpg] + self.gpg_base_opts + self.gpg_quiet_opts + \ self.gpg_fd_opts + [ '--output', filename_dec, '-d', filename_enc, ] debug(cmd) gpg = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=self.null, close_fds=True) debug('Sending passphrase') gpg.stdin.write('%s\n' % self.passphrase) line = gpg.stdout.read() debug('wait()ing on gpg') retval = gpg.wait() if retval != 0: debug('gpg decrypt return code %s' % retval) clean_files([filename, filename_enc, filename_dec]) return False if not os.path.exists(filename_dec): debug('Resulting file %s not found' % filename_dec) clean_files([filename, filename_enc, filename_dec]) return False tfile = open(filename_dec, 'r') line = tfile.readline() tfile.close() clean_files([filename, filename_enc, filename_dec]) if line == magic_string: return True debug('File does not contain magic string') return False
def clean_clean_key(self, key): '''Delete the "clean" unsigned key which we exported temporarily.''' # Remove the temporary exports of the public keys paths = [self._tmpfile_path('%s.asc' % x) for x in [self.signer, key]] clean_files(paths)
def cleanup(self): '''Cleanup all our temp files.''' clean_files([self.tmp_keyring, ('%s~' % self.tmp_keyring)])
def _generate_pgp_mime_email(self, signer, email, keyid, filename, psigner): '''Generates the PGP/Mime body. The message headers MUST be added by the caller.''' msg = email_mime_multipart.MIMEMultipart( 'encrypted', micalg="pgp-sha1", protocol="application/pgp-encrypted") msg.preamble = 'This is an OpenPGP/MIME signed message (RFC 2440 and 3156)' # The signed part of the message. This is a MIME encapsulation # of the main body of the message *and* the key. encrypted_body = email_mime_multipart.MIMEMultipart('mixed') # First part of signed body textpart = email_mime_base.MIMEBase('text', 'plain', charset="ISO-8859-1") textpart.add_header('Content-Transfer-Encoding', 'quoted-printable') textpart.__delitem__('MIME-Version') textpart.set_payload( quoprimime.encode(self._get_email_body(signer, keyid, email))) encrypted_body.attach(textpart) # The second part of the signed body file_base = os.path.basename(filename) attached_sig = email_mime_base.MIMEBase('application', 'pgp-keys', name='%s' % file_base) attached_sig.add_header('Content-Disposition', 'inline', filename='%s' % file_base) attached_sig.__delitem__('MIME-Version') # # We USED to make this quoted-printable, but people with non-PGP-aware MUAs # were decrypting the body manually, and then trying to import the resulting # MIME message which was QP-encoded... so if there was an equals-sign in the # message, it would actually be an '=3D' and thus fail the import. # # RFC2015 strongly suggests using QP for any signed data to prevent MTAs # from messing with it... however, since this gets encrypted, this data is # never available for an MTA to mess with, so this ... should be safe, and # allows both methods of decrypting and importing the key. # # Side-note, if we ever turn to QP, be sure to use quoprimime.encode to # encode the payload. # attached_sig.set_payload(open(filename, 'r').read()) encrypted_body.attach(attached_sig) encrypted_body.__delitem__('MIME-Version') # Encryt/Sign the MIME body. # # We have to conver to DOS newlines since that's what happens # to mail anyway and we don't want verification to fail dos_body = encrypted_body.as_string().replace('\n', '\r\n') tmpfile = os.path.join(self.tmp_dir, 'pius_tmp') signed_tmpfile = '%s.asc' % tmpfile clean_files([tmpfile, signed_tmpfile]) tfile = open(tmpfile, 'w') tfile.write(dos_body) tfile.close() try: psigner.encrypt_and_sign_file(tmpfile, signed_tmpfile, keyid) except EncryptionKeyError: raise EncryptionKeyError # Create the version part of the PGP/Mime encryption pgp_ver = email_mime_base.MIMEBase('application', 'pgp-encrypted') pgp_ver.add_header('Content-Description', 'PGP/MIME version identification') pgp_ver.__delitem__('MIME-Version') pgp_ver.set_payload('Version: 1\n') # Create the big sign-encrypted body part pgp_data = email_mime_base.MIMEBase('application', 'octet-stream', name='encrypted.asc') pgp_data.add_header('Content-Description', 'OpenPGP encrypted message') pgp_data.add_header('Content-Disposition', 'inline', filename='encrypted.asc') pgp_data.__delitem__('MIME-Version') pgp_data.set_payload(open(signed_tmpfile, 'r').read()) # This is the actual encrypt-signed PGP/Mime message msg.attach(pgp_ver) msg.attach(pgp_data) clean_files([tmpfile, signed_tmpfile]) return msg
def clean_clean_key(self, key): '''Delete the "clean" unsigned key which we exported temporarily.''' path = self._tmpfile_path('%s.asc' % key) clean_files([path])
def _generate_pgp_mime_email(self, signer, email, keyid, filename, psigner): """Generates the PGP/Mime body. The message headers MUST be added by the caller.""" msg = MIMEMultipart.MIMEMultipart("encrypted", micalg="pgp-sha1", protocol="application/pgp-encrypted") msg.preamble = "This is an OpenPGP/MIME signed message (RFC 2440 and 3156)" # The signed part of the message. This is a MIME encapsulation # of the main body of the message *and* the key. encrypted_body = MIMEMultipart.MIMEMultipart("mixed") # First part of signed body textpart = MIMEBase.MIMEBase("text", "plain", charset="ISO-8859-1") textpart.add_header("Content-Transfer-Encoding", "quoted-printable") textpart.__delitem__("MIME-Version") textpart.set_payload(quopriMIME.encode(self._get_email_body(signer, keyid, email))) encrypted_body.attach(textpart) # The second part of the signed body file_base = os.path.basename(filename) attached_sig = MIMEBase.MIMEBase("application", "pgp-keys", name="%s" % file_base) attached_sig.add_header("Content-Disposition", "inline", filename="%s" % file_base) attached_sig.__delitem__("MIME-Version") # # We USED to make this quoted-printable, but people with non-PGP-aware MUAs # were decrypting the body manually, and then trying to import the resulting # MIME message which was QP-encoded... so if there was an equals-sign in the # message, it would actually be an '=3D' and thus fail the import. # # RFC2015 strongly suggests using QP for any signed data to prevent MTAs # from messing with it... however, since this gets encrypted, this data is # never available for an MTA to mess with, so this ... should be safe, and # allows both methods of decrypting and importing the key. # # Side-note, if we ever turn to QP, be sure to use quopriMIME.encode to # encode the payload. # attached_sig.set_payload(open(filename, "r").read()) encrypted_body.attach(attached_sig) encrypted_body.__delitem__("MIME-Version") # Encryt/Sign the MIME body. # # We have to conver to DOS newlines since that's what happens # to mail anyway and we don't want verification to fail dos_body = encrypted_body.as_string().replace("\n", "\r\n") tmpfile = os.path.join(self.tmp_dir, "pius_tmp") signed_tmpfile = "%s.asc" % tmpfile clean_files([tmpfile, signed_tmpfile]) tfile = open(tmpfile, "w") tfile.write(dos_body) tfile.close() try: psigner.encrypt_and_sign_file(tmpfile, signed_tmpfile, keyid) except EncryptionKeyError: raise EncryptionKeyError # Create the version part of the PGP/Mime encryption pgp_ver = MIMEBase.MIMEBase("application", "pgp-encrypted") pgp_ver.add_header("Content-Description", "PGP/MIME version identification") pgp_ver.__delitem__("MIME-Version") pgp_ver.set_payload("Version: 1\n") # Create the big sign-encrypted body part pgp_data = MIMEBase.MIMEBase("application", "octet-stream", name="encrypted.asc") pgp_data.add_header("Content-Description", "OpenPGP encrypted message") pgp_data.add_header("Content-Disposition", "inline", filename="encrypted.asc") pgp_data.__delitem__("MIME-Version") pgp_data.set_payload(open(signed_tmpfile, "r").read()) # This is the actual encrypt-signed PGP/Mime message msg.attach(pgp_ver) msg.attach(pgp_data) clean_files([tmpfile, signed_tmpfile]) return msg