Create abstract Verifier and Signer, remove key_id hack from App Engine and IAM signers (#115)

diff --git a/tests/oauth2/test_service_account.py b/tests/oauth2/test_service_account.py
index f40ebf2..8ae545a 100644
--- a/tests/oauth2/test_service_account.py
+++ b/tests/oauth2/test_service_account.py
@@ -44,7 +44,7 @@
 
 @pytest.fixture(scope='module')
 def signer():
-    return crypt.Signer.from_string(PRIVATE_KEY_BYTES, '1')
+    return crypt.RSASigner.from_string(PRIVATE_KEY_BYTES, '1')
 
 
 class TestCredentials(object):
diff --git a/tests/test__service_account_info.py b/tests/test__service_account_info.py
index 4caea95..5466865 100644
--- a/tests/test__service_account_info.py
+++ b/tests/test__service_account_info.py
@@ -31,7 +31,7 @@
 
 def test_from_dict():
     signer = _service_account_info.from_dict(SERVICE_ACCOUNT_INFO)
-    assert isinstance(signer, crypt.Signer)
+    assert isinstance(signer, crypt.RSASigner)
     assert signer.key_id == SERVICE_ACCOUNT_INFO['private_key_id']
 
 
@@ -59,5 +59,5 @@
     for key, value in six.iteritems(SERVICE_ACCOUNT_INFO):
         assert info[key] == value
 
-    assert isinstance(signer, crypt.Signer)
+    assert isinstance(signer, crypt.RSASigner)
     assert signer.key_id == SERVICE_ACCOUNT_INFO['private_key_id']
diff --git a/tests/test_app_engine.py b/tests/test_app_engine.py
index af60bcf..d3a79d5 100644
--- a/tests/test_app_engine.py
+++ b/tests/test_app_engine.py
@@ -48,7 +48,7 @@
 
         signer = app_engine.Signer()
 
-        assert signer.key_id == mock.sentinel.key_id
+        assert signer.key_id is None
 
     def test_sign(self, app_identity_mock):
         app_identity_mock.sign_blob.return_value = (
diff --git a/tests/test_crypt.py b/tests/test_crypt.py
index 9671230..56612da 100644
--- a/tests/test_crypt.py
+++ b/tests/test_crypt.py
@@ -69,7 +69,7 @@
 
 def test_verify_signature():
     to_sign = b'foo'
-    signer = crypt.Signer.from_string(PRIVATE_KEY_BYTES)
+    signer = crypt.RSASigner.from_string(PRIVATE_KEY_BYTES)
     signature = signer.sign(to_sign)
 
     assert crypt.verify_signature(
@@ -82,57 +82,57 @@
 
 def test_verify_signature_failure():
     to_sign = b'foo'
-    signer = crypt.Signer.from_string(PRIVATE_KEY_BYTES)
+    signer = crypt.RSASigner.from_string(PRIVATE_KEY_BYTES)
     signature = signer.sign(to_sign)
 
     assert not crypt.verify_signature(
         to_sign, signature, OTHER_CERT_BYTES)
 
 
-class TestVerifier(object):
+class TestRSAVerifier(object):
     def test_verify_success(self):
         to_sign = b'foo'
-        signer = crypt.Signer.from_string(PRIVATE_KEY_BYTES)
+        signer = crypt.RSASigner.from_string(PRIVATE_KEY_BYTES)
         actual_signature = signer.sign(to_sign)
 
-        verifier = crypt.Verifier.from_string(PUBLIC_KEY_BYTES)
+        verifier = crypt.RSAVerifier.from_string(PUBLIC_KEY_BYTES)
         assert verifier.verify(to_sign, actual_signature)
 
     def test_verify_unicode_success(self):
         to_sign = u'foo'
-        signer = crypt.Signer.from_string(PRIVATE_KEY_BYTES)
+        signer = crypt.RSASigner.from_string(PRIVATE_KEY_BYTES)
         actual_signature = signer.sign(to_sign)
 
-        verifier = crypt.Verifier.from_string(PUBLIC_KEY_BYTES)
+        verifier = crypt.RSAVerifier.from_string(PUBLIC_KEY_BYTES)
         assert verifier.verify(to_sign, actual_signature)
 
     def test_verify_failure(self):
-        verifier = crypt.Verifier.from_string(PUBLIC_KEY_BYTES)
+        verifier = crypt.RSAVerifier.from_string(PUBLIC_KEY_BYTES)
         bad_signature1 = b''
         assert not verifier.verify(b'foo', bad_signature1)
         bad_signature2 = b'a'
         assert not verifier.verify(b'foo', bad_signature2)
 
     def test_from_string_pub_key(self):
-        verifier = crypt.Verifier.from_string(PUBLIC_KEY_BYTES)
-        assert isinstance(verifier, crypt.Verifier)
+        verifier = crypt.RSAVerifier.from_string(PUBLIC_KEY_BYTES)
+        assert isinstance(verifier, crypt.RSAVerifier)
         assert isinstance(verifier._pubkey, rsa.key.PublicKey)
 
     def test_from_string_pub_key_unicode(self):
         public_key = _helpers.from_bytes(PUBLIC_KEY_BYTES)
-        verifier = crypt.Verifier.from_string(public_key)
-        assert isinstance(verifier, crypt.Verifier)
+        verifier = crypt.RSAVerifier.from_string(public_key)
+        assert isinstance(verifier, crypt.RSAVerifier)
         assert isinstance(verifier._pubkey, rsa.key.PublicKey)
 
     def test_from_string_pub_cert(self):
-        verifier = crypt.Verifier.from_string(PUBLIC_CERT_BYTES)
-        assert isinstance(verifier, crypt.Verifier)
+        verifier = crypt.RSAVerifier.from_string(PUBLIC_CERT_BYTES)
+        assert isinstance(verifier, crypt.RSAVerifier)
         assert isinstance(verifier._pubkey, rsa.key.PublicKey)
 
     def test_from_string_pub_cert_unicode(self):
         public_cert = _helpers.from_bytes(PUBLIC_CERT_BYTES)
-        verifier = crypt.Verifier.from_string(public_cert)
-        assert isinstance(verifier, crypt.Verifier)
+        verifier = crypt.RSAVerifier.from_string(public_cert)
+        assert isinstance(verifier, crypt.RSAVerifier)
         assert isinstance(verifier._pubkey, rsa.key.PublicKey)
 
     def test_from_string_pub_cert_failure(self):
@@ -144,25 +144,25 @@
 
         with load_pem_patch as load_pem:
             with pytest.raises(ValueError):
-                crypt.Verifier.from_string(cert_bytes)
+                crypt.RSAVerifier.from_string(cert_bytes)
             load_pem.assert_called_once_with(cert_bytes, 'CERTIFICATE')
 
 
-class TestSigner(object):
+class TestRSASigner(object):
     def test_from_string_pkcs1(self):
-        signer = crypt.Signer.from_string(PKCS1_KEY_BYTES)
-        assert isinstance(signer, crypt.Signer)
+        signer = crypt.RSASigner.from_string(PKCS1_KEY_BYTES)
+        assert isinstance(signer, crypt.RSASigner)
         assert isinstance(signer._key, rsa.key.PrivateKey)
 
     def test_from_string_pkcs1_unicode(self):
         key_bytes = _helpers.from_bytes(PKCS1_KEY_BYTES)
-        signer = crypt.Signer.from_string(key_bytes)
-        assert isinstance(signer, crypt.Signer)
+        signer = crypt.RSASigner.from_string(key_bytes)
+        assert isinstance(signer, crypt.RSASigner)
         assert isinstance(signer._key, rsa.key.PrivateKey)
 
     def test_from_string_pkcs8(self):
-        signer = crypt.Signer.from_string(PKCS8_KEY_BYTES)
-        assert isinstance(signer, crypt.Signer)
+        signer = crypt.RSASigner.from_string(PKCS8_KEY_BYTES)
+        assert isinstance(signer, crypt.RSASigner)
         assert isinstance(signer._key, rsa.key.PrivateKey)
 
     def test_from_string_pkcs8_extra_bytes(self):
@@ -179,28 +179,29 @@
 
         with decode_patch as decode:
             with pytest.raises(ValueError):
-                crypt.Signer.from_string(key_bytes)
+                crypt.RSASigner.from_string(key_bytes)
             # Verify mock was called.
             decode.assert_called_once_with(
                 pem_bytes, asn1Spec=crypt._PKCS8_SPEC)
 
     def test_from_string_pkcs8_unicode(self):
         key_bytes = _helpers.from_bytes(PKCS8_KEY_BYTES)
-        signer = crypt.Signer.from_string(key_bytes)
-        assert isinstance(signer, crypt.Signer)
+        signer = crypt.RSASigner.from_string(key_bytes)
+        assert isinstance(signer, crypt.RSASigner)
         assert isinstance(signer._key, rsa.key.PrivateKey)
 
     def test_from_string_pkcs12(self):
         with pytest.raises(ValueError):
-            crypt.Signer.from_string(PKCS12_KEY_BYTES)
+            crypt.RSASigner.from_string(PKCS12_KEY_BYTES)
 
     def test_from_string_bogus_key(self):
         key_bytes = 'bogus-key'
         with pytest.raises(ValueError):
-            crypt.Signer.from_string(key_bytes)
+            crypt.RSASigner.from_string(key_bytes)
 
     def test_from_service_account_info(self):
-        signer = crypt.Signer.from_service_account_info(SERVICE_ACCOUNT_INFO)
+        signer = crypt.RSASigner.from_service_account_info(
+            SERVICE_ACCOUNT_INFO)
 
         assert signer.key_id == SERVICE_ACCOUNT_INFO[
             crypt._JSON_FILE_PRIVATE_KEY_ID]
@@ -208,12 +209,12 @@
 
     def test_from_service_account_info_missing_key(self):
         with pytest.raises(ValueError) as excinfo:
-            crypt.Signer.from_service_account_info({})
+            crypt.RSASigner.from_service_account_info({})
 
         assert excinfo.match(crypt._JSON_FILE_PRIVATE_KEY)
 
     def test_from_service_account_file(self):
-        signer = crypt.Signer.from_service_account_file(
+        signer = crypt.RSASigner.from_service_account_file(
             SERVICE_ACCOUNT_JSON_FILE)
 
         assert signer.key_id == SERVICE_ACCOUNT_INFO[
diff --git a/tests/test_iam.py b/tests/test_iam.py
index 5ac9911..f776788 100644
--- a/tests/test_iam.py
+++ b/tests/test_iam.py
@@ -64,16 +64,12 @@
                 mock.sentinel.service_account_email)
 
     def test_key_id(self):
-        key_id = '123'
-        request = make_request(http_client.OK, data={'keyId': key_id})
-        credentials = make_credentials()
-
         signer = iam.Signer(
-            request, credentials, mock.sentinel.service_account_email)
+            mock.sentinel.request,
+            mock.sentinel.credentials,
+            mock.sentinel.service_account_email)
 
-        assert signer.key_id == '123'
-        auth_header = request.call_args[1]['headers']['authorization']
-        assert auth_header == 'Bearer token'
+        assert signer.key_id is None
 
     def test_sign_bytes(self):
         signature = b'DEADBEEF'
diff --git a/tests/test_jwt.py b/tests/test_jwt.py
index e4a9a0a..df09ece 100644
--- a/tests/test_jwt.py
+++ b/tests/test_jwt.py
@@ -44,7 +44,7 @@
 
 @pytest.fixture
 def signer():
-    return crypt.Signer.from_string(PRIVATE_KEY_BYTES, '1')
+    return crypt.RSASigner.from_string(PRIVATE_KEY_BYTES, '1')
 
 
 def test_encode_basic(signer):
@@ -78,7 +78,7 @@
         # False is specified to remove the signer's key id for testing
         # headers without key ids.
         if key_id is False:
-            signer.key_id = None
+            signer._key_id = None
             key_id = None
 
         return jwt.encode(signer, payload, key_id=key_id)
@@ -265,7 +265,7 @@
         assert crypt.verify_signature(to_sign, signature, PUBLIC_CERT_BYTES)
 
     def test_signer(self):
-        assert isinstance(self.credentials.signer, crypt.Signer)
+        assert isinstance(self.credentials.signer, crypt.RSASigner)
 
     def test_signer_email(self):
         assert (self.credentials.signer_email ==