Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add digests verification #26

Merged
merged 5 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 79 additions & 5 deletions src/verifier/core/reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
import zipfile
from collections import namedtuple
from dataclasses import asdict
from hashlib import sha256

import falcon
from hio.base import doing
from keri import kering
from keri.core import coring, Siger
from keri.core import coring, Siger, MtrDex

from verifier.core.basing import ReportStats

Expand Down Expand Up @@ -54,6 +55,13 @@ def loadEnds(app, hby, vdb, filer):
app.add_route("/reports/{aid}/{dig}", reportEnd)


def get_non_prefixed_digest(dig):
prefix, digest = dig.split("_", 1)
if not digest:
raise kering.ValidationError(f"Digest ({dig}) must start with prefix")
return digest


class Filer:
""" Report status filer

Expand Down Expand Up @@ -92,19 +100,82 @@ def create(self, aid, dig, filename, typ, stream):
)

idx = 0
non_pref_dig = get_non_prefixed_digest(dig) # Temporarily remove prefix
non_pref_dig = bytes.fromhex(non_pref_dig)
diger = coring.Diger(raw=non_pref_dig, code=MtrDex.SHA2_256)

report = b''
while True:
chunk = stream.read(4096)
report += chunk
if not chunk:
break
key = f"{dig}.{idx}".encode("utf-8")
key = f"{diger.qb64}.{idx}".encode("utf-8")
self.vdb.setVal(db=self.vdb.imgs, key=key, val=chunk)
idx += 1
stats.size += len(chunk)

diger = coring.Diger(qb64=dig)
if not diger.verify(report):
raise kering.ValidationError(f"Report digets({dig} verification failed)")
with tempfile.TemporaryFile("w+b") as tf:
tf.write(report)
tf.seek(0)
with tempfile.TemporaryDirectory() as tempdirname:
z = zipfile.ZipFile(tf)
z.extractall(path=tempdirname)
manifest = None
for root, dirs, _ in os.walk(tempdirname):
if "META-INF" not in dirs or 'reports' not in dirs:
continue

metaDir = os.path.join(root, 'META-INF')
name = os.path.join(root, 'META-INF', 'reports.json')
if not os.path.exists(name):
continue
f = open(name, 'r')
manifest = json.load(f)
if "documentInfo" not in manifest:
raise kering.ValidationError("Invalid manifest file in report package, missing "
"'documentInfo")
reportsDir = os.path.join(root, 'reports')
files = os.listdir(reportsDir)

if manifest is None:
raise kering.ValidationError("No manifest in file, invalid signed report package")

docInfo = manifest["documentInfo"]

if "digests" not in docInfo:
raise kering.ValidationError("No digests found in manifest file")

digests = docInfo["digests"]
for digest in digests:
try:
file = digest["file"]
fullpath = os.path.normpath(os.path.join(metaDir, file))
f = open(fullpath, 'rb')
file_object = f.read()
f.close()
non_pref_dig = get_non_prefixed_digest(digest["dig"]) # Remove prefix
non_pref_dig = bytes.fromhex(non_pref_dig)
tmp_diger = coring.Diger(raw=non_pref_dig, code=MtrDex.SHA2_256)
if not tmp_diger.verify(file_object):
raise kering.ValidationError(f"Invalid digest for file {fullpath}")
except KeyError as e:
raise kering.ValidationError(f"Invalid digest in manifest digest list"
f"missing '{e.args[0]}'")
except OSError:
raise kering.ValidationError(f"signature element={digest} point to invalid file")

except Exception as e:
raise kering.ValidationError(f"{e}")




self.vdb.rpts.add(keys=(aid,), val=diger)
self.vdb.stts.add(keys=(stats.status,), val=diger)
self.vdb.stats.pin(keys=(dig,), val=stats)
self.vdb.stats.pin(keys=(diger.qb64,), val=stats)

def get(self, dig):
""" Return report stats for given report.
Expand All @@ -116,7 +187,10 @@ def get(self, dig):
ReportStats: Report stats for report with digest dig or None

