예제 #1
0
class reqPGP(object):
    def __init__(self, path=None):
        self.gpg = GPG(gpgbinary=('../gpg.exe' if osName == 'nt' else 'gpg'))
        if not path:
            try:
                self.path = environ["HOME"] + '/'
            except KeyError:
                self.path = environ["HOMEPATH"] + '\\'
        else:
            if path[-1] != '\\' and osName == 'nt':
                path += '\\'
            elif path[-1] != '/' and osName == 'posix':
                path += '/'
            self.path = path
            

    def genKey(self, account, passphrase):
        input_data = self.gpg.gen_key_input(
            name_email=account,
            passphrase=passphrase)
        self.gpg.gen_key(input_data)

    def encryptFile(self, account, data):
        encryptedData = str(self.gpg.encrypt(data, account))
        with open(self.path + '.' + account + '.req', 'w') as f:
            f.write(encryptedData)

    def decryptFile(self, account, passphrase):
        with open(self.path + '.' + account + '.req', 'rb') as f:
            decryptedData = str(self.gpg.decrypt_file(f, passphrase=passphrase))
        return decryptedData
    
    def deleteKey(self, keyId):
        self.gpg.delete_keys(keyId, True)
        self.gpg.delete_keys(keyId)
예제 #2
0
class reqPGP(object):
    def __init__(self, path=None):
        self.gpg = GPG(gpgbinary=('../gpg.exe' if osName == 'nt' else 'gpg'))
        if not path:
            try:
                self.path = environ["HOME"] + '/'
            except KeyError:
                self.path = environ["HOMEPATH"] + '\\'
        else:
            if path[-1] != '\\' and osName == 'nt':
                path += '\\'
            elif path[-1] != '/' and osName == 'posix':
                path += '/'
            self.path = path

    def genKey(self, account, passphrase):
        input_data = self.gpg.gen_key_input(name_email=account,
                                            passphrase=passphrase)
        self.gpg.gen_key(input_data)

    def encryptFile(self, account, data):
        encryptedData = str(self.gpg.encrypt(data, account))
        with open(self.path + '.' + account + '.req', 'w') as f:
            f.write(encryptedData)

    def decryptFile(self, account, passphrase):
        with open(self.path + '.' + account + '.req', 'rb') as f:
            decryptedData = str(self.gpg.decrypt_file(f,
                                                      passphrase=passphrase))
        return decryptedData

    def deleteKey(self, keyId):
        self.gpg.delete_keys(keyId, True)
        self.gpg.delete_keys(keyId)
예제 #3
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)
예제 #4
0
def _generate_key(username):
    gpg = GPG()
    key_input = gpg.gen_key_input(key_type="RSA", key_length=1024, name_email=username+"@node.org", name_real=username)

    entropy_thread = Process(target=generate_entropy)
    entropy_thread.start()
    key = gpg.gen_key(key_input)
    entropy_thread.terminate()
    keys = gpg.list_keys(True)
    for k in keys:
        if k.get("fingerprint") == key.fingerprint:
            return k['keyid']
