Ejemplo n.º 1
0
def detach_sign_with_pgp_key(file_to_sign_path, pgp_private_key_fingerprint, output_signature_path):
    """Does a detached sign of a given file using a given users private key.

    Parameters
    ----------
    file_to_sign_path : str
        Path to file to create a detached PGP signature for.

    pgp_private_key_fingerprint : str
        PGP private key fingerprint to sign the given file with.

    output_signature_path : str
        File path to put the detached signature in.

    Raises
    ------
    RuntimeError
        If error signing given file with given key.
    """
    try:
        sh.gpg( # pylint: disable=no-member
            '--armor',
            '--local-user',
            pgp_private_key_fingerprint,
            '--output',
            output_signature_path,
            '--detach-sign',
            file_to_sign_path
        )
    except sh.ErrorReturnCode as error:
        raise RuntimeError(
            f"Error performing detached signature of file ({file_to_sign_path})" \
            f" with PGP key ({pgp_private_key_fingerprint}): {error}"
        ) from error
Ejemplo n.º 2
0
 def install_gpg_key(self):
     # install private key
     gpg_private_key_path = os.path.join(
         os.path.dirname(__file__), 'files',
         'ploigos-step-runner-tests-private.asc')
     sh.gpg(  # pylint: disable=no-member
         '--import', gpg_private_key_path)
 def install_gpg_key(self):
     # install private key
     gpg_private_key_path = os.path.join(
         os.path.dirname(__file__), 'files',
         'tssc-python-package-tests-private.asc')
     sh.gpg(  # pylint: disable=no-member
         '--import', gpg_private_key_path)
 def delete_gpg_key(self):
     try:
         # uninstall private key
         sh.gpg(  # pylint: disable=no-member
             '--batch', '--pinentry-mode', 'loopback', '--yes',
             '--delete-secret-keys',
             SOPSIntegrationTestCase.TESTS_GPG_KEY_FINGERPRINT)
     except:
         # don't care if this fails really
         # could fail cuz the test uninstaleld it already
         pass
Ejemplo n.º 5
0
 def import_gpg_from_secret_env_var(self: object, env_var: str):
     gpg_home = helpers.NormalizeSubdir(self.get_gpg_home())()
     sys.stderr.write("GPG home:  {}\n".format(gpg_home))
     secret = self.env(env_var)
     sh.gpg("-v",
            "--batch",
            "--import",
            "-",
            _in=secret,
            _out=sys.stdout.buffer,
            _err=sys.stderr.buffer,
            _cwd=self.normalized_path)
Ejemplo n.º 6
0
def init():

    key_fingerprint = input("enter your key fingerprint")

    pub_key = gpg("--export", "--armor", key_fingerprint).stdout

    return {"public_key": pub_key, "key_fingerprint": key_fingerprint}
    def __import_pgp_key(
        pgp_private_key
    ):
        print("Import PGP private key to sign container image(s) with")
        try:
            # import the key

            # NOTE: GPG is weird in that it sends "none error" output to stderr even on success...
            #       so merge the stderr into stdout
            gpg_import_stdout_result = StringIO()
            gpg_import_stdout_callback = create_sh_redirect_to_multiple_streams_fn_callback([
                sys.stdout,
                gpg_import_stdout_result
            ])
            sh.gpg( # pylint: disable=no-member
                '--import',
                '--fingerprint',
                '--with-colons',
                '--import-options=import-show',
                _in=pgp_private_key,
                _out=gpg_import_stdout_callback,
                _err_to_out=True,
                _tee='out'
            )

            # get the fingerprint of the imported key
            #
            # NOTE: if more then one match just using first one...
            gpg_imported_pgp_private_key_fingerprints = re.findall(
                PodmanSign.GPG_IMPORT_FINGER_PRINT_REGEX,
                gpg_import_stdout_result.getvalue()
            )
            if len(gpg_imported_pgp_private_key_fingerprints) < 1:
                raise RuntimeError(
                    "Unexpected error getting PGP fingerprint for PGP key"
                    " to sign container image(s) with. See stdout and stderr for more info."
                )
            pgp_private_key_fingerprint = gpg_imported_pgp_private_key_fingerprints[0]

            print(
                "Imported PGP private key to sign container image(s) with: "
                f"fingerprint='{pgp_private_key_fingerprint}'"
            )
        except sh.ErrorReturnCode as error:
            raise RuntimeError(f"Unexpected error importing pgp private key: {error}") from error

        return pgp_private_key_fingerprint
