def test_verify_function(self): url = 'https://example.org/beths-robotics-badge.json' responses.add(responses.GET, url, body=test_components['2_0_basic_assertion'], status=200, content_type='application/ld+json') set_up_image_mock('https://example.org/beths-robot-badge.png') responses.add(responses.GET, 'https://w3id.org/openbadges/v2', body=test_components['openbadges_context'], status=200, content_type='application/ld+json') responses.add(responses.GET, 'https://example.org/robotics-badge.json', body=test_components['2_0_basic_badgeclass'], status=200, content_type='application/ld+json') set_up_image_mock(u'https://example.org/robotics-badge.png') responses.add(responses.GET, 'https://example.org/organization.json', body=test_components['2_0_basic_issuer'], status=200, content_type='application/ld+json') results = verify(url) self.assertEqual(results.get('input').get('value'), url) self.assertEqual(results.get('input').get('input_type'), 'url') self.assertEqual(len(results['report']['messages']), 0, "There should be no failing tasks.")
def test_can_full_verify_with_revocation_check(self): input_assertion = json.loads(test_components['2_0_basic_assertion']) input_assertion['verification'] = {'type': 'signed', 'creator': 'http://example.org/key1'} set_up_image_mock(u'https://example.org/beths-robot-badge.png') input_badgeclass = json.loads(test_components['2_0_basic_badgeclass']) set_up_image_mock(input_badgeclass['image']) revocation_list = { '@context': OPENBADGES_CONTEXT_V2_URI, 'id': 'http://example.org/revocationList', 'type': 'RevocationList', 'revokedAssertions': []} input_issuer = json.loads(test_components['2_0_basic_issuer']) input_issuer['revocationList'] = revocation_list['id'] input_issuer['publicKey'] = input_assertion['verification']['creator'] private_key = RSA.generate(2048) print("PKEY") print(private_key.publickey().exportKey('PEM').decode()) cryptographic_key_doc = { '@context': OPENBADGES_CONTEXT_V2_URI, 'id': input_assertion['verification']['creator'], 'type': 'CryptographicKey', 'owner': input_issuer['id'], 'publicKeyPem': private_key.publickey().exportKey('PEM').decode() } set_up_context_mock() for doc in [input_assertion, input_badgeclass, input_issuer, cryptographic_key_doc, revocation_list]: responses.add(responses.GET, doc['id'], json=doc, status=200) header = json.dumps({'alg': 'RS256'}) payload = json.dumps(input_assertion) encoded_separator = '.' if not sys.version[:3] < '3': encoded_separator = '.'.encode() encoded_header = b64encode(header.encode()) encoded_payload = b64encode(payload.encode()) else: encoded_header = b64encode(header) encoded_payload = b64encode(payload) signature = encoded_separator.join([ encoded_header, encoded_payload, jws.sign(header, payload, private_key, is_json=True) ]) response = verify(signature, use_cache=False) self.assertTrue(response['report']['valid'])
def test_verify_of_baked_image(self): url = 'https://example.org/beths-robotics-badge.json' png_badge = os.path.join(os.path.dirname(__file__), 'testfiles', 'public_domain_heart.png') responses.add(responses.GET, url, body=test_components['2_0_basic_assertion'], status=200, content_type='application/ld+json') set_up_image_mock(u'https://example.org/beths-robot-badge.png') responses.add(responses.GET, 'https://w3id.org/openbadges/v2', body=test_components['openbadges_context'], status=200, content_type='application/ld+json') responses.add(responses.GET, 'https://example.org/robotics-badge.json', body=test_components['2_0_basic_badgeclass'], status=200, content_type='application/ld+json') set_up_image_mock(u'https://example.org/robotics-badge.png') responses.add(responses.GET, 'https://example.org/organization.json', body=test_components['2_0_basic_issuer'], status=200, content_type='application/ld+json') with open(png_badge, 'rb') as image: baked_image = bake(image, test_components['2_0_basic_assertion']) responses.add(responses.GET, 'https://example.org/baked', body=baked_image.read(), content_type='image/png') results = verify(baked_image) # verify gets the JSON out of the baked image, and then detect_input_type # will reach out to the assertion URL to fetch the canonical assertion (thus, # we expect this to become an URL input type for the verifier). self.assertNotEqual(results, None) self.assertEqual(results.get('input').get('value'), url) self.assertEqual(results.get('input').get('input_type'), 'url') self.assertEqual(len(results['report']['messages']), 0, "There should be no failing tasks.") # Verify that the same result occurs when passing in the baked image url. another_result = verify('https://example.org/baked') self.assertTrue(another_result['report']['valid']) self.assertEqual(another_result['report']['validationSubject'], results['report']['validationSubject'])
def test_verify_badge_against_expected_profile(self): recipient_profile = {'email': '*****@*****.**'} url = 'https://example.org/beths-robotics-badge.json' assertion = json.loads(test_components['2_0_basic_assertion']) assertion['recipient']['identity'] = 'sha256$' + hashlib.sha256( recipient_profile['email'].encode('utf8') + assertion['recipient']['salt'].encode('utf8')).hexdigest() responses.add( responses.GET, url, body=json.dumps(assertion), status=200, content_type='application/ld+json' ) set_up_image_mock('https://example.org/beths-robot-badge.png') responses.add( responses.GET, 'https://w3id.org/openbadges/v2', body=test_components['openbadges_context'], status=200, content_type='application/ld+json' ) responses.add( responses.GET, 'https://example.org/robotics-badge.json', body=test_components['2_0_basic_badgeclass'], status=200, content_type='application/ld+json' ) set_up_image_mock('https://example.org/robotics-badge.png') responses.add( responses.GET, 'https://example.org/organization.json', body=test_components['2_0_basic_issuer'], status=200, content_type='application/ld+json' ) result = verification_store(url, recipient_profile) state = result.get_state() profile_verification_tasks = filter_tasks(state, name=VERIFY_RECIPIENT_IDENTIFIER) self.assertEqual(len(filter_failed_tasks(state)), 0) self.assertEqual(len(profile_verification_tasks), 1) self.assertTrue(profile_verification_tasks[0]['success']) recipient_profile = {'email': ['*****@*****.**', '*****@*****.**']} result = verification_store(url, recipient_profile) state = result.get_state() profile_verification_tasks = filter_tasks(state, name=VERIFY_RECIPIENT_IDENTIFIER) self.assertEqual(len(filter_failed_tasks(state)), 0) self.assertEqual(len(profile_verification_tasks), 1) self.assertTrue(profile_verification_tasks[0]['success'])
def test_can_full_verify_jws_signed_assertion(self): """ I can input a JWS string I can extract the Assertion from the input signature string and store it as the canonical version of the Assertion. I can discover and retrieve key information from the Assertion. I can Access the signing key I can verify the key is associated with the listed issuer Profile I can verify the JWS signature has been created by a key trusted to correspond to the issuer Profile Next: I can verify an assertion with an ephemeral embedded badgeclass as well """ input_assertion = json.loads(test_components['2_0_basic_assertion']) input_assertion['verification'] = {'type': 'signed', 'creator': 'http://example.org/key1'} set_up_image_mock(u'https://example.org/beths-robot-badge.png') input_badgeclass = json.loads(test_components['2_0_basic_badgeclass']) set_up_image_mock(input_badgeclass['image']) input_issuer = json.loads(test_components['2_0_basic_issuer']) input_issuer['publicKey'] = input_assertion['verification']['creator'] key = RSA.generate(2048) public_key_pem = key.publickey().export_key() cryptographic_key_doc = { '@context': OPENBADGES_CONTEXT_V2_URI, 'id': input_assertion['verification']['creator'], 'type': 'CryptographicKey', 'owner': input_issuer['id'], 'publicKeyPem': public_key_pem.decode() } set_up_context_mock() for doc in [input_badgeclass, input_issuer, cryptographic_key_doc]: responses.add(responses.GET, doc['id'], json=doc, status=200) signature = jws.sign(input_assertion, key, algorithm='RS256') response = verify(signature, use_cache=False) self.assertTrue(response['report']['valid'])
def test_can_full_verify_with_revocation_check(self): input_assertion = json.loads(test_components['2_0_basic_assertion']) input_assertion['verification'] = {'type': 'signed', 'creator': 'http://example.org/key1'} set_up_image_mock(u'https://example.org/beths-robot-badge.png') input_badgeclass = json.loads(test_components['2_0_basic_badgeclass']) set_up_image_mock(input_badgeclass['image']) revocation_list = { '@context': OPENBADGES_CONTEXT_V2_URI, 'id': 'http://example.org/revocationList', 'type': 'RevocationList', 'revokedAssertions': []} input_issuer = json.loads(test_components['2_0_basic_issuer']) input_issuer['revocationList'] = revocation_list['id'] input_issuer['publicKey'] = input_assertion['verification']['creator'] key = RSA.generate(2048) public_key_pem = key.publickey().export_key() cryptographic_key_doc = { '@context': OPENBADGES_CONTEXT_V2_URI, 'id': input_assertion['verification']['creator'], 'type': 'CryptographicKey', 'owner': input_issuer['id'], 'publicKeyPem': public_key_pem.decode() } set_up_context_mock() for doc in [input_assertion, input_badgeclass, input_issuer, cryptographic_key_doc, revocation_list]: responses.add(responses.GET, doc['id'], json=doc, status=200) header = {'alg': 'RS256'} payload = json.dumps(input_assertion).encode() signature = jws.sign(input_assertion, key, algorithm='RS256') response = verify(signature, use_cache=False) self.assertTrue(response['report']['valid'])
def test_can_full_verify_jws_signed_assertion(self): """ I can input a JWS string I can extract the Assertion from the input signature string and store it as the canonical version of the Assertion. I can discover and retrieve key information from the Assertion. I can Access the signing key I can verify the key is associated with the listed issuer Profile I can verify the JWS signature has been created by a key trusted to correspond to the issuer Profile Next: I can verify an assertion with an ephemeral embedded badgeclass as well """ input_assertion = json.loads(test_components['2_0_basic_assertion']) input_assertion['verification'] = {'type': 'signed', 'creator': 'http://example.org/key1'} set_up_image_mock(u'https://example.org/beths-robot-badge.png') input_badgeclass = json.loads(test_components['2_0_basic_badgeclass']) set_up_image_mock(input_badgeclass['image']) input_issuer = json.loads(test_components['2_0_basic_issuer']) input_issuer['publicKey'] = input_assertion['verification']['creator'] private_key = RSA.generate(2048) cryptographic_key_doc = { '@context': OPENBADGES_CONTEXT_V2_URI, 'id': input_assertion['verification']['creator'], 'type': 'CryptographicKey', 'owner': input_issuer['id'], 'publicKeyPem': private_key.publickey().exportKey('PEM').decode() } set_up_context_mock() for doc in [input_assertion, input_badgeclass, input_issuer, cryptographic_key_doc]: responses.add(responses.GET, doc['id'], json=doc, status=200) header = json.dumps({'alg': 'RS256'}) payload = json.dumps(input_assertion) encoded_separator = '.' if not sys.version[:3] < '3': encoded_separator = '.'.encode() encoded_header = b64encode(header.encode()) encoded_payload = b64encode(payload.encode()) else: encoded_header = b64encode(header) encoded_payload = b64encode(payload) signature = encoded_separator.join([ encoded_header, encoded_payload, jws.sign(header,payload,private_key, is_json=True) ]) response = verify(signature, use_cache=False) print("TEST CAN FULLY VERIFY JWS SIGNED ASSERTION : response:") print(response['report']) self.assertTrue(response['report']['valid'])