예제 #1
0
def generate_keys(gpg: gnupg.GPG, company_name: str, targer_folder: str):
    company_path, public_file_name, secret_file_name = __get_absolut_filepath(
        company_name=company_name)

    configuration_kwargs = utils.get_configuratation(
        path=os.path.join(targer_folder, 'configuration'))
    os.makedirs(company_path, exist_ok=True)

    gpg_keys = gpg.gen_key_input(**configuration_kwargs.get('array'))
    key = gpg.gen_key(gpg_keys)

    ascii_armored_public_keys = gpg.export_keys(key.fingerprint)
    ascii_armored_private_keys = gpg.export_keys(
        key.fingerprint,
        secret=True,
        passphrase=configuration_kwargs.get('array')['passphrase'],
    )

    with open(public_file_name, 'w') as file:
        file.write(ascii_armored_public_keys)

        logger.info(f'Generate file to export to customer done')

    with open(secret_file_name, 'w') as file:
        file.write(ascii_armored_public_keys)
        file.write(ascii_armored_private_keys)

        logger.info(f'Generate file to use done')

    _clean_directory(path=settings.PROJECT_NAME)
예제 #2
0
def test_check_git_commits_ok():
    with TemporaryDirectory() as tmp_git_repo:
        gpg_tmp_home = os.path.join(tmp_git_repo, 'gpg_tmp_home')
        # Included in the repository to avoid problems with low entropy in CI
        # environments.
        #  input_data = gpg.gen_key_input(
        #      key_type='RSA',
        #      subkey_type='RSA',
        #      key_length=1024,
        #      subkey_length=1024,
        #      name_comment='This is only a test key who’s private key is publicly know. Don’t use this key for anything!1!',
        #      name_email='*****@*****.**',
        #      # Has already expired at the time of creation to ensure no one will ever use the key.
        #      expire_date='2012-12-24',  # Needs to be set to the 24 for the key to expire on 23.
        #      # Hm, Ok, gpg does not do that by default. `--faked-system-time`
        #      # could be used to force it but that would require cmd access.
        #      # https://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.html
        #      # "gpg: Invalid option "--faked-system-time"" :(
        #      # Only: gpg2 --batch --gen-key --debug=0 --faked-system-time '2342-05-23'
        #      # has been confirmed to work from current Debian Stretch.
        #      # Faking it manually anyway …
        #  )
        #  print(input_data)
        #  print(gpg.gen_key(input_data))

        shutil.copytree(debops_keyring_fake_gnupg_home, gpg_tmp_home)
        gpg = GPG(gnupghome=gpg_tmp_home)

        os.chmod(gpg_tmp_home, 0o700)
        for r, d, f in os.walk(gpg_tmp_home):
            os.chmod(r, 0o700)
        gpg_key_fingerprint = gpg.list_keys()[0]['fingerprint']
        gpg_edit_key_cmd = subprocess.Popen(
            ['gpg', '--homedir', gpg_tmp_home, '--command-fd', '0', '--batch', '--edit-key', gpg_key_fingerprint],
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE, stderr=subprocess.PIPE,
        )
        (gpg_edit_key_cmd_stdout, gpg_edit_key_cmd_stderr) = gpg_edit_key_cmd.communicate(
            input='expire\n0\nsave\n'.encode(),
            timeout=5,
        )
        #  print(gpg_edit_key_cmd_stderr.decode())
        #  print(subprocess.check_output(['gpg', '--homedir', gpg_tmp_home, '--list-public-keys']).decode())
        if 'expires: never' not in str(gpg_edit_key_cmd_stderr):
            raise Exception("Could not change expiration date.")
        tmp_keyring_dir = os.path.join(tmp_git_repo, 'tmp-keyring-gpg')
        tmp_pubkey_file = os.path.join(
            tmp_keyring_dir,
            '0x' + gpg_key_fingerprint[-16:].upper()
        )
        os.mkdir(tmp_keyring_dir)
        with open(tmp_pubkey_file, 'w') as tmp_pubkey_fh:
            tmp_pubkey_fh.write(gpg.export_keys(gpg_key_fingerprint))

        git_cmd = git.Git(tmp_git_repo)
        git_cmd.update_environment(
            GNUPGHOME=debops_keyring_fake_gnupg_home,
        )
        git_cmd.init()
        git_cmd.config(['user.signingkey', gpg_key_fingerprint])
        git_cmd.config(['user.email', '*****@*****.**'])
        git_cmd.config(['user.name', 'debops-keyring-test'])
        git_cmd.update_environment(
            GNUPGHOME=os.path.join(tmp_git_repo, 'gpg_tmp_home'),
        )
        tmp_git_file = os.path.join(tmp_git_repo, 'new-file')
        with open(tmp_git_file, 'w') as tmp_git_fh:
            tmp_git_fh.write(str(time.time()))
        git_cmd.add([tmp_git_file])
        git_cmd.commit(['--gpg-sign', '--message', 'Signed commit'])
        debops_keyring = Keyring(
            keyring_name=tmp_keyring_dir,
        )
        debops_keyring.check_git_commits(tmp_git_repo)

        # Now make an unsigned commit to ensure that this raises an exception.
        with open(tmp_git_file, 'w') as tmp_git_fh:
            tmp_git_fh.write(str(time.time()))
        git_cmd.add([tmp_git_file])
        git_cmd.commit(['--no-gpg-sign', '--message', 'Unsigned commit'])
        try:
            debops_keyring.check_git_commits(tmp_git_repo)
            assert False
        except Exception as e:
            if 'OpenPGP signature of commit could not be verified' in str(e) and 'Unsigned commit' in str(e):
                assert True
            else:
                assert False