Ejemplo n.º 8
0
def lock_key_slot(data, nonce):
    """encode the nonce with the public key"""

    data["enc_nonce"] = gpg("--encrypt",
                            "--armor",
                            "--recipient",
                            data["key_fingerprint"],
                            _in=nonce).stdout
Ejemplo n.º 9
0
def UPLOADPK(msg, address=None, host=None):
    res={}
    sender=collapse_rfc2231_value(msg['from'])
    m=sendere.match(sender)
    if m:
        res['sender_name'], res['sender_mail']=m.groups()
    else:
        res['sender_mail']=sender

    for mpart in msg.walk():
        ispgp=False
        part=to_message(mpart)
        if part.get_content_type()=='text/plain':
            # cut of preamble
            inblock=False
            lines=part.get_payload(decode=True).split('\n')
            i=0
            while i<len(lines):
                if not inblock:
                    if lines[i].strip()=='-----BEGIN PGP PUBLIC KEY BLOCK-----':
                        inblock=True
                        i+=2
                else:
                    if lines[i].strip()=='-----END PGP PUBLIC KEY BLOCK-----':
                        break
                i+=1
            if i<len(lines): ispgp=True
        elif part.get_content_type()=='application/pgp-keys':
            ispgp=True

        if ispgp:
            res=getpgpmeta(part.get_payload(decode=True))
            ret=gpg('--import',
                    _err_to_out=True,
                    _in=part.get_payload(decode=True))
            #logging.info(ret)
            modifiers={'fresh': False,
                       'abbreved': False,
                       'singleid': False,
                       'tidy': False,
                      }
            if res['datetime']>datetime.datetime.utcnow()-datetime.timedelta(days=10):
                modifiers['fresh']=True
            if len(res['ids'])<2:
                modifiers['singleid']=True
                if len(res['ids'][0]['email'].split('@')[0])<9:
                    modifiers['abbreved']=True
            if len([1 for x in res['sigs'] if x['st'] not in ['Positive certification of a User ID and Public Key packet', 'Subkey Binding Signature']])==0:
                modifiers['tidy']=True
            res['award']=award("You uploaded your public key.\n%s" % '\n'.join(["%s [%s]" % (k,'X' if v else ' ') for k,v in modifiers.items()]))
            #logging.info(res)
            welcome = view.respond(res, "pkuploaded.msg",
                           From=sendermail,
                           To=sender,
                           Subject="Welcome to the Privacy Challenge")
            view.attach(welcome, {}, "pubkey.asc", filename="my key", content_type="application/pgp-keys")
            relay.deliver(welcome)
Ejemplo n.º 10
0
    def __verify_sig(
        self,
        signature_file_path,
        artifact_file_path,
        private_key_fingerprint,
    ):
        # GPG_OUTPUT_REGEX = re.compile(r"using RSA key ([A-Za-z0-9]+).*(Good signature)", re.DOTALL)
        GPG_OUTPUT_REGEX = re.compile(f"using RSA key {private_key_fingerprint}.*Good signature", re.DOTALL)

        with TempDirectory() as temp_dir:
            signature_file_path=Path(signature_file_path)

            try:
                stdout_result = StringIO()
                stdout_callback = create_sh_redirect_to_multiple_streams_fn_callback([
                    sys.stdout,
                    stdout_result
                ])

                sh.gpg( 
                    '--verify', signature_file_path,
                    artifact_file_path,
                    _out=stdout_callback,
                    _err_to_out=True,
                    _tee='out'
                )

                verify_matches = re.findall(
                    GPG_OUTPUT_REGEX,
                    stdout_result.getvalue()
                )

                if len(verify_matches) < 1:
                    return False

            except sh.ErrorReturnCode as error:
                print(
                    f"Error verifying sig with gpg: {error}"
                )
                return False
            
            # if here, then verification successful
            return True
