mirror of https://github.com/nucypher/nucypher.git
Refactor to use new RevocationKit
parent
88054ecc8f
commit
0ddfa230de
|
@ -170,22 +170,27 @@ class Alice(Character, PolicyAuthor):
|
|||
Parses the treasure map and revokes arrangements in it.
|
||||
If any arrangements can't be revoked (other than a 404 status), then
|
||||
the node_id and arrangement_id are added to a list and returned.
|
||||
|
||||
TODO: How do we tell the user that a revocation was successful or not?
|
||||
"""
|
||||
failed_revocations = list()
|
||||
for node_id, arrangement_id in policy.treasure_map:
|
||||
# TODO: What about nodes we don't know about?
|
||||
ursula = self._known_nodes[node_id]
|
||||
try:
|
||||
self.network_middleware.revoke_arrangement(ursula, arrangement_id)
|
||||
except RuntimeError as e:
|
||||
# Check the status code of the response to determine what to do
|
||||
# TODO: What do we do in the event of a 404? Is there are way
|
||||
# to check if it's a real 404 and not SuspiciousActivity?
|
||||
if e[1] != 404:
|
||||
failed_revocations.append((node_id, arrangement_id))
|
||||
continue
|
||||
# Sign the revocations in the RevocationKit in preparation for
|
||||
# sending to Ursula.
|
||||
policy.revocation_kit.sign_revocations(self.stamp)
|
||||
|
||||
try:
|
||||
# Wait for a revocation threshold of nodes to be known ((n - m) + 1)
|
||||
revocation_threshold = ((policy.n - policy.treasure_map.m) + 1)
|
||||
self.block_until_specific_nodes_are_known(
|
||||
policy.revocation_kit.revokable_addresses,
|
||||
allow_missing=revocation_threshold)
|
||||
except self.NotEnoughTeachers as e:
|
||||
raise e
|
||||
else:
|
||||
failed_revocations = list()
|
||||
for node_id in policy.revocation_kit.revokable_addresses:
|
||||
ursula = self.known_nodes[node_id]
|
||||
revocation = policy.revocation_kit[node_id]
|
||||
response = self.network_middleware.revoke_arrangement(ursula, revocation)
|
||||
if response.status_code != 200:
|
||||
failed_revocations.append(notice)
|
||||
return failed_revocations
|
||||
|
||||
|
||||
|
|
|
@ -261,15 +261,27 @@ class ProxyRESTRoutes:
|
|||
TODO: How do we want to verify that this request comes from Alice?
|
||||
What/How is she going to sign?
|
||||
"""
|
||||
arrangement_id = request.body
|
||||
from nucypher.crypto.kits import RevocationKit
|
||||
|
||||
revocation = RevocationKit.revocation_from_bytes(request.body)
|
||||
try:
|
||||
with ThreadedSession(self.db_engine) as session:
|
||||
self.datastore.del_policy_arrangement(
|
||||
arrangement_id,
|
||||
session=session)
|
||||
except NotFound:
|
||||
return 404 # TODO: Should we 404 or do something else?
|
||||
return 200
|
||||
# Verify the Notice was signed by Alice
|
||||
policy_arrangement = self.datastore.get_policy_arrangement(
|
||||
id_as_hex.encode(), session=session)
|
||||
alice_pubkey = UmbralPublicKey.from_bytes(
|
||||
policy_arrangement.alice_pubkey_sig.key_data)
|
||||
|
||||
# Check that the request is the same for the provided revocation
|
||||
if not id_as_hex.encode() == revocation.arrangement_id:
|
||||
return 400
|
||||
elif RevocationKit.verify_revocation(revocation, alice_pubkey):
|
||||
self.datastore.del_policy_arrangement(
|
||||
id_as_hex.encode(), session=session)
|
||||
except (NotFound, InvalidSignature):
|
||||
return 404
|
||||
else:
|
||||
return 200
|
||||
|
||||
def reencrypt_via_rest(self, id_as_hex, request: http.Request):
|
||||
from nucypher.policy.models import WorkOrder # Avoid circular import
|
||||
|
|
|
@ -248,6 +248,9 @@ class Policy:
|
|||
self.treasure_map.add_arrangement(arrangement)
|
||||
|
||||
else: # ...After *all* the policies are enacted
|
||||
# Create Alice's revocation kit
|
||||
self.revocation_kit = RevocationKit(self.treasure_map)
|
||||
|
||||
if publish is True:
|
||||
return self.publish(network_middleware)
|
||||
|
||||
|
|
|
@ -14,9 +14,12 @@ GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
from apistar import TestClient
|
||||
|
||||
from nucypher.characters.lawful import Ursula
|
||||
from nucypher.crypto.kits import RevocationKit
|
||||
from nucypher.network.middleware import RestMiddleware
|
||||
from nucypher.utilities.sandbox.constants import TEST_KNOWN_URSULAS_CACHE
|
||||
|
||||
|
@ -107,6 +110,18 @@ class MockRestMiddleware(RestMiddleware):
|
|||
data=map_payload, verify=certificate_filepath)
|
||||
return response
|
||||
|
||||
def revoke_arrangement(self, ursula, revocation):
|
||||
mock_client = self._get_mock_client_by_ursula(ursula)
|
||||
response = mock_client.delete('http://localhost/kFrag/{}'.format(
|
||||
revocation.arrangement_id.hex()),
|
||||
data=RevocationKit.revocation_to_bytes(revocation))
|
||||
|
||||
if response.status_code != 200:
|
||||
if response.status_code == 404:
|
||||
raise RuntimeError("KFrag doesn't exist to revoke with id {}".format(arrangement_id))
|
||||
raise RuntimeError("Bad response: {}".format(response.status_code))
|
||||
return response
|
||||
|
||||
|
||||
class EvilMiddleWare(MockRestMiddleware):
|
||||
"""
|
||||
|
|
|
@ -27,6 +27,7 @@ from nucypher.characters.lawful import Bob, Ursula
|
|||
from nucypher.config.characters import AliceConfiguration
|
||||
from nucypher.config.storages import LocalFileBasedNodeStorage
|
||||
from nucypher.crypto.api import keccak_digest
|
||||
from nucypher.crypto.kits import RevocationKit
|
||||
from nucypher.crypto.powers import SigningPower, DelegatingPower, EncryptingPower
|
||||
from nucypher.utilities.sandbox.constants import TEST_URSULA_INSECURE_DEVELOPMENT_PASSWORD
|
||||
from nucypher.utilities.sandbox.middleware import MockRestMiddleware
|
||||
|
|
Loading…
Reference in New Issue