"""
if (stats := self.vdb.stats.get(keys=(dig,))) is None:
non_pref_dig = get_non_prefixed_digest(dig) # Temporarily remove prefix
non_pref_dig = bytes.fromhex(non_pref_dig)
diger = coring.Diger(raw=non_pref_dig, code=MtrDex.SHA2_256)
if (stats := self.vdb.stats.get(keys=(diger.qb64,))) is None:
return None

return stats
Expand Down
28 changes: 14 additions & 14 deletions tests/integration/test_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,31 +113,31 @@ def get():
raise exceptions[0]

# @pytest.mark.manual
# def test_service_integration(seeder):
# def test_service_integration(seeder):
# with habbing.openHab(name="sid", temp=True, salt=b'0123456789abcdef') as (hby, hab):

#
# seeder.seedSchema(db=hby.db)
# regery, registry, verifier, seqner = reg_and_verf(hby, hab, registryName="qvireg")
# qvicred = get_qvi_cred(issuer=hab.pre, recipient=hab.pre, schema=Schema.QVI_SCHEMA, registry=registry)
# hab, qcrdntler, qsaid, qkmsgs, qtmsgs, qimsgs, qvimsgs = get_cred(hby, hab, regery, registry, verifier, Schema.QVI_SCHEMA, qvicred, seqner)
#
# qviedge = get_qvi_edge(qvicred.sad["d"], Schema.QVI_SCHEMA)

#
# leicred = get_lei_cred(issuer=hab.pre, recipient=hab.pre, schema=Schema.LEI_SCHEMA, registry=registry, sedge=qviedge)
# hab, lcrdntler, lsaid, lkmsgs, ltmsgs, limsgs, leimsgs = get_cred(hby, hab, regery, registry, verifier, Schema.LEI_SCHEMA, leicred, seqner)

#
# #chained ecr auth cred
# eaedge = get_ecr_auth_edge(lsaid,Schema.LEI_SCHEMA)
#
# eacred = get_ecr_auth_cred(aid=hab.pre, issuer=hab.pre, recipient=hab.pre, schema=Schema.ECR_AUTH_SCHEMA, registry=registry, sedge=eaedge)
# hab, eacrdntler, easaid, eakmsgs, eatmsgs, eaimsgs, eamsgs = get_cred(hby, hab, regery, registry, verifier, Schema.ECR_AUTH_SCHEMA, eacred, seqner)
#
# #chained ecr auth cred
# ecredge = get_ecr_edge(easaid,Schema.ECR_AUTH_SCHEMA)
#
# ecr = get_ecr_cred(issuer=hab.pre, recipient=hab.pre, schema=Schema.ECR_SCHEMA, registry=registry, sedge=ecredge)
# hab, eccrdntler, ecsaid, eckmsgs, ectmsgs, ecimsgs, ecmsgs = get_cred(hby, hab, regery, registry, verifier, Schema.ECR_SCHEMA, ecr, seqner)
#
# app = falcon.App(
# middleware=falcon.CORSMiddleware(
# allow_origins='*',
Expand All @@ -151,13 +151,13 @@ def get():
# # def get():
# # return dict(LEIs=[f"{LEI1}",f"{LEI2}"])
# rootsCf = configing.Configer(name="verifier-config-public.json",
# headDirPath="/Users/meenyleeny/VSCode/vlei-verifier/scripts",
# headDirPath="/home/aidar/Desktop/git/gleif/vlei-verifier/scripts",
# base="",
# temp=False, reopen=True, clear=False)
# authDoers = authorizing.setup(hby, vdb=vdb, reger=eccrdntler.rgy.reger, cf=rootsCf)

#
# reportDoers = reporting.setup(app=app, hby=hby, vdb=vdb)

#
# doers = authDoers + reportDoers + [httpServerDoer]
# limit = 0.25
# tock = 0.03125
Expand All @@ -173,14 +173,14 @@ def get():
# doist.recur()
# except Exception as e:
# raise ValueError(f"Likely you have another service running on {port}")

#
# issAndCred = bytearray()
# # issAndCred.extend(kmsgs)
# # issAndCred.extend(tmsgs)
# # issAndCred.extend(imsgs)
# issAndCred.extend(ecmsgs)
# acdc = issAndCred.decode("utf-8")

#
# # use this for integration testing debugging sessions
# while True:
# time.sleep(1)
Expand Down
Loading