Ejemplo n.º 11
0
def export_pgp_public_key(pgp_private_key_fingerprint):
    """Exports a PGP public key given a private key fingerprint.

    Parameters
    ----------
    pgp_private_key_fingerprint : str
        PGP fingerprint.

    Returns
    -------
    str
        Public key from the private key fingerprint.

    Raises
    ------
    RuntimeError
        If error getting exported PGP public key
    """
    try:
        gpg_export_stdout_result = StringIO()

        sh.gpg( # pylint: disable=no-member
            '--armor',
            '--export',
            pgp_private_key_fingerprint,
            _out=gpg_export_stdout_result,
            _err_to_out=False,
            _tee='out'
        )

        gpg_public_key = gpg_export_stdout_result.getvalue()
    except sh.ErrorReturnCode as error:
        raise RuntimeError(
            f"Error exporting pgp public key: {error}"
        ) from error

    return gpg_public_key
Ejemplo n.º 12
0
    def test_create_rekor_entry(self):
        with TempDirectory() as temp_dir:
            parent_work_dir_path = os.path.join(temp_dir.path, 'working')
            signer_pgp_public_key_path = os.path.join(
                os.path.dirname(__file__), '../../helpers', 'files',
                'ploigos-step-runner-tests-public.key')

            try:
                sh.gpg('--import', signer_pgp_public_key_path)
            except sh.ErrorReturnCode_2:
                print("Key already imported.")

            # Write empty WorkflowResult to json file to use as Rekor extra data
            extra_data_file = os.path.join(parent_work_dir_path,
                                           'automated-governance',
                                           'automated-governance.json')
            extra_data_file_path = Path(extra_data_file)
            WorkflowResult().write_results_to_json_file(extra_data_file_path)

            sig_file = extra_data_file + '.asc'
            sig_file_path = Path(sig_file)
            sig_file_path.touch()

            result = Rekor.create_rekor_entry(
                signer_pgp_public_key_path=signer_pgp_public_key_path,
                signer_pgp_private_key_user=
                TestStepImplementerAutomatedGovernanceRekor.
                TEST_signer_pgp_private_key_user,
                extra_data_file=extra_data_file)
            self.assertEqual(
                result['spec']['data']['hash']['value'],
                TestStepImplementerAutomatedGovernanceRekor.
                TEST_REKOR_ENTRY['spec']['data']['hash']['value'])
            self.assertEqual(
                result['spec']['extraData'],
                TestStepImplementerAutomatedGovernanceRekor.
                TEST_REKOR_ENTRY['spec']['extraData'])
Ejemplo n.º 13
0
 def extract_gpg_keyid_from_secret_env_var(self: object, env_var: str):
     gpg_home = helpers.NormalizeSubdir(self.get_gpg_home())()
     sys.stderr.write("GPG home:  {}\n".format(gpg_home))
     secret = self.env(env_var)
     output = sh.gpg("-v",
                     "--batch",
                     "--import",
                     "--import-options=show-only",
                     "--dry-run",
                     "--with-colons",
                     "-",
                     _in=secret,
                     _cwd=self.normalized_path)
     for line in output:
         if line.startswith('sec'):
             fields = line.split(':')
             return fields[4]