예제 #5
0
class Test(unittest.TestCase):
    '''Unit test cases for signing envelopes from the Learning Registry'''
    def __init__(self, methodName="runTest"):
        
        self.gpgbin="/usr/local/bin/gpg"
        self.gnupgHome = os.path.expanduser(os.path.join("~", ".gnupg"))
        self.gpg = GPG(gpgbinary=self.gpgbin, gnupghome=self.gnupgHome)
        
        unittest.TestCase.__init__(self, methodName)
        
        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"]
        
        
        
    def setUp(self):
        now = time.localtime()
        now = calendar.timegm(now)
        self.goodEmail = "signTest-{0}@learningregistry.org".format(now)
        self.goodRealName = "Autogenerated Sign Test"
        self.goodpassphrase = "supersecret"
        
        input = self.gpg.gen_key_input(name_real=self.goodRealName, name_email=self.goodEmail, passphrase=self.goodpassphrase)
        self.goodPrivateKey = self.gpg.gen_key(input)
        
        privateKeyAvailable = False
        privateKeys = self.gpg.list_keys(secret=True)
        for skey in privateKeys:
            if skey["keyid"] == self.goodPrivateKey.fingerprint:
                privateKeyAvailable = True
                self.privateKeyInfo = skey
                break
            if skey["fingerprint"] == self.goodPrivateKey.fingerprint:
                privateKeyAvailable = True
                self.privateKeyInfo = skey
                break
        
        assert privateKeyAvailable == True, "Could not locate generated Private Key"
        
        self.goodkeyid = self.privateKeyInfo["keyid"]
        
        self.goodowner = self.privateKeyInfo["uids"][0]
        
        
        self.badkeyid = "XXXXXXXXXXXXXXXX"
        self.badpassphrase = "bad passphrase"
        
        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.sampleJSON_strip = '''{"keys": ["United States--Description and travel.", "eng"], "TOS": {"submission_attribution": "unidentified", "submission_TOS": "http://example.com/tos/unknown"}, "payload_placement": "inline", "active": true, "resource_locator": "http://hdl.loc.gov/loc.gdc/lhbtn.12281", "doc_type": "resource_data", "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      ", "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_schema": ["oai_dc"], "doc_version": "0.10.0", "submitter": "NSDL 2 LR Data Pump"}'''
        self.sampleJSON_strip_normal = '''{"keys": ["United States--Description and travel.", "eng"], "TOS": {"submission_attribution": "unidentified", "submission_TOS": "http://example.com/tos/unknown"}, "payload_placement": "inline", "active": "true", "resource_locator": "http://hdl.loc.gov/loc.gdc/lhbtn.12281", "doc_type": "resource_data", "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      ", "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_schema": ["oai_dc"], "doc_version": "0.10.0", "submitter": "NSDL 2 LR Data Pump"}''' 
        self.sampleJSON_strip_normal_bencode = '''d3:TOSd14:submission_TOS30:http://example.com/tos/unknown22:submission_attribution12:unidentifiede6:active4:true8:doc_type13:resource_data11:doc_version6:0.10.04:keysl38:United States--Description and travel.3:enge17:payload_placement6:inline14:payload_schemal6:oai_dce22:payload_schema_locator90:http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd13:resource_data968:<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      18:resource_data_type8:metadata16:resource_locator38:http://hdl.loc.gov/loc.gdc/lhbtn.122819:submitter19:NSDL 2 LR Data Pump14:submitter_type5:agente'''
        self.sampleJSON_sha256 = '''ef1b3b63adc663602c7a3c7595951b2761b34f5f6490ea1acee3df0fd97db03c'''
        
        self.sampleKeyLocations = [
                                   "http://example.com/mykey",
                                   "http://example2.com/mykey"
                                   ]
       
        
        self.signatureTemplate = '{{"key_location": [{0}], "key_owner": "'+self.goodowner+'", "signing_method": "LR-PGP.1.0", "signature": "{1}"}}'

    def tearDown(self):
        self.gpg.delete_keys([self.goodPrivateKey.fingerprint, ], secret=True)
        self.gpg.delete_keys([self.goodPrivateKey.fingerprint, ], secret=False)
        pass
        
    def testMissingPrivateKey(self):
        
        def missingKey():
            try:
                sign = Sign_0_21(self.badkeyid)
            except UnknownKeyException as e:
                assert e.keyid == self.badkeyid, "keyid in exception doesn't match key passed to sign."
                raise e
            
        self.assertRaises(UnknownKeyException, missingKey)

    def testPresentPrivateKey(self):
        sign = Sign_0_21(self.goodkeyid)
        assert sign.privateKeyID == self.goodkeyid 
        
    def testStrip(self):
        origJson = json.loads(self.sampleJSON)
        benchmark = json.loads(self.sampleJSON_strip)
        
        signer = Sign_0_21(self.goodkeyid)        
        stripJson = signer._stripEnvelope(origJson)
        assert benchmark == stripJson
        
    def testStripNormal(self):
        origJson = json.loads(self.sampleJSON)
        benchmark = json.loads(self.sampleJSON_strip_normal)
        
        signer = Sign_0_21(self.goodkeyid)        
        stripJson = signer._stripEnvelope(origJson)
        normalJson = signer._bnormal(stripJson)
        assert benchmark == normalJson
    
    def testStripNormalBencode(self):
        origJson = json.loads(self.sampleJSON)
        benchmark = self.sampleJSON_strip_normal_bencode
        
        signer = Sign_0_21(self.goodkeyid)        
        stripJson = signer._stripEnvelope(origJson)
        normalJson = signer._bnormal(stripJson)
        bencodeJson = signer._buildCanonicalString(normalJson)
        assert benchmark == bencodeJson
    
    def testStripNormalBencodeHash(self):
        origJson = json.loads(self.sampleJSON)
        benchmark = self.sampleJSON_sha256
        
        signer = Sign_0_21(self.goodkeyid)        
        stripJson = signer._stripEnvelope(origJson)
        normalJson = signer._bnormal(stripJson)
        bencodeJson = signer._buildCanonicalString(normalJson)
        hash = signer._hash(bencodeJson)
        assert benchmark == hash
        
    def testGetMessage(self):
        origJson = json.loads(self.sampleJSON)
        benchmark = self.sampleJSON_sha256
        
        signer = Sign_0_21(self.goodkeyid)
        message = signer.get_message(origJson)
        assert benchmark == message
    
    def testPrivateKeyOwner(self):
        benchmark = self.goodowner
        signer = Sign_0_21(self.goodkeyid)
        assert benchmark == signer._get_privatekey_owner()
    
    def testSigBlock(self):
        origJson = json.loads(self.sampleJSON)
        arbitrarySigdata = "ABCDEF0123456789-abcdef"
        arbitraryKeyLoc = self.sampleKeyLocations
        
        keyloc = ",".join(map(lambda x: '"{0}"'.format(x), arbitraryKeyLoc))
        benchmark = json.loads(self.signatureTemplate.format(keyloc, arbitrarySigdata))
        
        signer = Sign_0_21(self.goodkeyid, passphrase=self.goodpassphrase, publicKeyLocations=arbitraryKeyLoc)
        assert benchmark == signer._get_sig_block(arbitrarySigdata)
     
    def testSign(self):
        origJson = json.loads(self.sampleJSON)
        arbitraryKeyLoc = self.sampleKeyLocations
        
        signer = Sign_0_21(self.goodkeyid, passphrase=self.goodpassphrase, publicKeyLocations=arbitraryKeyLoc)
        signed = signer.sign(origJson)
        
        assert signed.has_key("digital_signature")
        
        sig = signed["digital_signature"]
        assert sig.has_key("signature")
        assert sig["signature"] != None and len(sig["signature"]) > 0
    
    def testSignUnicode(self):
        if self.testDataDir == None:
            log.info("Skipping test, test data directory not set.")
            return
        
        import codecs
        
        fileName = "2011-02-28Metadata1004.json"
        unsigned = json.load(codecs.open(os.path.join(self.testDataDir, fileName), "r", "utf-8-sig"))
        
        arbitraryKeyLoc = self.sampleKeyLocations
        
        signer = Sign_0_21(self.goodkeyid, passphrase=self.goodpassphrase, publicKeyLocations=arbitraryKeyLoc)
        signed = signer.sign(unsigned)
        
        assert signed.has_key("digital_signature")
        
        sig = signed["digital_signature"]
        assert sig.has_key("signature")
        assert sig["signature"] != None and len(sig["signature"]) > 0
        
    def testSignLRTestData(self):
        if self.testDataDir == None:
            log.info("Skipping test, test data directory not set.")
            return
        
        import codecs
        
        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"))
        
            arbitraryKeyLoc = self.sampleKeyLocations
            
            signer = Sign_0_21(self.goodkeyid, passphrase=self.goodpassphrase, publicKeyLocations=arbitraryKeyLoc)
            signed = signer.sign(unsigned)
            
            assert signed.has_key("digital_signature")
            
            sig = signed["digital_signature"]
            assert sig.has_key("signature")
            assert sig["signature"] != None and len(sig["signature"]) > 0
