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 __init__(self, gpgbin="/usr/local/bin/gpg", gnupgHome=os.path.expanduser(os.path.join("~", ".gnupg"))): ''' Constructor ''' self.gnupgHome = gnupgHome self.gpgbin = gpgbin Sign_0_21.__init__(self, privateKeyID=None, passphrase=None, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin, publicKeyLocations=[])
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
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 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 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 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"
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
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 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 _get_signer_for_version(version, private_key): if version == "0.21.0": return Sign_0_21(privateKeyID=private_key, gpgbin=gpg_location) elif version == "0.23.0": return Sign_0_23(privateKeyID=private_key, gpgbin=gpg_location) elif version == "0.49.0": return Sign_0_49(privateKeyID=private_key, gpgbin=gpg_location) elif version == "0.51.0": return Sign_0_51(privateKeyID=private_key, gpgbin=gpg_location)
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 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
def __init__(self, options): self.options = options self.server = 'https://' + options['host'] + '/' self.identity = options['identity'] if options['key'] is not None and options['key_location'] is not None: self.signer = Sign_0_21( privateKeyID=options['key'], publicKeyLocations=[options['key_location']], passphrase=options['passphrase'], gpgbin=options['gpgbin']) else: self.signer = None
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 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 test_Sign__0_23__no_passthru(self): origJson = json.loads(self.sampleJSON__0_23_0) arbitraryKeyLoc = self.sampleKeyLocations signer = Sign_0_21(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 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 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 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 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 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 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 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 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 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 writeTestData(obj, **kw): try: key = kw["pgp_keys"][0] signer = Sign_0_21(privateKeyID=key["fingerprint"], passphrase=key["passphrase"], gnupgHome=kw["gnupghome"], gpgbin=kw["gpgbin"], publicKeyLocations=key["locations"]) except: signer = None if not hasattr(obj, "test_data_ids"): obj.test_data_ids = {} obj.test_data_ids[prefix] = [] with open(test_data_log, "w") as plog: for doc in sourceData: if "doc_ID" not in doc: doc["doc_ID"] = prefix + str(uuid1()) try: doc = signer.sign(doc) except: pass obj.app.post('/publish', params=json.dumps({"documents": [doc]}), headers=json_headers) plog.write(doc["doc_ID"] + os.linesep) obj.test_data_ids[prefix].append(doc["doc_ID"]) if sleep > 0: time.sleep(sleep) kw["test_data_ids"] = obj.test_data_ids[prefix] return kw
parser.add_argument( '--data-dir', help= 'Directory of source LR Data Envelopes. Overrides root_path in [upload] from configuration file"', default=None) parser.add_argument('--lr-test-data', help='Publish as lr test data, default is True', default="True") parser.add_argument('--config', help='Configuration file, default is "testconfig.ini"', default="testconfig.ini") args = parser.parse_args() if args.key is not None and args.key_location is not None: signer = Sign_0_21(privateKeyID=args.key, publicKeyLocations=[args.key_location], passphrase=args.passphrase, gpgbin=args.gpgbin) _config = ConfigParser.ConfigParser() _config.read(args.config) root_path = _config.get("upload", "root_path") publish_url = _config.get("upload", "publish_url") publish_urls = [ 'http://lrdev1.learningregistry.org/publish', 'http://lrdev2.learningregistry.org/publish', 'http://lrdev3.learningregistry.org/publish' ] lr_test_data = args.lr_test_data.lower() in ["true", "t", "yes" "1"] if args.publish_url != None: publish_url = args.publish_url
def testPrivateKeyOwner(self): benchmark = self.goodowner signer = Sign_0_21(self.goodkeyid, gnupgHome=self.gnupgHome, gpgbin=self.gpgbin) assert benchmark == signer._get_privatekey_owner()