Ejemplo n.º 14
0
def doxer(msg, mailid=None, host=None):
    try:
        keyid=get_val('dox-mailid',":%s" % mailid, second)[:-(len(mailid)+1)]
    except TypeError:
        #print >>sys.stderr, 'nomailid'
        return # no such mailid
    pwd=get_state(keyid, 'prod.pdf.pass')
    #logging.info("pwd "+pwd)
    if not pwd:
        add_state(keyid, 'prod.pdf.err',"I got a mail, but i was not aware of the password at that time. try to resend it after telling me the password please.")
        return
    err = None
    for mpart in msg.walk():
        part=to_message(mpart)
        #if part.get_content_maintype() == 'multipart' or len(part.get_payload(decode=True)) < 268125:
        if part.get_content_maintype() == 'multipart':
            #print >>sys.stderr, 'skip', len(part.get_payload(decode=True) or ''), part.get_content_maintype()
            continue
        size = len(part.get_payload(decode=True))
        if (size < 200000 or size > 310000):
            continue
        hash=hashlib.sha256()
        def hupdate(data): # workaround for http://bugs.python.org/issue17481
            hash.update(data)
        ret=gpg('-d',
                '--passphrase', pwd,
                _ok_code=[0,2],
                _in=part.get_payload(decode=True),
                _out=hupdate)
        if ret.exit_code!=0:
            add_state(keyid, 'prod.pdf.err',"got a mail, but gpg had problems, try fixing the problem and resend the mail. gpg said this\n"+err)
            break
        #logging.info('ret '+str(ret))
        #logging.info('stderr '+ret.stderr)
        err=str(ret.stderr) # for flushing the process?
        #print >>sys.stderr, 'err', err
        if hash.hexdigest() == '658be96015645fe1d646fd167c1ac3bd372360530191d574ace5870c5aeb132f':
            add_state(keyid, 'prod.pdf.done','1')
            break
        else:
            add_state(keyid, 'prod.pdf.err',"got a mail, but it wasn't quite what i expected, so i dropped it.")
            break
    else:
        add_state(keyid, 'prod.pdf.err',"got a mail, but there was nothing found that looked like a reasonably sized pgp payload")
Ejemplo n.º 15
0
def import_pgp_key(pgp_private_key):
    """Imports a PGP key.

    Parameters
    ----------
    pgp_private_key : str
        PGP key to import.

    Returns
    -------
    str
        Fingerprint of the imported PGP key.

    Raises
    ------
    RuntimeError
        If error getting PGP fingerprint for imported PGP key
        If error importing PGP key.
    """
    # Example input to match on:
    #   sec:-:3072:1:CF4AC14A3D109637:1601483310:1664555310::-:::scESC::::::23::0:
    #   fpr:::::::::DD7208BA0A6359F65B906B29CF4AC14A3D109637:
    #   grp:::::::::A483EE079EC1D58A954E3AAF3BCC61EDD7596BF0:
    gpg_regex = re.compile(r"^fpr:+([^:]+):$", re.MULTILINE)

    print("Import PGP private key to sign artifacts with")
    try:
        # import the key

        # NOTE: GPG is weird in that it sends "none error" output to stderr even on success...
        #       so merge the stderr into stdout
        gpg_import_stdout_result = StringIO()
        gpg_import_stdout_callback = create_sh_redirect_to_multiple_streams_fn_callback([
            sys.stdout,
            gpg_import_stdout_result
        ])
        sh.gpg( # pylint: disable=no-member
            '--import',
            '--fingerprint',
            '--with-colons',
            '--import-options=import-show',
            _in=pgp_private_key,
            _out=gpg_import_stdout_callback,
            _err_to_out=True,
            _tee='out'
        )

        # get the fingerprint of the imported key
        #
        # NOTE: if more then one match just using first one...
        gpg_imported_pgp_private_key_fingerprints = re.findall(
            gpg_regex,
            gpg_import_stdout_result.getvalue()
        )
        if len(gpg_imported_pgp_private_key_fingerprints) < 1:
            raise RuntimeError(
                "Error getting PGP fingerprint for PGP key"
                " to sign container image(s) with. See stdout and stderr for more info."
            )
        pgp_private_key_fingerprint = gpg_imported_pgp_private_key_fingerprints[0]

        print(
            "Imported PGP private key to sign artifacts with: "
            f"fingerprint='{pgp_private_key_fingerprint}'"
        )
    except sh.ErrorReturnCode as error:
        raise RuntimeError(
            f"Error importing pgp private key: {error}"
        ) from error

    return pgp_private_key_fingerprint
Ejemplo n.º 16
0
def award(text):
    return gpg('--clearsign',
            '--armor',
            '--default-key',
            sendermail,
            _in="Achievement unlocked %s\n%s" % (text, datetime.datetime.utcnow().isoformat()))
