async def test_sign_unreadable_sig(aiohttp_client, response_obj): csc_session_info = csc_signer.CSCServiceSessionInfo('', 'foobar') auth_man = csc_signer.PrefetchedSADAuthorizationManager( csc_session_info=csc_session_info, credential_info=csc_signer.CSCCredentialInfo( signing_cert=TESTING_CA.get_cert(CertLabel('signer1')), chain=[], supported_mechanisms=frozenset({'sha256_rsa'}), max_batch_size=1, hash_pinning_required=False, response_data={}), csc_auth_info=csc_signer.CSCAuthorizationInfo(sad='')) async def fake_return(_request): return web.json_response(response_obj) app = web.Application() app.router.add_post('/csc/v1/signatures/signHash', fake_return) client = await aiohttp_client(app) signer = csc_signer.CSCSigner( client, auth_manager=auth_man, batch_size=1, batch_autocommit=False, client_data='Some client data, because why not') result = asyncio.create_task(signer.async_sign_raw(b'foobarbaz', 'sha256')) with pytest.raises(SigningError, match='Expected response with b64'): await asyncio.sleep(1) await signer.commit() try: result.cancel() await result except asyncio.CancelledError: pass
async def test_sign_mechanism_not_supported(): csc_session_info = csc_signer.CSCServiceSessionInfo( 'https://example.com', 'foobar') auth_man = csc_signer.PrefetchedSADAuthorizationManager( csc_session_info=csc_session_info, credential_info=csc_signer.CSCCredentialInfo( signing_cert=TESTING_CA.get_cert(CertLabel('signer1')), chain=[], supported_mechanisms=frozenset({'is_nonsense'}), max_batch_size=10, hash_pinning_required=False, response_data={}), csc_auth_info=csc_signer.CSCAuthorizationInfo(sad='')) # check expected failure for a signing attempt with pytest.raises(SigningError, match='No signing results available'): async with aiohttp.ClientSession() as session: signer = csc_signer.CSCSigner(session, auth_manager=auth_man) await signer.async_sign_raw(b'foobarbazquux', 'sha256') # check expected failure when fetching the signature mechanism directly with pytest.raises(SigningError, match='must be one of'): # noinspection PyTypeChecker signer = csc_signer.CSCSigner(None, auth_manager=auth_man) signer.get_signature_mechanism(digest_algorithm='sha256') # ...but overrides should still work # noinspection PyTypeChecker signer = csc_signer.CSCSigner(None, auth_manager=auth_man) signer.signature_mechanism = mech \ = algos.SignedDigestAlgorithm({'algorithm': 'sha256_rsa'}) assert signer.get_signature_mechanism(digest_algorithm='sha256') == mech
async def test_cert_provision_fail(): csc_session_info = csc_signer.CSCServiceSessionInfo( 'https://example.invalid', 'foobar') with pytest.raises(SigningError, match='Credential info request failed'): async with aiohttp.ClientSession() as session: await csc_signer.fetch_certs_in_csc_credential( session, csc_session_info=csc_session_info)
async def _set_up_dummy_client(aiohttp_client, require_hash_pinning=True): csc_session_info = csc_signer.CSCServiceSessionInfo( '', 'testing-ca/signer1') csc_dummy = CSCWithCertomancer( certomancer_config=CERTOMANCER, service_params=DummyServiceParams( hash_pinning_required=require_hash_pinning)) csc_dummy.register_routes() client = await aiohttp_client(csc_dummy.app) auth_man = CSCDummyClientAuthManager( client, session_info=csc_session_info, credential_info=await csc_signer.fetch_certs_in_csc_credential(client, csc_session_info)) return client, auth_man, csc_dummy
async def test_csc_placeholder_sig_size(): csc_session_info = csc_signer.CSCServiceSessionInfo( 'https://example.com', 'foobar') auth_man = csc_signer.PrefetchedSADAuthorizationManager( csc_session_info=csc_session_info, credential_info=csc_signer.CSCCredentialInfo( signing_cert=TESTING_CA.get_cert(CertLabel('signer1')), chain=[], supported_mechanisms=frozenset({'is_nonsense'}), max_batch_size=10, hash_pinning_required=False, response_data={}), csc_auth_info=csc_signer.CSCAuthorizationInfo(sad='')) # noinspection PyTypeChecker signer = csc_signer.CSCSigner(None, auth_manager=auth_man) await signer.async_sign_raw(b'foobarbazquux', 'sha256', dry_run=True)
async def test_sign_network_fail(): csc_session_info = csc_signer.CSCServiceSessionInfo( 'https://example.invalid', 'foobar') auth_man = csc_signer.PrefetchedSADAuthorizationManager( csc_session_info=csc_session_info, credential_info=csc_signer.CSCCredentialInfo( signing_cert=TESTING_CA.get_cert(CertLabel('signer1')), chain=[], supported_mechanisms=frozenset({'sha256_rsa'}), max_batch_size=10, hash_pinning_required=False, response_data={}), csc_auth_info=csc_signer.CSCAuthorizationInfo(sad='')) with pytest.raises(SigningError, match='No signing results available'): async with aiohttp.ClientSession() as session: signer = csc_signer.CSCSigner(session, auth_manager=auth_man) await signer.async_sign_raw(b'foobarbazquux', 'sha256')
async def test_fail_different_digest(): csc_session_info = csc_signer.CSCServiceSessionInfo('', 'foobar') auth_man = csc_signer.PrefetchedSADAuthorizationManager( csc_session_info=csc_session_info, credential_info=csc_signer.CSCCredentialInfo( signing_cert=TESTING_CA.get_cert(CertLabel('signer1')), chain=[], supported_mechanisms=frozenset({'sha256_rsa'}), max_batch_size=2, hash_pinning_required=False, response_data={}), csc_auth_info=csc_signer.CSCAuthorizationInfo(sad='')) # noinspection PyTypeChecker signer = csc_signer.CSCSigner(None, auth_manager=auth_man, batch_size=2) with pytest.raises(SigningError, match='same digest function'): result = asyncio.gather( signer.async_sign_raw(b'foobarbaz', 'sha256'), signer.async_sign_raw(b'foobarbazquux', 'sha512'), ) await result
def test_format_csc_auth_request(): # any old auth manager will do auth_man = csc_signer.PrefetchedSADAuthorizationManager( csc_session_info=csc_signer.CSCServiceSessionInfo( 'https://example.com', 'foobar'), credential_info=csc_signer.CSCCredentialInfo( signing_cert=TESTING_CA.get_cert(CertLabel('signer1')), chain=[], supported_mechanisms=frozenset(), max_batch_size=10, hash_pinning_required=False, response_data={}), csc_auth_info=csc_signer.CSCAuthorizationInfo(sad='')) result = auth_man.format_csc_auth_request( pin='1234', otp='123456', hash_b64s=[ 'Sa6Tcy/PjWP+HM51lmSYLb1bIxYfAH26hWGGKtyW0GM=', 'Sa6Tcy/PjWP+HM51lmSYLb1bIxYfAH26hWGGKtyW0GM=' ], description='baz', client_data='quux') assert result == { 'credentialID': 'foobar', 'numSignatures': 2, 'hash': [ 'Sa6Tcy/PjWP+HM51lmSYLb1bIxYfAH26hWGGKtyW0GM=', 'Sa6Tcy/PjWP+HM51lmSYLb1bIxYfAH26hWGGKtyW0GM=' ], 'PIN': '1234', 'OTP': '123456', 'description': 'baz', 'clientData': 'quux' }
async def test_sign_wrong_number_of_sigs(aiohttp_client): csc_session_info = csc_signer.CSCServiceSessionInfo('', 'foobar') auth_man = csc_signer.PrefetchedSADAuthorizationManager( csc_session_info=csc_session_info, credential_info=csc_signer.CSCCredentialInfo( signing_cert=TESTING_CA.get_cert(CertLabel('signer1')), chain=[], supported_mechanisms=frozenset({'sha256_rsa'}), max_batch_size=2, hash_pinning_required=False, response_data={}), csc_auth_info=csc_signer.CSCAuthorizationInfo(sad='')) async def fake_return(_request): return web.json_response( {'signatures': [ base64.b64encode(bytes(512)).decode('ascii'), ]}) app = web.Application() app.router.add_post('/csc/v1/signatures/signHash', fake_return) client = await aiohttp_client(app) signer = csc_signer.CSCSigner(client, auth_manager=auth_man, batch_size=2, batch_autocommit=False) result = asyncio.gather( signer.async_sign_raw(b'foobarbaz', 'sha256'), signer.async_sign_raw(b'foobarbazquux', 'sha256'), ) with pytest.raises(SigningError, match='Expected 2 signatures'): await asyncio.sleep(1) await signer.commit() try: result.cancel() await result except asyncio.CancelledError: pass