예제 #3
0
class Test(unittest.TestCase):
    '''Unit tests for validating signed envelopes from the Learning Registry'''
    def __init__(self, methodName="runTest"):
        self.sampleJSON = '''
            {
                "_id":"00e3f67232e743b6bc2a079bd98ff55a",
                "_rev":"1-8163d32f6cc9996f2b7228d8b5db7962",
                "doc_type":"resource_data",
                "update_timestamp":"2011-03-14 13:36:04.617999",
                "resource_data":"<oai_dc:dc xmlns:oai_dc=\\"http://www.openarchives.org/OAI/2.0/oai_dc/\\" xmlns:dc=\\"http://purl.org/dc/elements/1.1/\\" xmlns:xsi=\\"http://www.w3.org/2001/XMLSchema-instance\\" xmlns=\\"http://www.openarchives.org/OAI/2.0/\\" xsi:schemaLocation=\\"http://www.openarchives.org/OAI/2.0/oai_dc/                          http://www.openarchives.org/OAI/2.0/oai_dc.xsd\\">\\n<dc:title>A chat about America. October and November, 1884.</dc:title>\\n<dc:creator>J. P.</dc:creator>\\n<dc:subject>United States--Description and travel.</dc:subject>\\n<dc:description>\\"Printed for private circulation only.\\"</dc:description>\\n<dc:description>Electronic reproduction. Washington, D.C. : Library of Congress, [2002-2003]</dc:description>\\n<dc:publisher>Manchester, Palmer &amp; Howe</dc:publisher>\\n<dc:date>1885</dc:date>\\n<dc:type>text</dc:type>\\n<dc:identifier>http://hdl.loc.gov/loc.gdc/lhbtn.12281</dc:identifier>\\n<dc:language>eng</dc:language>\\n<dc:coverage>United States</dc:coverage>\\n</oai_dc:dc>\\n      ",
                "keys":["United States--Description and travel.","eng"],
                "submitter_type":"agent",
                "resource_data_type":"metadata",
                "payload_schema_locator":"http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd",
                "payload_placement":"inline",
                "submitter":"NSDL 2 LR Data Pump",
                "payload_schema":["oai_dc"],
                "node_timestamp":"2011-03-14 13:36:04.617999",
                "doc_version":"0.10.0",
                "create_timestamp":"2011-03-14 13:36:04.617999",
                "active":true,
                "publishing_node":"string",
                "resource_locator":"http://hdl.loc.gov/loc.gdc/lhbtn.12281",
                "doc_ID":"00e3f67232e743b6bc2a079bd98ff55a",
                "TOS": {
                    "submission_TOS": "http://example.com/tos/unknown",
                    "submission_attribution": "unidentified"
                }
            }
            '''

        self.sampleKeyLocations = [
            "http://example.com/mykey", "http://example2.com/mykey"
        ]

        self.gpgbin = "gpg"
        self.gnupgHome = os.path.expanduser(
            os.path.abspath(os.path.join("..", "gnupg_home")))
        self.gpg = None

        self.testDataDir = None
        self.testDataUnicode = None

        configFile = os.path.join("config.cfg")
        if os.path.exists(configFile):
            config = json.load(file(configFile))

            if "global" in config:
                if "testdata" in config["global"] and os.path.exists(
                        config["global"]["testdata"]):
                    self.testDataDir = config["global"]["testdata"]

                if "testdata_unicode" in config["global"] and os.path.exists(
                        config["global"]["testdata_unicode"]):
                    self.testDataUnicode = config["global"]["testdata_unicode"]

        unittest.TestCase.__init__(self, methodName)

    def setUp(self):

        now = time.localtime()
        now = calendar.timegm(now)

        try:
            for root, dirs, files in os.walk(self.gnupgHome):
                for filename in files:
                    try:
                        os.unlink(os.path.join(root, filename))
                    except:
                        pass
                os.removedirs(root)
        except:
            pass

        os.makedirs(self.gnupgHome)

        self.gpg = GPG(gpgbinary=self.gpgbin, gnupghome=self.gnupgHome)

        self.privateEmail = "privateTest-{0}@learningregistry.org".format(now)
        self.privateEmail2 = "privateTest2-{0}@learningregistry.org".format(
            now)
        self.genericPassphrase = "supersecret"

        input = self.gpg.gen_key_input(name_email=self.privateEmail,
                                       passphrase=self.genericPassphrase)
        self.privateKey = self.gpg.gen_key(input)

        input = self.gpg.gen_key_input(name_email=self.privateEmail2,
                                       passphrase=self.genericPassphrase)
        self.privateKey2 = self.gpg.gen_key(input)

        self.privExport = self.gpg.export_keys(
            [self.privateKey.fingerprint, self.privateKey2.fingerprint],
            secret=True)
        self.pubExport = self.gpg.export_keys(
            [self.privateKey.fingerprint, self.privateKey2.fingerprint],
            secret=False)

        pass

    def tearDown(self):
        self.gpg.delete_keys(
            [self.privateKey.fingerprint, self.privateKey2.fingerprint],
            secret=True)
        self.gpg.delete_keys(
            [self.privateKey.fingerprint, self.privateKey2.fingerprint],
            secret=False)
        pass

    def testGetSignatureBlock(self):
        '''Check that signature block validation correctly returns a structurally valid response'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "envelope did not sign correctly"

        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        sigInfo = verifytool._getSignatureInfo(signed)

        assert sigInfo != None, "signature extraction from envelope failed"

        assert "signing_method" in sigInfo and sigInfo[
            "signing_method"] == verifytool.signatureMethod, "signing_method is missing from signature block"

        assert "signature" in sigInfo and sigInfo["signature"] != None and len(
            sigInfo["signature"]
        ) > 0, "signature field is missing, null or is empty"

        assert "key_location" in sigInfo and sigInfo[
            "key_location"] == self.sampleKeyLocations, "key_location field is not correct"

        assert "key_owner" in sigInfo and sigInfo[
            "key_owner"] == signtool._get_privatekey_owner(
            ), "key_owner field does not match signing key"

    def testBadSignatureBlockMissingLocation(self):
        '''Check that signature block validation correctly checks for missing key_location field'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=None)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope not signed correctly"

        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)

        with self.assertRaises(errors.BadSignatureFormat,
                               msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)

        assert caught.exception.message == errors.MISSING_KEY_LOCATION, "Exception not formatted with correct message"

    def testBadSignatureBlockMissingSignatureMethod(self):
        '''Check signature block for missing signature_method detection'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope not signed correctly."

        del signed["digital_signature"]["signing_method"]

        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)

        with self.assertRaises(errors.UnsupportedSignatureAlgorithm,
                               msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)

        assert caught.exception.alg == None, "Raised exception not formatted correctly"

    def testBadSignatureBlockBadSignatureMethod(self):
        '''Check signature block for detecting unsupported algorithm use'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None

        signed["digital_signature"][
            "signing_method"] = signtool.signatureMethod + "+BAD_SIGNATURE_METHOD"

        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)

        with self.assertRaises(errors.UnsupportedSignatureAlgorithm,
                               msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)

        assert caught.exception.alg == signed["digital_signature"][
            "signing_method"], "Exception not raised correctly."

    def testBadSignatureBlockBadKeyOwner(self):
        '''Check signature block for a bad key_owner field'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope not signed correctly"

        signed["digital_signature"]["key_owner"] = [
            "John Q. Public <*****@*****.**>"
        ]

        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)

        with self.assertRaises(errors.BadSignatureFormat,
                               msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)

        assert caught.exception.message == errors.BAD_KEY_OWNER, "Wrong exception"

    def testBadSignatureBlockMissingNullEmptySignature(self):
        '''Check signature block validation with missing/null or empty signature'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope signing did not succeed correctly."

        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)

        signed["digital_signature"]["signature"] = ""
        with self.assertRaises(errors.BadSignatureFormat,
                               msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)
        assert caught.exception.message == errors.MISSING_SIGNATURE, "Wrong exception raised"

        signed["digital_signature"]["signature"] = None
        with self.assertRaises(errors.BadSignatureFormat,
                               msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)
        assert caught.exception.message == errors.MISSING_SIGNATURE, "Wrong exception raised"

        del signed["digital_signature"]["signature"]
        with self.assertRaises(errors.BadSignatureFormat,
                               msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)
        assert caught.exception.message == errors.MISSING_SIGNATURE, "Wrong exception raised"

    def testValidSignature(self):
        '''Check for valid signature'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope did not sign correctly"

        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        verified = verifytool.verify(signed)
        assert verified == True, "Envelope signature verification did not succeed, even though it should"

    def testMissingPublicKey(self):
        '''Check for appropriate response when public key for signature is missing'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope did not sign correctly"

        self.gpg.delete_keys([self.privateKey.fingerprint], secret=True)
        self.gpg.delete_keys([self.privateKey.fingerprint], secret=False)

        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)

        with self.assertRaises(errors.MissingPublicKey,
                               msg="Expected exception not raised.") as caught:
            verified = verifytool.verify(signed)
            assert verified == False, "Envelope verified, despite missing public key."

    def testCorruptEnvelope(self):
        '''Modify a signed envelope and check for validity'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "envelope did not get signed correctly"

        signed["X_corrupted"] = "Corrupted Envelope"

        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)

        verified = verifytool.verify(signed)

        assert verified == False, "corrupted envelope verified as good"

    def testWrongSignature(self):
        '''Test using a mis-matched signature, using a signature from a different valid envelope'''
        unsigned = json.loads(self.sampleJSON)
        altered = copy.deepcopy(unsigned)
        altered["X_corrupted"] = "Altered Envelope"

        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=self.sampleKeyLocations)
        signtool2 = Sign_0_21(privateKeyID=self.privateKey2.fingerprint,
                              passphrase=self.genericPassphrase,
                              gnupgHome=self.gnupgHome,
                              gpgbin=self.gpgbin,
                              publicKeyLocations=self.sampleKeyLocations)

        signed = signtool.sign(unsigned)
        alt_signed = signtool2.sign(altered)

        assert signed != None, "original did not get signed"
        assert alt_signed != None, "modified copy did not get signed"

        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)

        verified = verifytool.verify(signed)
        assert verified == True, "signature did not verify, even though it should."
        verified = verifytool.verify(alt_signed)
        assert verified == True, "signature did not verify, even though it should."

        signed["digital_signature"] = alt_signed["digital_signature"]

        verified = verifytool.verify(signed)
        assert verified == False, "swapped signature block validated envelope as good."

    def testCorruptSignature(self):
        '''Test using a corrupted signature, replace the hash within a signature with a hash from a different envelope'''
        unsigned = json.loads(self.sampleJSON)

        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "baseline signing failed"

        # validate original with good signature
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        verified = verifytool.verify(signed)
        assert verified == True, "baseline validation failed"

        # manipulate the hash portion of a signature block
        altered = copy.deepcopy(unsigned)
        altered["X_corrupted"] = "Altered Envelope"
        altered_hash = signtool.get_message(altered)

        validHash = verifytool._extractHashFromSignature(
            signed["digital_signature"]["signature"])
        alt_signed = copy.deepcopy(signed)

        alt_signed["digital_signature"]["signature"] = signed[
            "digital_signature"]["signature"].replace(validHash, altered_hash)
        assert alt_signed["digital_signature"]["signature"] != signed[
            "digital_signature"][
                "signature"], "envelopes should not be equal after deliberate modificaton"

        verified = verifytool.verify(alt_signed)
        assert verified == False, "verification failed, corrupted signature block verified as good"

    def testSignLRTestData(self):
        '''Test using LR Test Data, if available'''
        if self.testDataDir == None:
            log.info("Skipping test, test data directory not set.")
            return

        import codecs

        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint,
                             passphrase=self.genericPassphrase,
                             gnupgHome=self.gnupgHome,
                             gpgbin=self.gpgbin,
                             publicKeyLocations=self.sampleKeyLocations)
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)

        allfiles = os.listdir(self.testDataDir)
        for root, dirs, files in os.walk(self.testDataDir):

            for fileName in files:
                log.info("Trying to sign %s" % (fileName, ))

                unsigned = json.load(
                    codecs.open(os.path.join(root, fileName), "r",
                                "utf-8-sig"))

                signed = signtool.sign(unsigned)

                assert "digital_signature" in signed, "missing digital_signature"

                verified = verifytool.verify(signed)
                assert verified == True, "baseline validation failed"
예제 #4
0
파일: manager.py 프로젝트: grocid/Skier
def import_from_dump(file):
    """Import from an SKS dump."""
    # First, load a new GPG instance.
    gpg = GPG(gnupghome="/tmp/skier-import")

    # Read data in
    dumpf = open(file, 'rb')
    data = dumpf.read()
    dump = pgpdump.BinaryData(data)
    dumpf.close()

    # Import the keydump into gpg
    try:
        gpg.import_keys(data)
    except:
        # Yeah, whatever.
        pass
    """
    # Read in packets
    packets_flat = []
    try:
        for packet in dump.packets():
            packets_flat.append(packet)
    except Exception as e:
        # Some SKS data is malformed.
        print("SKS data in {} is malformed - truncating at packet {}".format(file, len(packets_flat)+1))

    # Unflatten list into sublists, starting at each new Publickey packet.
    packets = []
    tmpl = []
    for packet in packets_flat:
        if isinstance(packet, pgpdump.packet.PublicKeyPacket) and not isinstance(packet, pgpdump.packet.PublicSubkeyPacket) and tmpl:
            tmpl.insert(0, packet)
            gpg_output = gpg.export_keys(keyids=[packet.fingerprint.decode()])
            if gpg_output:
                tmpl.append(gpg_output)
            packets.append(tmpl)
            tmpl = []
            continue
        else:
            tmpl.append(packet)
    packets.append(tmpl)
    """
    armored = []
    for key in gpg.list_keys():
        tmpkey = gpg.export_keys(keyids=key['fingerprint'])
        if not tmpkey:
            print("{} is malformed - not importing".format(key['fingerprint']))
        armored.append(tmpkey)


    print("Importing {} keys".format(len(armored)))
    """
    for gpack in packets:
        keyinfo = KeyInfo.pgp_dump(None, packets=gpack)
        dbob = db.Key.from_keyinfo(keyinfo)
        db.db.session.add(dbob)

    db.db.session.commit()
    """

    for key in armored:
        kyinfo = KeyInfo.pgp_dump(key)
        if not kyinfo.fingerprint:
            print("Key {} is malformed - cannot be imported".format(kyinfo))
        else:
            dbob = db.Key.from_keyinfo(kyinfo)
            db.db.session.add(dbob)

    db.db.session.commit()

    shutil.rmtree("/tmp/skier-import")
예제 #5
0
def finish_login(message, bot, settings):
	user_root_folder = '/Seppass/Users_folder/user_' + str(message.chat.id)
	try:
		if not path.isdir(user_root_folder+'/main'):
			makedirs(user_root_folder+'/main')
		if not path.isdir(user_root_folder+'/user_data'):
			makedirs(user_root_folder+'/user_data')
	
	except:
		msg = bot.send_message(message.chat.id, 'Произошла ошибка.')
		del_mess(msg, bot, 4)
		return

	try:	
		gpg = GPG()
		input_data = gpg.gen_key_input(
			passphrase=message.text,
			name_real='user_'+str(message.chat.id)
			)
		key = gpg.gen_key(input_data)
		key = key.fingerprint

		ascii_armored_private_keys = gpg.export_keys(key, True, passphrase=message.text)
		system('echo RELOADAGENT | gpg-connect-agent')
		with open(user_root_folder+'/user_data/gpg_private_key.asc', 'w') as f:
			f.write(ascii_armored_private_keys)
		with open(user_root_folder+'/main/gpg_private_key.asc', 'w') as f:
			f.write(ascii_armored_private_keys)


	except:
		msg = bot.send_message(message.chat.id, 'Произошла ошибка.')
		del_mess(msg, bot, 4)
		return

	try:
		data = (('user_'+str(message.chat.id), key, str(settings)))
		conn = connect('DataBase.db', check_same_thread=False)
		c = conn.cursor()
		query = "INSERT INTO Users VALUES (?, ?, ?)"
		c.execute(query, data)
		conn.commit()
		conn.close()

	except:
		msg = bot.send_message(message.chat.id, 'Произошла ошибка.')
		del_mess(msg, bot, 4)
		return

	markup = types.ReplyKeyboardMarkup(one_time_keyboard=True)
	markup.add('Да')

	if settings["store_pass"] == "pass_server":
		try:
			with open(user_root_folder+'/user_data/Nothing.txt', 'w') as f:
				f.write(message.text)
		
		except:
			msg = bot.send_message(message.chat.id, 'Произошла ошибка.')
			del_mess(msg, bot, 4)
			return

		msg_handler = bot.send_message(message.chat.id, 'Регистрация прошла успешно. Пароль храниться на сервере.\n\nВаш user id:\n'+str(message.chat.id)+'\n\nПароль:\n'+ message.text +'\n\nЭто ваш отпечаток ключа:\n'+ str(key)+'\n\nЗапомнили? Я сейчас это сообщение удалю, в целях сохранности ваших данных.', reply_markup = markup)
		bot.register_next_step_handler(msg_handler, lambda msg: complete_finish_login(msg, bot))

	else:
		msg_handler = bot.send_message(message.chat.id, 'Регистрация прошла успешно. Запомните пароль, в случае его утери ваш акк не восстановить (пока).\n\nВаш user id:\n'+str(message.chat.id)+'\n\nПароль:\n'+ message.text +'\n\nЭто ваш отпечаток ключа:\n'+ str(key)+'\n\nЗапомнили? Я сейчас это сообщение удалю, в целях сохранности ваших данных.', reply_markup = markup)
		bot.register_next_step_handler(msg_handler, lambda msg: complete_finish_login(msg, bot))
예제 #6
0
class Test(unittest.TestCase):
    '''Unit tests for validating signed envelopes from the Learning Registry''' 
    def __init__(self, methodName="runTest"):
        self.sampleJSON = '''
            {
                "_id":"00e3f67232e743b6bc2a079bd98ff55a",
                "_rev":"1-8163d32f6cc9996f2b7228d8b5db7962",
                "doc_type":"resource_data",
                "update_timestamp":"2011-03-14 13:36:04.617999",
                "resource_data":"<oai_dc:dc xmlns:oai_dc=\\"http://www.openarchives.org/OAI/2.0/oai_dc/\\" xmlns:dc=\\"http://purl.org/dc/elements/1.1/\\" xmlns:xsi=\\"http://www.w3.org/2001/XMLSchema-instance\\" xmlns=\\"http://www.openarchives.org/OAI/2.0/\\" xsi:schemaLocation=\\"http://www.openarchives.org/OAI/2.0/oai_dc/                          http://www.openarchives.org/OAI/2.0/oai_dc.xsd\\">\\n<dc:title>A chat about America. October and November, 1884.</dc:title>\\n<dc:creator>J. P.</dc:creator>\\n<dc:subject>United States--Description and travel.</dc:subject>\\n<dc:description>\\"Printed for private circulation only.\\"</dc:description>\\n<dc:description>Electronic reproduction. Washington, D.C. : Library of Congress, [2002-2003]</dc:description>\\n<dc:publisher>Manchester, Palmer &amp; Howe</dc:publisher>\\n<dc:date>1885</dc:date>\\n<dc:type>text</dc:type>\\n<dc:identifier>http://hdl.loc.gov/loc.gdc/lhbtn.12281</dc:identifier>\\n<dc:language>eng</dc:language>\\n<dc:coverage>United States</dc:coverage>\\n</oai_dc:dc>\\n      ",
                "keys":["United States--Description and travel.","eng"],
                "submitter_type":"agent",
                "resource_data_type":"metadata",
                "payload_schema_locator":"http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd",
                "payload_placement":"inline",
                "submitter":"NSDL 2 LR Data Pump",
                "payload_schema":["oai_dc"],
                "node_timestamp":"2011-03-14 13:36:04.617999",
                "doc_version":"0.10.0",
                "create_timestamp":"2011-03-14 13:36:04.617999",
                "active":true,
                "publishing_node":"string",
                "resource_locator":"http://hdl.loc.gov/loc.gdc/lhbtn.12281",
                "doc_ID":"00e3f67232e743b6bc2a079bd98ff55a",
                "TOS": {
                    "submission_TOS": "http://example.com/tos/unknown",
                    "submission_attribution": "unidentified"
                }
            }
            '''
        
        self.sampleKeyLocations = [
                                   "http://example.com/mykey",
                                   "http://example2.com/mykey"
                                   ]
        
        self.gpgbin="/usr/local/bin/gpg"
        self.gnupgHome = os.path.expanduser(os.path.join("~", ".gnupg"))
        self.gpg = GPG(gpgbinary=self.gpgbin, gnupghome=self.gnupgHome)
        
        self.testDataDir = None
        configFile = os.path.join("config.cfg")
        if os.path.exists(configFile):
            config = json.load(file(configFile))
            
            if config.has_key("global"):
                if config["global"].has_key("testdata") and os.path.exists(config["global"]["testdata"]):
                    self.testDataDir = config["global"]["testdata"]
        
        unittest.TestCase.__init__(self, methodName)


    def setUp(self):
        
        now = time.localtime()
        now = calendar.timegm(now)
        
        
        self.privateEmail = "privateTest-{0}@learningregistry.org".format(now)
        self.privateEmail2 = "privateTest2-{0}@learningregistry.org".format(now)
        self.genericPassphrase = "supersecret"
        
        input = self.gpg.gen_key_input(name_email=self.privateEmail, passphrase=self.genericPassphrase)
        self.privateKey = self.gpg.gen_key(input)
        
       
        

        input = self.gpg.gen_key_input(name_email=self.privateEmail2, passphrase=self.genericPassphrase)
        self.privateKey2 = self.gpg.gen_key(input)
        
        self.privExport = self.gpg.export_keys([self.privateKey.fingerprint, self.privateKey2.fingerprint], secret=True)
        self.pubExport = self.gpg.export_keys([self.privateKey.fingerprint, self.privateKey2.fingerprint], secret=False)
        
        pass


    def tearDown(self):
        self.gpg.delete_keys([self.privateKey.fingerprint, self.privateKey2.fingerprint], secret=True)
        self.gpg.delete_keys([self.privateKey.fingerprint, self.privateKey2.fingerprint], secret=False)
        pass


    def testGetSignatureBlock(self):
        '''Check that signature block validation correctly returns a structurally valid response'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "envelope did not sign correctly"
        
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        sigInfo = verifytool._getSignatureInfo(signed)
        
        assert sigInfo != None, "signature extraction from envelope failed"
        
        assert sigInfo.has_key("signing_method") and sigInfo["signing_method"] == verifytool.signatureMethod, "signing_method is missing from signature block"
        
        assert sigInfo.has_key("signature") and sigInfo["signature"] != None and len(sigInfo["signature"]) > 0, "signature field is missing, null or is empty"
        
        assert sigInfo.has_key("key_location") and sigInfo["key_location"] == self.sampleKeyLocations, "key_location field is not correct"
        
        assert sigInfo.has_key("key_owner") and sigInfo["key_owner"] == signtool._get_privatekey_owner(), "key_owner field does not match signing key"

    def testBadSignatureBlockMissingLocation(self):
        '''Check that signature block validation correctly checks for missing key_location field'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=None)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope not signed correctly"
        
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        
        with self.assertRaises(errors.BadSignatureFormat, msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)
        
        assert caught.exception.message == errors.MISSING_KEY_LOCATION, "Exception not formatted with correct message" 
        
        
    def testBadSignatureBlockMissingSignatureMethod(self):
        '''Check signature block for missing signature_method detection'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope not signed correctly."
        
        del signed["digital_signature"]["signing_method"]
        
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        
        with self.assertRaises(errors.UnsupportedSignatureAlgorithm, msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)
        
        assert caught.exception.alg == None, "Raised exception not formatted correctly" 
        
        
    def testBadSignatureBlockBadSignatureMethod(self):
        '''Check signature block for detecting unsupported algorithm use'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None
        
        signed["digital_signature"]["signing_method"] = signtool.signatureMethod+"+BAD_SIGNATURE_METHOD"
        
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        
        with self.assertRaises(errors.UnsupportedSignatureAlgorithm, msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)
        
        assert caught.exception.alg == signed["digital_signature"]["signing_method"], "Exception not raised correctly."
        
    def testBadSignatureBlockBadKeyOwner(self):
        '''Check signature block for a bad key_owner field'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope not signed correctly"
        
        signed["digital_signature"]["key_owner"] = ["John Q. Public <*****@*****.**>"]
        
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        
        with self.assertRaises(errors.BadSignatureFormat, msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)
        
        assert caught.exception.message == errors.BAD_KEY_OWNER, "Wrong exception"
        
        
    def testBadSignatureBlockMissingNullEmptySignature(self):
        '''Check signature block validation with missing/null or empty signature'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope signing did not succeed correctly."
                
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        
        signed["digital_signature"]["signature"] = ""
        with self.assertRaises(errors.BadSignatureFormat, msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)
        assert caught.exception.message == errors.MISSING_SIGNATURE, "Wrong exception raised"
        
        signed["digital_signature"]["signature"] = None
        with self.assertRaises(errors.BadSignatureFormat, msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)
        assert caught.exception.message == errors.MISSING_SIGNATURE, "Wrong exception raised"
        
        del signed["digital_signature"]["signature"] 
        with self.assertRaises(errors.BadSignatureFormat, msg="Expected exception not raised.") as caught:
            sigInfo = verifytool._getSignatureInfo(signed)
        assert caught.exception.message == errors.MISSING_SIGNATURE, "Wrong exception raised"
    
    
    def testValidSignature(self):
        '''Check for valid signature'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope did not sign correctly"
                
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        verified = verifytool.verify(signed)
        assert verified == True, "Envelope signature verification did not succeed, even though it should"
        
    def testMissingPublicKey(self):
        '''Check for appropriate response when public key for signature is missing'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "Envelope did not sign correctly"
        
        self.gpg.delete_keys([self.privateKey.fingerprint], secret=True)
        self.gpg.delete_keys([self.privateKey.fingerprint], secret=False)
                
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        
        with self.assertRaises(errors.MissingPublicKey, msg="Expected exception not raised.") as caught:
            verified = verifytool.verify(signed)
            assert verified == False, "Envelope verified, despite missing public key."
    
    def testCorruptEnvelope(self):
        '''Modify a signed envelope and check for validity'''
        unsigned = json.loads(self.sampleJSON)
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "envelope did not get signed correctly"
        
        signed["X_corrupted"] = "Corrupted Envelope"
        
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)

        verified = verifytool.verify(signed)
        
        assert verified == False, "corrupted envelope verified as good"
        
        
    def testWrongSignature(self):
        '''Test using a mis-matched signature, using a signature from a different valid envelope'''
        unsigned = json.loads(self.sampleJSON)
        altered = copy.copy(unsigned)
        altered["X_corrupted"] = "Altered Envelope"
        
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        signtool2 = Sign_0_21(privateKeyID=self.privateKey2.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        
        signed = signtool.sign(unsigned)
        alt_signed = signtool2.sign(altered)
        
        assert signed != None, "original did not get signed"
        assert alt_signed != None, "modified copy did not get signed"
        
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        
        verified = verifytool.verify(signed)
        assert verified == True, "signature did not verify, even though it should."
        verified = verifytool.verify(alt_signed)
        assert verified == True, "signature did not verify, even though it should."
        
        signed["digital_signature"] = alt_signed["digital_signature"]
        
        verified = verifytool.verify(signed)
        assert verified == False, "swapped signature block validated envelope as good."
        
    def testCorruptSignature(self):
        '''Test using a corrupted signature, replace the hash within a signature with a hash from a different envelope'''
        unsigned = json.loads(self.sampleJSON)
        
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        signed = signtool.sign(unsigned)
        assert signed != None, "baseline signing failed"
        
        # validate original with good signature
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)
        verified = verifytool.verify(signed)
        assert verified == True, "baseline validation failed"
        
        # manipulate the hash portion of a signature block
        altered = copy.copy(unsigned)
        altered["X_corrupted"] = "Altered Envelope"
        altered_hash = signtool.get_message(altered)
        
        validHash = verifytool._extractHashFromSignature(signed["digital_signature"]["signature"])
        alt_signed = copy.deepcopy(signed)
        
        alt_signed["digital_signature"]["signature"] = signed["digital_signature"]["signature"].replace(validHash, altered_hash)
        assert alt_signed["digital_signature"]["signature"] != signed["digital_signature"]["signature"], "envelopes should not be equal after deliberate modificaton"
        
        verified = verifytool.verify(alt_signed)
        assert verified == False, "verification failed, corrupted signature block verified as good"
        
    def testSignLRTestData(self):
        '''Test using LR Test Data, if available'''
        if self.testDataDir == None:
            log.info("Skipping test, test data directory not set.")
            return
        
        import codecs
        
        signtool = Sign_0_21(privateKeyID=self.privateKey.fingerprint, passphrase=self.genericPassphrase, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=self.sampleKeyLocations)
        verifytool = Verify_0_21(gpgbin=self.gpgbin, gnupgHome=self.gnupgHome)

        allfiles = os.listdir(self.testDataDir)
        for fileName in allfiles:
            log.info("Trying to sign %s" % (fileName, ))
            
            unsigned = json.load(codecs.open(os.path.join(self.testDataDir, fileName), "r", "utf-8-sig"))
            
            signed = signtool.sign(unsigned)
            
            assert signed.has_key("digital_signature"), "missing digital_signature"
            
            verified = verifytool.verify(signed)
            assert verified == True, "baseline validation failed"
예제 #7
0
파일: __init__.py 프로젝트: LukeCarrier/hn
    def setUp(self):
        """
        Construct environment.

        Here, we adopt the configuration used by the production or development
        installation and make the necessary changes before writing it to a new
        file in the etc directory. When we're finished, we'll remove it in the
        tearDown() function.
        """

        if not os.path.exists(self.client_env['CONFDIR']):

            # Don't waste time and entropy on keys if we can't write configuration
            # files -- that's a very distressing experience.
            assert len(sys.argv) == 2

            # Prepare two GPG keypairs; one for the agent, one for the client
            agent_gpg_dir  = os.path.join(self.client_env['CONFDIR'], 'agent_gpg')
            agent_gpg      = GPG(gnupghome=agent_gpg_dir)
            agent_key      = agent_gpg.gen_key(agent_gpg.gen_key_input(**self.gpg_params))
            client_gpg_dir = os.path.join(self.client_env['CONFDIR'], 'client_gpg')
            client_gpg     = GPG(gnupghome=client_gpg_dir)
            client_key     = client_gpg.gen_key(client_gpg.gen_key_input(**self.gpg_params))

            # Export both public keys; import them into the opposing side
            agent_key_blob  = agent_gpg.export_keys(agent_key.fingerprint)
            client_gpg.import_keys(agent_key_blob)
            client_gpg.sign_key(agent_key.fingerprint)
            client_key_blob = client_gpg.export_keys(client_key.fingerprint)
            agent_gpg.import_keys(client_key_blob)
            agent_gpg.sign_key(client_key.fingerprint)

            # Configure the agent to run in a development-safe configuration.
            #
            # Here, we load the base configuration we ship with the application
            # as the default. All other configuration will be ignored for the
            # purposes of the test run, since this is outside of our scope.
            with open(self.agent_env['CONFDIR'], 'w') as f:
                l = os.path.join(self.client_env['CONFDIR'], 'agent_%s.log')
                agent_cfg = ConfigurationFactory.get('hypernova.agent',
                                                     root_dir=sys.argv[1])
                agent_cfg.set('server',  'address',     self.agent_addr[0])
                agent_cfg.set('server',  'port',        self.agent_addr[1])
                agent_cfg.set('server',  'daemon',      'false')
                agent_cfg.set('gpg',     'key_store',   agent_gpg_dir)
                agent_cfg.set('gpg',     'fingerprint', agent_key.fingerprint)
                agent_cfg.set('logging', 'main_log',    l %('main'))
                agent_cfg.set('logging', 'request_log', l %('request'))
                agent_cfg.set('logging', 'error_log',   l %('error'))
                agent_cfg.write(f)

            # The client has to use two different configuration files, both in
            # the same directory.
            client_cfg_dir = self.client_env['CONFDIR']

            # Configure the client to use its temporary key.
            #
            # To communicate with the agent (which will be running in a limited
            # testing mode), we'll need to reconfigure the client with a keypair
            # we've imported into the agent. This keystore manipulation has
            # already taken place, so we know the fingerprint of our new private
            # key.
            client_cfg_file = os.path.join(client_cfg_dir, 'client.ini')
            with open(client_cfg_file, 'w') as f:
                client_cfg      = configparser.SafeConfigParser()
                client_cfg.add_section('client')
                client_cfg.set('client', 'privkey', client_key.fingerprint)
                client_cfg.write(f)

            # Pair the client to the agent.
            #
            # We do this manually, since the importer requires that we write the
            # public key to a file before we import it. This would be a
            # pointless exercise and an unnecessary complication.
            client_srv_file = os.path.join(client_cfg_dir, 'servers.ini')
            with open(client_srv_file, 'w') as f:
                client_srv_cfg  = configparser.SafeConfigParser()
                client_srv_cfg.add_section('local')
                client_srv_cfg.set('local', 'addr', ':'.join(self.agent_addr))
                client_srv_cfg.set('local', 'pubkey', agent_key.fingerprint)
                client_srv_cfg.write(f)

        # TODO: instead of lazily and unreliably falling asleep on the job,
        #       we should probably use a regular expression to check the output.
        #       Time is of the essence, though!
        #       No, we'll use pexpect instead, since it's now shipped as a py3k
        #       dependency.
        agent_cmd = [
            'hn-agent',
            self.agent_env['CONFDIR']
        ]
        self.agent_proc = subprocess.Popen(agent_cmd, env=self.agent_env,
                                           stdin=subprocess.PIPE,
                                           stdout=subprocess.PIPE,
                                           stderr=subprocess.PIPE)
        time.sleep(self.agent_init_time)
예제 #8
0
def test_check_git_commits_ok():
    with TemporaryDirectory() as tmp_git_repo:
        gpg_tmp_home = os.path.join(tmp_git_repo, 'gpg_tmp_home')
        # Included in the repository to avoid problems with low entropy in CI
        # environments.
        #  input_data = gpg.gen_key_input(
        #      key_type='RSA',
        #      subkey_type='RSA',
        #      key_length=1024,
        #      subkey_length=1024,
        #      name_comment='This is only a test key who’s private key is publicly know. Don’t use this key for anything!1!',
        #      name_email='*****@*****.**',
        #      # Has already expired at the time of creation to ensure no one will ever use the key.
        #      expire_date='2012-12-24',  # Needs to be set to the 24 for the key to expire on 23.
        #      # Hm, Ok, gpg does not do that by default. `--faked-system-time`
        #      # could be used to force it but that would require cmd access.
        #      # https://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.html
        #      # "gpg: Invalid option "--faked-system-time"" :(
        #      # Only: gpg2 --batch --gen-key --debug=0 --faked-system-time '2342-05-23'
        #      # has been confirmed to work from current Debian Stretch.
        #      # Faking it manually anyway …
        #  )
        #  print(input_data)
        #  print(gpg.gen_key(input_data))

        shutil.copytree(debops_keyring_fake_gnupg_home, gpg_tmp_home)
        gpg = GPG(gnupghome=gpg_tmp_home)

        os.chmod(gpg_tmp_home, 0o700)
        for r, d, f in os.walk(gpg_tmp_home):
            os.chmod(r, 0o700)
        gpg_key_fingerprint = gpg.list_keys()[0]['fingerprint']
        gpg_edit_key_cmd = subprocess.Popen(
            [
                'gpg', '--homedir', gpg_tmp_home, '--command-fd', '0',
                '--batch', '--edit-key', gpg_key_fingerprint
            ],
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        (gpg_edit_key_cmd_stdout,
         gpg_edit_key_cmd_stderr) = gpg_edit_key_cmd.communicate(
             input='expire\n0\nsave\n'.encode(),
             timeout=5,
         )
        #  print(gpg_edit_key_cmd_stderr.decode())
        #  print(subprocess.check_output(['gpg', '--homedir', gpg_tmp_home, '--list-public-keys']).decode())
        if 'expires: never' not in str(gpg_edit_key_cmd_stderr):
            raise Exception("Could not change expiration date.")
        tmp_keyring_dir = os.path.join(tmp_git_repo, 'tmp-keyring-gpg')
        tmp_pubkey_file = os.path.join(
            tmp_keyring_dir, '0x' + gpg_key_fingerprint[-16:].upper())
        os.mkdir(tmp_keyring_dir)
        with open(tmp_pubkey_file, 'w') as tmp_pubkey_fh:
            tmp_pubkey_fh.write(gpg.export_keys(gpg_key_fingerprint))

        git_cmd = git.Git(tmp_git_repo)
        git_cmd.update_environment(GNUPGHOME=debops_keyring_fake_gnupg_home, )
        git_cmd.init()
        git_cmd.config(['user.signingkey', gpg_key_fingerprint])
        git_cmd.config(['user.email', '*****@*****.**'])
        git_cmd.config(['user.name', 'debops-keyring-test'])
        git_cmd.update_environment(GNUPGHOME=os.path.join(
            tmp_git_repo, 'gpg_tmp_home'), )
        tmp_git_file = os.path.join(tmp_git_repo, 'new-file')
        with open(tmp_git_file, 'w') as tmp_git_fh:
            tmp_git_fh.write(str(time.time()))
        git_cmd.add([tmp_git_file])
        git_cmd.commit(['--gpg-sign', '--message', 'Signed commit'])
        debops_keyring = Keyring(keyring_name=tmp_keyring_dir, )
        debops_keyring.check_git_commits(tmp_git_repo)

        # Now make an unsigned commit to ensure that this raises an exception.
        with open(tmp_git_file, 'w') as tmp_git_fh:
            tmp_git_fh.write(str(time.time()))
        git_cmd.add([tmp_git_file])
        git_cmd.commit(['--no-gpg-sign', '--message', 'Unsigned commit'])
        try:
            debops_keyring.check_git_commits(tmp_git_repo)
            assert False
        except Exception as e:
            if 'OpenPGP signature of commit could not be verified' in str(
                    e) and 'Unsigned commit' in str(e):
                assert True
            else:
                assert False
예제 #9
0
class gpg(object):
    """
    module to wrap the gnupg library and gpg binary
    """
    def __init__(self, folder_path=None, binary_path=None):
        # ugly but working
        if binary_path is None:
            binary_path = join(project_base, "gpg", "gpg.exe")
            if not isfile(binary_path):
                binary_path = join(project_base, 'gpg')
                if not isfile(binary_path):
                    binary_path = find_executable('gpg')
                    if not isfile(binary_path):
                        raise RuntimeError('gpg not found')
        self.gpg = GPG(
            binary_path,  # gpgbinary
            folder_path,  # gnupghome
            verbose=False,
            options=["--allow-non-selfsigned-uid"])

    def get_key(self, fingerprint, private, passphrase):
        """
        returns the key belonging to the fingerprint given. if 'private' is
        True, the private key is returned. If 'private' is False, the public
        key will be returned.
        """
        key = self.gpg.export_keys(fingerprint,
                                   private,
                                   armor=False,
                                   passphrase=passphrase)
        return b64encode(key)

    def add_keypair(self, public_key, private_key, site, user, passphrase):
        """
        add a keypair into the gpg key database
        """
        try:
            result1 = self.gpg.import_keys(b64decode(public_key))
            result2 = self.gpg.import_keys(b64decode(private_key))
        except TypeError as error:
            getLogger(__name__).critical("add_keypair TypeError " + str(error))
        # make sure this is a key _pair_
        try:
            assert result1.fingerprints[0] == result2.fingerprints[0]
        except (IndexError, AssertionError) as error:
            getLogger(__name__).exception(
                'add_keypair IndexError/AssertionError: ' + str(error))
            return None
        fingerprint = result1.fingerprints[0]

        if self.is_passphrase_valid(passphrase=passphrase,
                                    fingerprint=fingerprint):
            old_fingerprint = self.get_fingerprint(site, user)
            if not old_fingerprint:
                sql = "INSERT INTO keys (site, user, fingerprint) VALUES (?, ?, ?)"
                database_execute(sql, (site, user, fingerprint))
            else:
                sql = "UPDATE keys SET SITE=? WHERE fingerprint=?"
                database_execute(sql, (site, old_fingerprint))
                if fingerprint != old_fingerprint:
                    getLogger(__name__).warn('updating %s fingerprint to %s' %
                                             (user, fingerprint))
            return fingerprint
        else:
            return None

    def add_public_key(self, site, user, public_key):
        """
        add a public key into the gpg key database
        """
        try:
            result1 = self.gpg.import_keys(b64decode(public_key))
            fingerprint = result1.fingerprints[0]

            sql = "INSERT INTO keys (site, user, fingerprint) VALUES (?, ?, ?)"
            database_execute(sql, (site, user, fingerprint))
            return fingerprint
        except TypeError as error:
            getLogger(__name__).critical("add_public_key TypeError " +
                                         str(error))
        except DatabaseError as error:
            getLogger(__name__).critical("add_public_key DatabaseError " +
                                         str(error))

    def is_passphrase_valid(self,
                            passphrase,
                            label=None,
                            user=None,
                            fingerprint=None):
        if not fingerprint:
            fingerprint = self.get_fingerprint(label, user)

        sign_result = self.gpg.sign("test",
                                    keyid=fingerprint,
                                    passphrase=passphrase)

        return sign_result.data != ''

    def generate(self, passphrase, site, user):
        """
        Generate a new 2048 bit GPG key and add it to the gpg manager.
        """
        data = self.gpg.gen_key_input(key_length=2048, passphrase=passphrase)
        dat = self.gpg.gen_key(data)
        fingerprint = dat.fingerprint
        sql = "INSERT INTO keys (site, user, fingerprint) VALUES (?, ?, ?);"
        database_execute(sql, (site, user, fingerprint))
        return fingerprint

    def get_fingerprint(self, site, user):
        sql = "select fingerprint from keys where site = ? and user = ?"
        result = database_execute(sql, (site, user))
        if not len(result):
            return None
        return result[0][0]

    def has_key(self, site, user):
        """
        Check whether a key is present for a certain site and user
        """
        return self.get_fingerprint(site, user) is None

    def encrypt(self, data, site, user, armor=False):
        """
        encrypt data for user at site.
        """
        fingerprint = self.get_fingerprint(site, user)
        cryptdata = self.gpg.encrypt_file(StringIO(data),
                                          fingerprint,
                                          always_trust=True,
                                          armor=armor)
        return str(cryptdata)

    def decrypt(self, data, passphrase):
        """
        decrypt data received from site.
        """
        datafile = StringIO(data)
        result = self.gpg.decrypt_file(datafile,
                                       passphrase=passphrase,
                                       always_trust=True)
        return str(result)

    @staticmethod
    def add_pkcs7_padding(contents):
        # Input strings must be a multiple of the segment size 16 bytes in length
        segment_size = 16

        # calculate how much padding is needed
        old_contents_length = len(contents)
        next_mult = old_contents_length + (segment_size -
                                           old_contents_length % segment_size)
        getLogger(__name__).debug(
            'old contents length %s || new contents length %s' %
            (old_contents_length, next_mult))

        # do the padding
        padding_byte = chr(next_mult - old_contents_length)
        contents = contents.ljust(next_mult, padding_byte)

        return contents

    @staticmethod
    def remove_pkcs7_padding(contents):
        """
        Remove PKCS#7 padding bytes

        >>> gpg.remove_pkcs7_padding('some_content'.ljust(16, chr(4)))
        'some_content'

        >>> gpg.remove_pkcs7_padding('some_content')
        'some_content'

        >>> gpg.remove_pkcs7_padding('')
        ''

        :param contents:
        :return: contents without padding
        """
        if len(contents) < 1:
            getLogger(__name__).debug(
                'contents is empty. No PKCS#7 padding removed')
            return contents

        bytes_to_remove = ord(contents[-1])  # will work up to 255 bytes

        # check if contents have valid PKCS#7 padding
        if bytes_to_remove > 1 and contents[-2] != contents[-1]:
            getLogger(__name__).debug('no PKCS#7 padding detected')
            return contents

        getLogger(__name__).debug('removing %s bytes of PKCS#7 padding' %
                                  bytes_to_remove)
        return contents[0:(len(contents) - bytes_to_remove)]