Ejemplo n.º 17
0
def otrfp(msg, address=None, host=None):
    sender=collapse_rfc2231_value(msg['from'])
    m=sendere.match(sender)
    res={}
    if m:
        res['sender_name'], res['sender_mail']=m.groups()
    else:
        res['sender_mail']=sender

    for mpart in msg.walk():
        part=to_message(mpart)
        # cut of preamble
        inblock=False
        lines=part.get_payload(decode=True).split('\n')
        i=0
        #logging.info(lines)
        while i<len(lines):
            if not inblock:
                if lines[i].strip()=='-----BEGIN PGP SIGNED MESSAGE-----' or lines[i].strip()=='-----BEGIN PGP MESSAGE-----':
                    inblock=True
                    i+=2
            else:
                if lines[i].strip()=='-----END PGP SIGNATURE-----' or lines[i].strip()=='-----END PGP MESSAGE-----':
                    break
            i+=1
        #logging.info(i)
        if i<len(lines):
            res.update(getpgpmeta(part.get_payload(decode=True)))
            ret=gpg('-d',
                    _ok_code=[0,2],
                    _in=part.get_payload(decode=True))
            #logging.info('ret '+str(ret))
            #logging.info('stderr '+ret.stderr)
            res['msg']='\n'.join(["> %s" % x for x in ret.stdout.split('\n')])
            # extra points,
            #   - no named recipient
            #   - signed
            #logging.info(res['keys'])
            modifiers={'sekrit': False, 'signed': False}
            if len([x for x in res['keys'] if x['key_id']!="0000000000000000"])==0:
                modifiers['sekrit']=True
            else: 
                logging.warn([x for x in res['keys'] if x['key_id']!="0000000000000000"])
            signed={}
            for line in ret.stderr.split('\n'):
                if line.startswith('gpg: Signature made '):
                    # gpg: Signature made Fri 11 May 2012 04:43:04 PM CEST using RSA key ID XXXXXX
                    m=signed1re.match(line)
                    if m:
                        #logging.info(m.groups())
                        signed['date']=dparse(str(m.group(1)))
                        signed['algo']=m.group(2)
                        signed['key_id']=m.group(3)
                elif line.startswith('gpg: Good signature from '):
                    # gpg: Good signature from "name <mail>"
                    m=signed2re.match(line)
                    if m:
                        #logging.info(m.groups())
                        signed['name']=m.group(1)
                        signed['mail']=m.group(2)
                    modifiers['signed']=True
            if not signed:
                plssign = view.respond(res, "plssign.msg",
                                       From=sendermail,
                                       To=sender,
                                       Subject="OTR fingerprint help")
                relay.deliver(plssign)
                continue
            res['signed']=signed
            res['award']=award("you bootstrapped OTR trust using PGP.\n%s" % '\n'.join(["%s [%s]" % (k,'X' if v else ' ') for k,v in modifiers.items()]))
            #logging.info(res)
            jid=None
            fp=None
            secret=None
            for line in to_message(from_string(ret.stdout)).get_payload(decode=True).split('\n'):
                if not line.strip(): continue
                if line=='-- ': break
                if jid and fp:
                    secret=line
                    break
                #logging.info("line "+line)
                m=otrfpre.match(line)
                if m:
                    #logging.info(m.groups())
                    jid, fp = m.group(1), m.group(2)
            if jid and fp:
                with FileLock('%s/otr/otr/%s.fpr' % (basepath, botjid)):
                    fr=open('%s/otr/otr/%s.fpr' % (basepath, botjid), 'r')
                    fw=open('%s/otr/otr/%s.fpr.new' % (basepath, botjid), 'w')
                    for line in fr:
                        #logging.info(line)
                        #logging.info("%s\t%s\tjabber\t%s" % (jid,
                        #                              botjid,
                        #                              fp.lower().replace(' ','')))
                        if line.startswith("%s\t%s\tjabber\t%s" % (jid,
                                                                   botjid,
                                                                   fp.lower().replace(' ',''))):
                            fw.write("%s\t%s\tjabber\t%s\ttrust\n" % (jid,
                                                                    botjid,
                                                                    fp.lower().replace(' ','')))
                        else:
                            fw.write(line)
                    fw.close()
                    fr.close()
                    os.unlink('%s/otr/otr/%s.fpr' % (basepath, botjid))
                    shutil.move('%s/otr/otr/%s.fpr.new' % (basepath, botjid),
                                '%s/otr/otr/%s.fpr' % (basepath, botjid))
            if secret:
                fs=open('%s/otr/otr/%s.s' % (basepath, jid), 'w')
                fs.write("%s %s" % (signed['key_id'], secret))
                fs.close()
            welcome = view.respond(res, "otrtrust.msg",
                           From=sendermail,
                           To=sender,
                           Subject="OTR fingerprint received")
            relay.deliver(welcome)
