Skip to content

Commit

Permalink
restore verify receipt and improve output format from register statem…
Browse files Browse the repository at this point in the history
…ent (#47)

* update to work with improved outputformat from samples register

* fix: formatting

* sort out a rebase issue

* remove unused imports

* add info telementry for ci flaky failures

* always print the result on success

* remove vestigial DID reference

* fix: terminate imediately for operation failed

* fix: don't mask backend errors

The backend should always write compliant response codes.
This change removes a work around for the case where it failed to
correctly set 202

---------

Co-authored-by: Robin Bryce <[email protected]>
  • Loading branch information
robinbryce and Robin Bryce authored Dec 11, 2024
1 parent 06f5cab commit d74bbe0
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 198 deletions.
26 changes: 17 additions & 9 deletions datatrails_scitt_samples/scripts/register_signed_statement.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
a Transparent Statement"""

import sys
import json
import argparse
from pycose.messages import Sign1Message

Expand Down Expand Up @@ -103,17 +104,20 @@ def main(args=None):
op_id = submit_statement_from_file(ctx, args.signed_statement_file)
ctx.info("Successfully submitted with Operation ID %s", op_id)

# Always wait for registration to complete
ctx.info("Waiting for registration to complete")
# Wait for the registration to complete
try:
entry_id = wait_for_entry_id(ctx, op_id)
except TimeoutError as e:
ctx.error(e)
sys.exit(1)
ctx.info("Fully Registered with Entry ID %s", entry_id)

result = {"entryid": entry_id}

# If the client wants the Transparent Statement or receipt, wait for registration to complete
if args.verify or args.output_file != "":
ctx.info("Waiting for registration to complete")
# Wait for the registration to complete
try:
entry_id = wait_for_entry_id(ctx, op_id)
except TimeoutError as e:
ctx.error(e)
sys.exit(1)
ctx.info("Fully Registered with Entry ID %s", entry_id)

leaf = get_leaf_hash(ctx, entry_id)
# Notice: the leaf hash corresponds to the leaf hash visible in the UI
ctx.info("Leaf Hash: %s", leaf.hex())
Expand All @@ -128,8 +132,10 @@ def main(args=None):
if not verify_receipt_mmriver(receipt, leaf):
ctx.info("Receipt verification failed")
sys.exit(1)
result["leaf"] = leaf.hex()

if args.output_file == "":
print(json.dumps(result))
return

if args.output_receipt_file != "":
Expand All @@ -141,6 +147,8 @@ def main(args=None):
attach_receipt(receipt, args.signed_statement_file, args.output_file)
ctx.info(f"File saved successfully {args.output_file}")

print(json.dumps(result))


if __name__ == "__main__":
main()
141 changes: 141 additions & 0 deletions datatrails_scitt_samples/scripts/verify_receipt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
"""Module for verifying the counter signed receipt signature"""

import argparse
import sys
import json

from pycose.messages import Sign1Message

from datatrails_scitt_samples.cose_receipt_verification import verify_receipt_mmriver
from datatrails_scitt_samples.scripts.fileaccess import open_event_json
from datatrails_scitt_samples.datatrails.eventpreimage import get_event
from datatrails_scitt_samples.datatrails.v3eventhash import v3leaf_hash
from datatrails_scitt_samples.datatrails.entryid import entryid_to_identity

from datatrails_scitt_samples.datatrails.servicecontext import ServiceContext


def read_cbor_file(cbor_file: str) -> Sign1Message:
"""
opens the receipt from the receipt file.
"""
with open(cbor_file, "rb") as file:
contents = file.read()

# decode the cbor encoded cose sign1 message
try:
cose_object = Sign1Message.decode(contents)
except (ValueError, AttributeError):
# This is fatal
print("failed to decode cose sign1 from file", file=sys.stderr)
sys.exit(1)

return cose_object


def verify_transparent_statement(
transparent_statement: Sign1Message, leaf: bytes
) -> bool:
"""
verifies the counter signed receipt signature in a TS
"""

# Pull the receipt out of the structure
try:
receipt_bytes = transparent_statement.uhdr["receipts"][0]
except (ValueError, AttributeError, KeyError):
print("failed to extract receipt from Transparent Statement", file=sys.stderr)
return False

return verify_receipt_mmriver(receipt_bytes, leaf)


def main():
"""Verifies a counter signed receipt signature"""

parser = argparse.ArgumentParser(
description="Verify countersigned signature from a Receipt or Transparent Statement."
)
parser.add_argument(
"--datatrails-url",
type=str,
help="The url of the DataTrails transparency service.",
default=None,
)
options = parser.add_argument_group("Node (Leaf) Hash")
options.add_argument(
"--leaf", type=str, help="hex encoded leaf hash to verify against"
)

options.add_argument(
"--entryid", type=str, help="the SCRAPI entry id of the statement"
)

parser.add_argument(
"--event-json-file",
type=str,
help="filepath to the stored event, in json format.",
default=None,
)

options = parser.add_argument_group("Input File Type")
options.add_argument(
"--receipt-file",
type=str,
help="filepath to a stored Receipt, in CBOR format.",
)
options.add_argument(
"--transparent-statement-file",
type=str,
help="filepath to a stored Transparent Statement, in CBOR format.",
default="transparent-statement.cbor",
)

args = parser.parse_args()

# Note: the context is only used if --entryid is
# used to obtain the leaf hash directly from datatrails
cfg_overrides = {}
if args.datatrails_url:
cfg_overrides["datatrails_url"] = args.datatrails_url
ctx = ServiceContext.from_env("verify-receipt", **cfg_overrides)

if not (args.leaf or args.event_json_file or args.entryid):
print("either --leaf or --event-json-file is required", file=sys.stderr)
sys.exit(1)

leaf = None
if args.leaf:
leaf = bytes.fromhex(args.leaf)
elif args.event_json_file:
event = json.loads(open_event_json(args.event_json_file))
leaf = v3leaf_hash(event)
print(leaf.hex())
elif args.entryid:
identity = entryid_to_identity(args.entryid)
event = get_event(ctx, identity, True)
leaf = v3leaf_hash(event)
print(leaf.hex())

if leaf is None:
print("failed to obtain leaf hash", file=sys.stderr)
sys.exit(1)

if args.receipt_file:
with open(args.receipt_file, "rb") as file:
receipt_bytes = file.read()
verified = verify_receipt_mmriver(receipt_bytes, leaf)
else:
# Note this logic works because only the transparent statement arg
# has a default. Don't change that without changing this!
transparent_statement = read_cbor_file(args.transparent_statement_file)
verified = verify_transparent_statement(transparent_statement, leaf)

if verified:
print("signature verification succeeded")
else:
print("signature verification failed")


if __name__ == "__main__":
main()
185 changes: 0 additions & 185 deletions datatrails_scitt_samples/scripts/verify_receipt.py.disabled

This file was deleted.

Loading

0 comments on commit d74bbe0

Please sign in to comment.