'''
Copyright 2011 SRI International

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Created on May 6, 2011

@author: jklo
'''
import unittest, json, calendar, time, os, logging
from gnupg import GPG
from LRSignature.sign.Sign import Sign_0_21, Sign_0_23, Sign_0_51
from LRSignature.errors import UnknownKeyException
import types
import sys

log =  logging.getLogger(__name__)

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 config.has_key("global"):
                if config["global"].has_key("testdata") and os.path.exists(config["global"]["testdata"]):
                    self.testDataDir = config["global"]["testdata"]

                if config["global"].has_key("testdata_unicode") 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(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, 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 signed.has_key("digital_signature")
        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 signed.has_key("digital_signature")

        sig = signed["digital_signature"]
        assert sig.has_key("signature")
        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 not signed.has_key("digital_signature")

        # 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 signed.has_key("digital_signature")
        sig = signed["digital_signature"]
        assert sig.has_key("signature")
        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 signed.has_key("digital_signature")
        sig = signed["digital_signature"]
        assert sig.has_key("signature")
        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 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.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 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 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 signed.has_key("digital_signature")

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






if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testSigning']
    unittest.main()