Ejemplo n.º 18
0
 def get_gpg_home(self: object):
     gpg_help = str(sh.gpg("--help", _tty_out=False))
     match = self.gpg_home_regex.search(gpg_help)
     return match.group(1)
Ejemplo n.º 19
0
def init_auth(data):
    pub_key = gpg("--export", "--armor", data["key_fingerprint"]).stdout

    data["public_key"] = pub_key
Ejemplo n.º 20
0
def unlock_key_slot(data, unlock_data):
    return gpg("--decrypt", _in=data["enc_nonce"]).stdout
Ejemplo n.º 21
0
def DECODER(msg, address=None, host=None):
    sender=collapse_rfc2231_value(msg['from'])
    m=sendere.match(sender)
    res={}
    if m:
        res['sender_name'], res['sender_mail']=m.groups()
    else:
        res['sender_mail']=sender

    for mpart in msg.walk():
        part=to_message(mpart)
        # cut of preamble
        inblock=False
        lines=part.get_payload(decode=True).split('\n')
        i=0
        #logging.info(lines)
        while i<len(lines):
            if not inblock:
                if lines[i].strip()=='-----BEGIN PGP MESSAGE-----':
                    inblock=True
                    i+=2
            else:
                if lines[i].strip()=='-----END PGP MESSAGE-----':
                    break
            i+=1
        #logging.info(i)
        if i<len(lines):
            res.update(getpgpmeta(part.get_payload(decode=True)))
            ret=gpg('-d',
                    _ok_code=[0,2],
                    _in=part.get_payload(decode=True))
            #logging.info('ret '+str(ret))
            #logging.info('stderr '+ret.stderr)
            res['msg']='\n'.join(["> %s" % x for x in ret.stdout.split('\n')])
            # extra points,
            #   - no named recipient
            #   - signed
            modifiers={'sekrit': False, 'signed': False}
            #logging.info(res['keys'])
            if len([x for x in res['keys'] if x['key_id']!="0000000000000000"])==0:
                modifiers['sekrit']=True
            signed={}
            for line in ret.stderr.split('\n'):
                if line.startswith('gpg: Signature made '):
                    # gpg: Signature made Fri 11 May 2012 04:43:04 PM CEST using RSA key ID XXXXXX
                    m=signed1re.match(line)
                    if m:
                        #logging.info(m.groups())
                        signed['date']=dparse(str(m.group(1)))
                        signed['algo']=m.group(2)
                        signed['key_id']=m.group(3)
                elif line.startswith('gpg: Good signature from '):
                    # gpg: Good signature from "name <mail>"
                    m=signed2re.match(line)
                    if m:
                        #logging.info(m.groups())
                        signed['name']=m.group(1)
                        signed['mail']=m.group(2)
                    modifiers['signed']=True
            if signed: res['signed']=signed
            res['award']=award("You sent an encrypted mail.\n%s" % '\n'.join(["%s [%s]" % (k,'X' if v else ' ') for k,v in modifiers.items()]))
            #logging.info(res)
            welcome = view.respond(res, "pgpmail.msg",
                           From=sendermail,
                           To=sender,
                           Subject="Encrypted mail received")
            relay.deliver(welcome)
Ejemplo n.º 22
0
def unlock_key_slot(data, enc_nonce):

    return gpg("--decrypt", _in=enc_nonce).stdout
Ejemplo n.º 23
0
	def verify_sig(self, path, sig):
		try:
			gpg("--batch", "--no-tty", "--verify", sig, path)
			return True
		except:
			return False