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_prefetched_sad_not_twice(aiohttp_client): client, auth_man, csc_dummy = await _set_up_dummy_client( aiohttp_client, require_hash_pinning=False) # prefetch SAD that is not bound to any hashes async with client.post('/csc/v1/credentials/authorize', json=auth_man.format_csc_auth_request(), raise_for_status=True) as resp: sad = (await resp.json())['SAD'] auth_man = csc_signer.PrefetchedSADAuthorizationManager( csc_session_info=auth_man.csc_session_info, credential_info=auth_man.credential_info, csc_auth_info=csc_signer.CSCAuthorizationInfo(sad=sad)) signer = csc_signer.CSCSigner( session=client, auth_manager=auth_man, batch_autocommit=True, batch_size=1, ) result = await signer.async_sign_raw(b'foobar', digest_algorithm='sha256') signer_cert = TESTING_CA.get_cert(CertLabel('signer1')) _validate_raw(result, b'foobar', signer_cert, signature_algorithm=algos.SignedDigestAlgorithm( {'algorithm': 'sha256_rsa'}), md_algorithm='sha256') # but a second attempt should fail with pytest.raises(SigningError, match='No signing results'): await signer.async_sign_raw(b'foobar', digest_algorithm='sha256')
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_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_csc_with_parameters(aiohttp_client): # produce a signature with parameters client, auth_man, csc_dummy = await _set_up_dummy_client(aiohttp_client) signer = csc_signer.CSCSigner(session=client, auth_manager=auth_man, batch_autocommit=True, batch_size=1, prefer_pss=True) result = await signer.async_sign_raw(b'foobar', digest_algorithm='sha256') signer_cert = TESTING_CA.get_cert(CertLabel('signer1')) mech = signer.get_signature_mechanism('sha256') assert mech.signature_algo == 'rsassa_pss' _validate_raw(result, b'foobar', signer_cert, signature_algorithm=mech, md_algorithm='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
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