예제 #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 = "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"
예제 #7
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))
예제 #8
0
class Test(unittest.TestCase):
    '''Unit test cases for signing envelopes from the Learning Registry'''
    def __init__(self, methodName="runTest"):

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

        try:
            os.makedirs(self.gnupghome)
        except:
            pass

        self.gpg = None

        unittest.TestCase.__init__(self, methodName)

        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"]

    def setUp(self):
        now = time.localtime()
        now = calendar.timegm(now)
        self.goodEmail = "signTest-{0}@learningregistry.org".format(now)
        self.goodRealName = "Autogenerated Sign Test"
        self.goodpassphrase = "supersecret"

        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)

        input = self.gpg.gen_key_input(name_real=self.goodRealName,
                                       name_email=self.goodEmail,
                                       passphrase=self.goodpassphrase)
        self.goodPrivateKey = self.gpg.gen_key(input)

        privateKeyAvailable = False
        privateKeys = self.gpg.list_keys(secret=True)
        for skey in privateKeys:
            if skey["keyid"] == self.goodPrivateKey.fingerprint:
                privateKeyAvailable = True
                self.privateKeyInfo = skey
                break
            if skey["fingerprint"] == self.goodPrivateKey.fingerprint:
                privateKeyAvailable = True
                self.privateKeyInfo = skey
                break

        assert privateKeyAvailable == True, "Could not locate generated Private Key"

        self.goodkeyid = self.privateKeyInfo["keyid"]

        self.goodowner = self.privateKeyInfo["uids"][0]

        self.badkeyid = "XXXXXXXXXXXXXXXX"
        self.badpassphrase = "bad passphrase"

        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.sampleJSON__0_23_0 = '''
            {
                "_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"],
                "identity":{
                    "submitter_type":"agent",
                    "submitter":"NSDL 2 LR Data Pump"
                },
                "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",
                "payload_schema":["oai_dc"],
                "node_timestamp":"2011-03-14 13:36:04.617999",
                "doc_version":"0.23.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.sampleJSON__0_51_0 = '''
            {
                "_id":"00e3f67232e743b6bc2a079bd98ff55a",
                "_rev":"1-8163d32f6cc9996f2b7228d8b5db7962",
                "doc_type":"resource_data",
                "update_timestamp":"2014-04-01 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"],
                "identity":{
                    "submitter_type":"agent",
                    "submitter":"NSDL 2 LR Data Pump"
                },
                "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",
                "payload_schema":["oai_dc"],
                "node_timestamp":"2014-04-01 13:32:04.617999",
                "doc_version":"0.51.0",
                "create_timestamp":"2014-04-01 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.sampleJSON_no_coercion = '''
            {
                "_id":"00e3f67232e743b6bc2a079bd98ff55a",
                "_rev":"1-8163d32f6cc9996f2b7228d8b5db7962",
                "doc_type":"resource_data",
                "update_timestamp":"2011-03-14 13:36:04.617999",
                "resource_data": {
                    "name": "Test coersion",
                    "nullable": null,
                    "booleanT": true,
                    "booleanF": false
                },
                "keys":["United States--Description and travel.","eng"],
                "identity":{
                    "submitter_type":"agent",
                    "submitter":"NSDL 2 LR Data Pump"
                },
                "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",
                "payload_schema":["oai_dc"],
                "node_timestamp":"2011-03-14 13:36:04.617999",
                "doc_version":"0.23.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.sampleJSON_lossy_sha256 = [
            '''
            {
                "_id":"00e3f67232e743b6bc2a079bd98ff55a",
                "_rev":"1-8163d32f6cc9996f2b7228d8b5db7962",
                "doc_type":"resource_data",
                "update_timestamp":"2011-03-14 13:36:04.617999",
                "resource_data": {
                    "name": "Test Lossy"
                    "integer": 1
                },
                "keys":["United States--Description and travel.","eng"],
                "identity":{
                    "submitter_type":"agent",
                    "submitter":"NSDL 2 LR Data Pump"
                },
                "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",
                "payload_schema":["oai_dc"],
                "node_timestamp":"2011-03-14 13:36:04.617999",
                "doc_version":"0.23.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"
                }
            }
            ''', '''
            {
                "_id":"00e3f67232e743b6bc2a079bd98ff55a",
                "_rev":"1-8163d32f6cc9996f2b7228d8b5db7962",
                "doc_type":"resource_data",
                "update_timestamp":"2011-03-14 13:36:04.617999",
                "resource_data": {
                    "name": "Test Lossy"
                    "float": 1.1
                },
                "keys":["United States--Description and travel.","eng"],
                "identity":{
                    "submitter_type":"agent",
                    "submitter":"NSDL 2 LR Data Pump"
                },
                "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",
                "payload_schema":["oai_dc"],
                "node_timestamp":"2011-03-14 13:36:04.617999",
                "doc_version":"0.23.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"
                }
            }
            ''', '''
            {
                "_id":"00e3f67232e743b6bc2a079bd98ff55a",
                "_rev":"1-8163d32f6cc9996f2b7228d8b5db7962",
                "doc_type":"resource_data",
                "update_timestamp":"2011-03-14 13:36:04.617999",
                "resource_data": {
                    "name": "Test Lossy"
                    "max_int": 9007199254740990
                },
                "keys":["United States--Description and travel.","eng"],
                "identity":{
                    "submitter_type":"agent",
                    "submitter":"NSDL 2 LR Data Pump"
                },
                "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",
                "payload_schema":["oai_dc"],
                "node_timestamp":"2011-03-14 13:36:04.617999",
                "doc_version":"0.23.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"
                }
            }
            ''', '''
            {
                "_id":"00e3f67232e743b6bc2a079bd98ff55a",
                "_rev":"1-8163d32f6cc9996f2b7228d8b5db7962",
                "doc_type":"resource_data",
                "update_timestamp":"2011-03-14 13:36:04.617999",
                "resource_data": {
                    "name": "Test Lossy"
                    "min_int": -9007199254740990
                },
                "keys":["United States--Description and travel.","eng"],
                "identity":{
                    "submitter_type":"agent",
                    "submitter":"NSDL 2 LR Data Pump"
                },
                "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",
                "payload_schema":["oai_dc"],
                "node_timestamp":"2011-03-14 13:36:04.617999",
                "doc_version":"0.23.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.sampleJSON_strip = '''{"keys": ["United States--Description and travel.", "eng"], "TOS": {"submission_attribution": "unidentified", "submission_TOS": "http://example.com/tos/unknown"}, "payload_placement": "inline", "active": true, "resource_locator": "http://hdl.loc.gov/loc.gdc/lhbtn.12281", "doc_type": "resource_data", "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      ", "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_schema": ["oai_dc"], "doc_version": "0.10.0", "submitter": "NSDL 2 LR Data Pump"}'''
        self.sampleJSON_strip_normal = '''{"keys": ["United States--Description and travel.", "eng"], "TOS": {"submission_attribution": "unidentified", "submission_TOS": "http://example.com/tos/unknown"}, "payload_placement": "inline", "active": "true", "resource_locator": "http://hdl.loc.gov/loc.gdc/lhbtn.12281", "doc_type": "resource_data", "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      ", "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_schema": ["oai_dc"], "doc_version": "0.10.0", "submitter": "NSDL 2 LR Data Pump"}'''
        self.sampleJSON_strip_normal_bencode = '''d3:TOSd14:submission_TOS30:http://example.com/tos/unknown22:submission_attribution12:unidentifiede6:active4:true8:doc_type13:resource_data11:doc_version6:0.10.04:keysl38:United States--Description and travel.3:enge17:payload_placement6:inline14:payload_schemal6:oai_dce22:payload_schema_locator90:http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd13:resource_data968:<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      18:resource_data_type8:metadata16:resource_locator38:http://hdl.loc.gov/loc.gdc/lhbtn.122819:submitter19:NSDL 2 LR Data Pump14:submitter_type5:agente'''
        self.sampleJSON_sha256 = '''ef1b3b63adc663602c7a3c7595951b2761b34f5f6490ea1acee3df0fd97db03c'''

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

        self.signatureTemplate = '{{"key_location": [{0}], "key_owner": "' + self.goodowner + '", "signing_method": "LR-PGP.1.0", "signature": "{1}"}}'

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

    def testMissingPrivateKey(self):
        def missingKey():
            try:
                sign = Sign_0_21(self.badkeyid,
                                 gnupgHome=self.gnupgHome,
                                 gpgbin=self.gpgbin)
            except UnknownKeyException as e:
                assert e.keyid == self.badkeyid, "keyid in exception doesn't match key passed to sign."
                raise e

        self.assertRaises(UnknownKeyException, missingKey)

    def testPresentPrivateKey(self):
        sign = Sign_0_21(self.goodkeyid,
                         gnupgHome=self.gnupgHome,
                         gpgbin=self.gpgbin)
        assert sign.privateKeyID == self.goodkeyid

    def testStrip(self):
        origJson = json.loads(self.sampleJSON)
        benchmark = json.loads(self.sampleJSON_strip)

        signer = Sign_0_21(self.goodkeyid,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        stripJson = signer._stripEnvelope(origJson)
        assert benchmark == stripJson

    def testStripNormal(self):
        origJson = json.loads(self.sampleJSON)
        benchmark = json.loads(self.sampleJSON_strip_normal)

        signer = Sign_0_21(self.goodkeyid,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        stripJson = signer._stripEnvelope(origJson)
        normalJson = signer._bnormal(stripJson)
        assert benchmark == normalJson

    def testStripNormalBencode(self):
        origJson = json.loads(self.sampleJSON)
        benchmark = self.sampleJSON_strip_normal_bencode

        signer = Sign_0_21(self.goodkeyid,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        stripJson = signer._stripEnvelope(origJson)
        normalJson = signer._bnormal(stripJson)
        bencodeJson = signer._buildCanonicalString(normalJson)
        assert benchmark == bencodeJson

    def testStripNormalBencodeHash(self):
        origJson = json.loads(self.sampleJSON)
        benchmark = self.sampleJSON_sha256

        signer = Sign_0_21(self.goodkeyid,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        stripJson = signer._stripEnvelope(origJson)
        normalJson = signer._bnormal(stripJson)
        bencodeJson = signer._buildCanonicalString(normalJson)
        hashed = signer._hash(bencodeJson)
        assert benchmark == hashed

    def testKnownLossyHash(self):
        for idx, lossyJSON in enumerate(self.sampleJSON_lossy_sha256):
            origJson = json.loads(self.sampleJSON)

            signer = Sign_0_21(self.goodkeyid,
                               gnupgHome=self.gnupgHome,
                               gpgbin=self.gpgbin)
            stripJson = signer._stripEnvelope(origJson)
            normalJson = signer._bnormal(stripJson)
            bencodeJson = signer._buildCanonicalString(normalJson)
            hashed = signer._hash(bencodeJson)

            if idx > 0:
                assert prev_hashed == hashed, "Hashes should match - algorithm is lossy"
                assert prev_bencodeJson == bencodeJson, "Bencode strings should match - algorithm is lossy"

            prev_bencodeJson = bencodeJson
            prev_hashed = hashed

    def testGetMessage(self):
        origJson = json.loads(self.sampleJSON)
        benchmark = self.sampleJSON_sha256

        signer = Sign_0_21(self.goodkeyid,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        message = signer.get_message(origJson)
        assert benchmark == message

    def testPrivateKeyOwner(self):
        benchmark = self.goodowner
        signer = Sign_0_21(self.goodkeyid,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        assert benchmark == signer._get_privatekey_owner()

    def testSigBlock(self):
        origJson = json.loads(self.sampleJSON)
        arbitrarySigdata = "ABCDEF0123456789-abcdef"
        arbitraryKeyLoc = self.sampleKeyLocations

        keyloc = ",".join(['"{0}"'.format(x) for x in arbitraryKeyLoc])
        benchmark = json.loads(
            self.signatureTemplate.format(keyloc, arbitrarySigdata))

        signer = Sign_0_21(self.goodkeyid,
                           passphrase=self.goodpassphrase,
                           publicKeyLocations=arbitraryKeyLoc,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        assert benchmark == signer._get_sig_block(arbitrarySigdata)

    def testSignNoEnvelopeCoercion(self):
        origJson = json.loads(self.sampleJSON_no_coercion)
        arbitraryKeyLoc = self.sampleKeyLocations

        assert origJson["resource_data"]["nullable"] == None, "Expected null"
        assert origJson["resource_data"]["booleanT"] == True, "Expected true"
        assert origJson["resource_data"]["booleanF"] == False, "Expected false"

        signer = Sign_0_21(self.goodkeyid,
                           passphrase=self.goodpassphrase,
                           publicKeyLocations=arbitraryKeyLoc,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        signed = signer.sign(origJson)

        assert "digital_signature" in signed
        assert origJson["resource_data"]["nullable"] == None, "Expected null"
        assert origJson["resource_data"]["booleanT"] == True, "Expected true"
        assert origJson["resource_data"]["booleanF"] == False, "Expected false"

    def testSign_0_10__no_passthru(self):
        origJson = json.loads(self.sampleJSON)
        arbitraryKeyLoc = self.sampleKeyLocations

        signer = Sign_0_21(self.goodkeyid,
                           passphrase=self.goodpassphrase,
                           publicKeyLocations=arbitraryKeyLoc,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        signed = signer.sign(origJson)

        assert "digital_signature" in signed

        sig = signed["digital_signature"]
        assert "signature" in sig
        assert sig["signature"] != None and len(sig["signature"]) > 0

    def test_Sign__0_10__passthru(self):
        origJson = json.loads(self.sampleJSON)
        arbitraryKeyLoc = self.sampleKeyLocations

        signer = Sign_0_21(self.goodkeyid,
                           passphrase=self.goodpassphrase,
                           publicKeyLocations=arbitraryKeyLoc,
                           sign_everything=False,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        signed = signer.sign(origJson)

        assert "digital_signature" not in signed

        # sig = signed["digital_signature"]
        # assert sig.has_key("signature")
        # assert sig["signature"] != None and len(sig["signature"]) > 0

    def test_Sign__0_23__passthru(self):
        origJson = json.loads(self.sampleJSON__0_23_0)
        arbitraryKeyLoc = self.sampleKeyLocations

        signer = Sign_0_23(self.goodkeyid,
                           passphrase=self.goodpassphrase,
                           publicKeyLocations=arbitraryKeyLoc,
                           sign_everything=False,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        signed = signer.sign(origJson)

        assert "digital_signature" in signed
        sig = signed["digital_signature"]
        assert "signature" in sig
        assert sig["signature"] != None and len(sig["signature"]) > 0

    def test_Sign__0_23__no_passthru(self):
        origJson = json.loads(self.sampleJSON__0_23_0)
        arbitraryKeyLoc = self.sampleKeyLocations

        signer = Sign_0_23(self.goodkeyid,
                           passphrase=self.goodpassphrase,
                           publicKeyLocations=arbitraryKeyLoc,
                           sign_everything=True,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        signed = signer.sign(origJson)

        assert "digital_signature" in signed
        sig = signed["digital_signature"]
        assert "signature" in sig
        assert sig["signature"] != None and len(sig["signature"]) > 0

    def test_Sign__0_51__no_passthru(self):
        origJson = json.loads(self.sampleJSON__0_51_0)
        arbitraryKeyLoc = self.sampleKeyLocations

        signer = Sign_0_51(self.goodkeyid,
                           passphrase=self.goodpassphrase,
                           publicKeyLocations=arbitraryKeyLoc,
                           sign_everything=True,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        signed = signer.sign(origJson)

        assert "digital_signature" in signed
        sig = signed["digital_signature"]
        assert "signature" in sig
        assert sig["signature"] != None and len(sig["signature"]) > 0

    def testSignUnicode(self):
        if self.testDataUnicode == None:
            log.info("Skipping test, unicode test data file not set.")
            return

        import codecs

        # fileName = "2011-02-28Metadata1004.json"
        # unsigned = json.load(codecs.open(os.path.join(self.testDataDir, fileName), "r", "utf-8-sig"))
        unsigned = json.load(
            codecs.open(self.testDataUnicode, "r", "utf-8-sig"))

        arbitraryKeyLoc = self.sampleKeyLocations

        signer = Sign_0_21(self.goodkeyid,
                           passphrase=self.goodpassphrase,
                           publicKeyLocations=arbitraryKeyLoc,
                           gnupgHome=self.gnupgHome,
                           gpgbin=self.gpgbin)
        signed = signer.sign(unsigned)

        assert "digital_signature" in signed

        sig = signed["digital_signature"]
        assert "signature" in sig
        assert sig["signature"] != None and len(sig["signature"]) > 0

    def testSignLRTestData(self):
        if self.testDataDir == None:
            log.info("Skipping test, test data directory not set.")
            return

        import codecs

        # 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"))

                arbitraryKeyLoc = self.sampleKeyLocations

                signer = Sign_0_21(self.goodkeyid,
                                   passphrase=self.goodpassphrase,
                                   publicKeyLocations=arbitraryKeyLoc,
                                   gnupgHome=self.gnupgHome,
                                   gpgbin=self.gpgbin)
                signed = signer.sign(unsigned)

                assert "digital_signature" in signed

                sig = signed["digital_signature"]
                assert "signature" in sig
                assert sig["signature"] != None and len(sig["signature"]) > 0
예제 #9
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"
예제 #10
0
class OpenPgpFactory(GenericFactory):
    """Provides OpenPGP functionality based on GnuPG."""

    implements(ICipherModule)

    gpg_binary = Option(
        'crypto', 'gpg_binary', 'gpg',
        """GnuPG binary name, allows for full path too.

        Value 'gpg' is same default as in python-gnupg itself.
        For usual installations location of the gpg binary is auto-detected.
        """)
    gpg_home = Option(
        'crypto', 'gpg_home', '.gpg', """Directory containing keyring files.

        In case of wrong configuration missing keyring files without content
        will be created in the configured location, provided necessary
        write permssion is granted for the corresponding parent directory.
        """)
    priv_key = Option(
        'crypto', 'gpg_private_key', '',
        """Key ID of private key (last 8 chars or more).

        If unset, a private key will be selected from keyring automagicly.
        The password must be available i.e. provided by running gpg-agent
        (not yet available) or empty (security trade-off). No private key
        operation can happen before the key has been unlocked successfully.
        """)

    name = 'openpgp'
    _supported_keys = [
        'name_real', 'name_comment', 'name_email', 'key_type', 'key_length',
        'subkey_type', 'subkey_length', 'expire_date', 'passphrase'
    ]

    def __init__(self):
        try:
            from gnupg import GPG
        except ImportError:
            raise TracError(
                _("""Unable to load the python-gnupg module.
                              Please check and correct your installation."""))
        try:
            # Initialize the GnuPG instance.
            path = os.path.join(os.path.abspath(self.env.path), self.gpg_home)
            self.env.log.debug('Using GnuPG home dir: ' + str(path))
            self.gpg = GPG(gpgbinary=self.gpg_binary, gnupghome=path)
        except ValueError:
            raise TracError(
                _("""Missing the crypto binary. Please check and
                              set full path with option 'gpg_binary'."""))

    # IKeyVault methods

    def keys(self, private=False, id_only=False):
        """Returns the list of all available keys."""
        # DEVEL: Cache this for performance.
        if not id_only:
            return self.gpg.list_keys(private)  # same as gpg.list_keys(False)
        keys = []
        for key in self.gpg.list_keys(private):
            keys.append(key['fingerprint'])
        return keys

    def create_key(self, **kwargs):
        """Generate a new OpenPGP key pair."""
        # Sanitize input.
        for k in kwargs.keys():
            if k not in self._supported_keys:
                kwargs.pop(k)
        input_data = self.gpg.gen_key_input(**kwargs)
        try:
            return self.gpg.gen_key(input_data)
        except ValueError, e:
            return False, e
예제 #11
0
class OpenPgpFactory(GenericFactory):
    """Provides OpenPGP functionality based on GnuPG."""

    implements(ICipherModule)

    gpg_binary = Option('crypto', 'gpg_binary', 'gpg',
        """GnuPG binary name, allows for full path too.

        Value 'gpg' is same default as in python-gnupg itself.
        For usual installations location of the gpg binary is auto-detected.
        """)
    gpg_home = Option('crypto', 'gpg_home', '.gpg',
        """Directory containing keyring files.

        In case of wrong configuration missing keyring files without content
        will be created in the configured location, provided necessary
        write permssion is granted for the corresponding parent directory.
        """)
    priv_key = Option('crypto', 'gpg_private_key', '',
        """Key ID of private key (last 8 chars or more).

        If unset, a private key will be selected from keyring automagicly.
        The password must be available i.e. provided by running gpg-agent
        (not yet available) or empty (security trade-off). No private key
        operation can happen before the key has been unlocked successfully.
        """)

    name = 'openpgp'
    _supported_keys = ['name_real', 'name_comment', 'name_email',
                       'key_type',  'key_length',
                       'subkey_type', 'subkey_length',
                       'expire_date', 'passphrase']

    def __init__(self):
        try:
            from gnupg import GPG
        except ImportError:
            raise TracError(_("""Unable to load the python-gnupg module.
                              Please check and correct your installation."""))
        try:
            # Initialize the GnuPG instance.
            path = os.path.join(os.path.abspath(self.env.path), self.gpg_home)
            self.env.log.debug('Using GnuPG home dir: ' + str(path))
            self.gpg = GPG(gpgbinary=self.gpg_binary, gnupghome=path)
        except ValueError:
            raise TracError(_("""Missing the crypto binary. Please check and
                              set full path with option 'gpg_binary'."""))

    # IKeyVault methods

    def keys(self, private=False, id_only=False):
        """Returns the list of all available keys."""
        # DEVEL: Cache this for performance.
        if not id_only:
            return self.gpg.list_keys(private) # same as gpg.list_keys(False)
        keys = []
        for key in self.gpg.list_keys(private):
            keys.append(key['fingerprint'])
        return keys

    def create_key(self, **kwargs):
        """Generate a new OpenPGP key pair."""
        # Sanitize input.
        for k in kwargs.keys():
            if k not in self._supported_keys:
                kwargs.pop(k)
        input_data = self.gpg.gen_key_input(**kwargs)
        try:
            return self.gpg.gen_key(input_data)
        except ValueError, e:
            return False, e
예제 #12
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)
예제 #13
0
 def setUpClass(cls):
     super(TestGnuPGMessage, cls).setUpClass()
     gpg = GPG(gnupghome=settings.GNUPG_HOMEDIR)
     key_input = gpg.gen_key_input()
     gpg.gen_key(key_input)
예제 #14
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)]
예제 #15
0
 def gen(this):
   gpg=GPG(gnupghome=os.path.join(GNUPG_HOME,user.pk))
   input_data = gpg.gen_key_input(key_type="RSA", key_length=1024)
   key=gpg.gen_key(input_data)