sdata 1.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sdata/__init__.py +140 -0
- sdata/base.py +684 -0
- sdata/contrib/__init__.py +0 -0
- sdata/contrib/piexif/__init__.py +12 -0
- sdata/contrib/piexif/_common.py +94 -0
- sdata/contrib/piexif/_dump.py +346 -0
- sdata/contrib/piexif/_exceptions.py +2 -0
- sdata/contrib/piexif/_exif.py +638 -0
- sdata/contrib/piexif/_insert.py +60 -0
- sdata/contrib/piexif/_load.py +270 -0
- sdata/contrib/piexif/_remove.py +56 -0
- sdata/contrib/piexif/_transplant.py +45 -0
- sdata/contrib/piexif/_webp.py +240 -0
- sdata/contrib/piexif/helper.py +66 -0
- sdata/contrib/ranger/__init__.py +8 -0
- sdata/contrib/ranger/collections/__init__.py +0 -0
- sdata/contrib/ranger/collections/rangebucketmap.py +346 -0
- sdata/contrib/ranger/collections/rangemap.py +396 -0
- sdata/contrib/ranger/collections/rangeset.py +483 -0
- sdata/contrib/ranger/range/__init__.py +0 -0
- sdata/contrib/ranger/range/cut.py +285 -0
- sdata/contrib/ranger/range/range.py +644 -0
- sdata/contrib/sobol_seq.py +394 -0
- sdata/contrib/sortedcontainers/LICENSE +13 -0
- sdata/contrib/sortedcontainers/__init__.py +74 -0
- sdata/contrib/sortedcontainers/sorteddict.py +789 -0
- sdata/contrib/sortedcontainers/sortedlist.py +2646 -0
- sdata/contrib/sortedcontainers/sortedset.py +733 -0
- sdata/contrib/sqlitedict.py +598 -0
- sdata/contrib/timeflake/__init__.py +40 -0
- sdata/contrib/timeflake/flake.py +69 -0
- sdata/contrib/timeflake/utils.py +47 -0
- sdata/deprecated/__init__.py +10 -0
- sdata/deprecated/data.py +1503 -0
- sdata/did/__init__.py +129 -0
- sdata/did/_http.py +67 -0
- sdata/did/base58btc.py +49 -0
- sdata/did/did_github.py +152 -0
- sdata/did/did_peer4.py +155 -0
- sdata/did/did_web.py +222 -0
- sdata/did/diddoc.py +75 -0
- sdata/did/ed25519.py +225 -0
- sdata/did/eddsa.py +107 -0
- sdata/did/errors.py +40 -0
- sdata/did/issue_vc.py +193 -0
- sdata/did/jose.py +126 -0
- sdata/did/keys.py +104 -0
- sdata/did/utils_didkey.py +161 -0
- sdata/did/verify_vp.py +158 -0
- sdata/doe.py +101 -0
- sdata/dtypes.py +510 -0
- sdata/experiments/__init__.py +331 -0
- sdata/experiments/blob0.py +131 -0
- sdata/experiments/file.py +42 -0
- sdata/experiments/filegroup.py +144 -0
- sdata/experiments/image_old.py +313 -0
- sdata/experiments/ks2.py +15 -0
- sdata/experiments/lapshear.py +8 -0
- sdata/experiments/material.py +7 -0
- sdata/experiments/parameters_deprecated.py +394 -0
- sdata/experiments/workbook.py +226 -0
- sdata/format.py +125 -0
- sdata/imagemeta.py +533 -0
- sdata/interactive.py +118 -0
- sdata/iolib/__init__.py +51 -0
- sdata/iolib/hashtree.py +264 -0
- sdata/iolib/json1sqlitestore.py +554 -0
- sdata/iolib/jsonsqlitestore.py +704 -0
- sdata/iolib/pud.py +242 -0
- sdata/iolib/reader.py +262 -0
- sdata/iolib/writer.py +419 -0
- sdata/metadata.py +882 -0
- sdata/parameter.py +414 -0
- sdata/schema.py +273 -0
- sdata/sclass/__init__.py +111 -0
- sdata/sclass/bfo_classes.py +362 -0
- sdata/sclass/blob.py +362 -0
- sdata/sclass/content.py +87 -0
- sdata/sclass/dataframe.py +1251 -0
- sdata/sclass/dataframegroup.py +187 -0
- sdata/sclass/dependency_graph.py +85 -0
- sdata/sclass/filereference.py +124 -0
- sdata/sclass/image.py +218 -0
- sdata/sclass/lazy_namespace.py +155 -0
- sdata/sclass/process.py +383 -0
- sdata/sclass/process_graph.py +221 -0
- sdata/sclass/zipfile.py +135 -0
- sdata/semantic.py +346 -0
- sdata/suuid.py +136 -0
- sdata/timestamp.py +336 -0
- sdata/tools.py +14 -0
- sdata/units.py +602 -0
- sdata/vocab.py +149 -0
- sdata-1.5.0.dist-info/METADATA +264 -0
- sdata-1.5.0.dist-info/RECORD +98 -0
- sdata-1.5.0.dist-info/WHEEL +5 -0
- sdata-1.5.0.dist-info/licenses/LICENSE-MIT +21 -0
- sdata-1.5.0.dist-info/top_level.txt +1 -0
sdata/did/verify_vp.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""Verifikation von Verifiable Presentations (VP) und der eingebetteten VC.
|
|
3
|
+
|
|
4
|
+
Geprüft werden:
|
|
5
|
+
|
|
6
|
+
1. die Holder-Signatur der VP,
|
|
7
|
+
2. optional ``aud`` und ``nonce`` (Replay-Schutz),
|
|
8
|
+
3. die Issuer-Signatur des eingebetteten VC,
|
|
9
|
+
4. der Gültigkeitszeitraum des VC (``nbf``/``exp``).
|
|
10
|
+
|
|
11
|
+
Unterstützte DID-Methoden für die Schlüsselauflösung:
|
|
12
|
+
|
|
13
|
+
* **Issuer** ``did:web`` – Auflösung via HTTPS (:mod:`sdata.did.did_web`),
|
|
14
|
+
* **Holder** ``did:key`` – lokale Rückgewinnung des Public-JWK (kein Netzwerk).
|
|
15
|
+
|
|
16
|
+
Die Bibliotheksfunktionen werfen :class:`sdata.did.VerificationError` /
|
|
17
|
+
:class:`sdata.did.ResolutionError` (nie ``SystemExit``).
|
|
18
|
+
|
|
19
|
+
CLI::
|
|
20
|
+
|
|
21
|
+
python -m sdata.did.verify_vp --vp product.vp \\
|
|
22
|
+
--expected-aud https://verifier.example.org --expected-nonce <nonce>
|
|
23
|
+
"""
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import time
|
|
27
|
+
import logging
|
|
28
|
+
import argparse
|
|
29
|
+
from typing import Any, Dict, Optional
|
|
30
|
+
|
|
31
|
+
from . import jose
|
|
32
|
+
from .errors import ResolutionError, VerificationError
|
|
33
|
+
from .utils_didkey import pub_jwk_from_did_key
|
|
34
|
+
from .did_web import resolve_public_jwk_for_kid as resolve_web_kid
|
|
35
|
+
|
|
36
|
+
logger = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"resolve_public_jwk_for_kid",
|
|
40
|
+
"verify_presentation",
|
|
41
|
+
"jws_header",
|
|
42
|
+
"jws_verify",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def jws_header(compact: str) -> Dict[str, Any]:
|
|
47
|
+
"""Dekodiere den (ungeprüften) Header eines Compact-JWS."""
|
|
48
|
+
return jose.decode_header(compact)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def jws_verify(compact: str, public_jwk: Dict) -> Dict[str, Any]:
|
|
52
|
+
"""Verifiziere ein Compact-JWS gegen ``public_jwk`` und gib das Payload zurück."""
|
|
53
|
+
return jose.verify_compact(compact, public_jwk)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def resolve_public_jwk_for_kid(kid: str) -> Dict[str, str]:
|
|
57
|
+
"""Löse die ``kid`` zu einem öffentlichen JWK auf (``did:web`` oder ``did:key``).
|
|
58
|
+
|
|
59
|
+
Raises:
|
|
60
|
+
ResolutionError: bei nicht unterstützter DID-Methode oder Auflösefehler.
|
|
61
|
+
"""
|
|
62
|
+
did = kid.split("#")[0]
|
|
63
|
+
if did.startswith("did:web:"):
|
|
64
|
+
return resolve_web_kid(kid)
|
|
65
|
+
if did.startswith("did:key:"):
|
|
66
|
+
return pub_jwk_from_did_key(did)
|
|
67
|
+
raise ResolutionError("nicht unterstützte DID-Methode in kid: {}".format(kid))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def verify_presentation(vp_jws: str, *, expected_aud: Optional[str] = None,
|
|
71
|
+
expected_nonce: Optional[str] = None,
|
|
72
|
+
now: Optional[int] = None) -> Dict[str, Any]:
|
|
73
|
+
"""Verifiziere eine VP samt eingebettetem VC vollständig.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
vp_jws: Die Verifiable Presentation als Compact-JWS.
|
|
77
|
+
expected_aud: Falls gesetzt, muss ``vp.aud`` exakt übereinstimmen.
|
|
78
|
+
expected_nonce: Falls gesetzt, muss ``vp.nonce`` exakt übereinstimmen.
|
|
79
|
+
now: Referenzzeit (Unix-Sekunden) für die ``nbf``/``exp``-Prüfung;
|
|
80
|
+
Default ist die aktuelle Zeit. Nützlich für Tests.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Ein Dict mit ``issuer``, ``holder``, ``credentialSubject``, ``vc`` und ``vp``.
|
|
84
|
+
|
|
85
|
+
Raises:
|
|
86
|
+
VerificationError: bei ungültiger Signatur, ``aud``/``nonce``-Mismatch,
|
|
87
|
+
fehlendem VC oder abgelaufenem/ noch nicht gültigem VC.
|
|
88
|
+
ResolutionError: wenn ein Schlüssel nicht aufgelöst werden kann.
|
|
89
|
+
"""
|
|
90
|
+
now = int(time.time()) if now is None else int(now)
|
|
91
|
+
|
|
92
|
+
# 1) VP-Signatur (Holder)
|
|
93
|
+
vp_pub = resolve_public_jwk_for_kid(jws_header(vp_jws)["kid"])
|
|
94
|
+
vp = jws_verify(vp_jws, vp_pub)
|
|
95
|
+
|
|
96
|
+
# 2) aud / nonce
|
|
97
|
+
if expected_aud is not None and vp.get("aud") != expected_aud:
|
|
98
|
+
raise VerificationError("aud stimmt nicht überein")
|
|
99
|
+
if expected_nonce is not None and vp.get("nonce") != expected_nonce:
|
|
100
|
+
raise VerificationError("nonce stimmt nicht überein")
|
|
101
|
+
|
|
102
|
+
# 3) eingebettetes VC extrahieren & prüfen (Issuer)
|
|
103
|
+
creds = vp.get("vp", {}).get("verifiableCredential", [])
|
|
104
|
+
if not creds:
|
|
105
|
+
raise VerificationError("VP enthält keine verifiableCredential")
|
|
106
|
+
vc_jws = creds[0]
|
|
107
|
+
vc_pub = resolve_public_jwk_for_kid(jws_header(vc_jws)["kid"])
|
|
108
|
+
vc = jws_verify(vc_jws, vc_pub)
|
|
109
|
+
|
|
110
|
+
# 4) Gültigkeitszeitraum
|
|
111
|
+
nbf, exp = vc.get("nbf"), vc.get("exp")
|
|
112
|
+
if nbf is not None and now < nbf:
|
|
113
|
+
raise VerificationError("VC ist noch nicht gültig (nbf)")
|
|
114
|
+
if exp is not None and now > exp:
|
|
115
|
+
raise VerificationError("VC ist abgelaufen (exp)")
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
"issuer": vc.get("iss"),
|
|
119
|
+
"holder": vp.get("holder"),
|
|
120
|
+
"credentialSubject": vc.get("vc", {}).get("credentialSubject", {}),
|
|
121
|
+
"vc": vc,
|
|
122
|
+
"vp": vp,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# --------------------------------------------------------------------------
|
|
127
|
+
# CLI
|
|
128
|
+
# --------------------------------------------------------------------------
|
|
129
|
+
def main(argv=None) -> None:
|
|
130
|
+
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
|
131
|
+
ap = argparse.ArgumentParser(description="Verifiable Presentation verifizieren")
|
|
132
|
+
ap.add_argument("--vp", required=True)
|
|
133
|
+
ap.add_argument("--expected-aud")
|
|
134
|
+
ap.add_argument("--expected-nonce")
|
|
135
|
+
args = ap.parse_args(argv)
|
|
136
|
+
|
|
137
|
+
with open(args.vp, "r") as fh:
|
|
138
|
+
vp_jws = fh.read().strip()
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
result = verify_presentation(
|
|
142
|
+
vp_jws,
|
|
143
|
+
expected_aud=args.expected_aud,
|
|
144
|
+
expected_nonce=args.expected_nonce,
|
|
145
|
+
)
|
|
146
|
+
except (VerificationError, ResolutionError) as exc:
|
|
147
|
+
raise SystemExit("✘ Verifikation fehlgeschlagen: {}".format(exc))
|
|
148
|
+
|
|
149
|
+
subj = result["credentialSubject"]
|
|
150
|
+
logger.info("✔ VP + VC verifiziert")
|
|
151
|
+
logger.info("Issuer: %s", result["issuer"])
|
|
152
|
+
logger.info("Holder: %s", result["holder"])
|
|
153
|
+
logger.info("GTIN: %s SN: %s", subj.get("gtin"), subj.get("serialNumber"))
|
|
154
|
+
logger.info("CO2: %s Recycled: %s", subj.get("co2Footprint"), subj.get("recycledContent"))
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
if __name__ == "__main__":
|
|
158
|
+
main()
|
sdata/doe.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# -*-coding: utf-8-*-
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import collections
|
|
5
|
+
import sdata
|
|
6
|
+
from sdata.contrib.ranger import Range
|
|
7
|
+
import sdata.contrib.sobol_seq
|
|
8
|
+
from sdata.contrib.sobol_seq import Sobol
|
|
9
|
+
import pandas as pd
|
|
10
|
+
class DOE():
|
|
11
|
+
"""
|
|
12
|
+
DoE Generator
|
|
13
|
+
|
|
14
|
+
params_ranges = {"sheet_thickness": [0.8, 1.8],
|
|
15
|
+
"slant_depth": [10., 50.],}
|
|
16
|
+
doe = DOE(params_ranges)
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
def __init__(self, ranges=None, name="N.N."):
|
|
20
|
+
"""DoE Generator
|
|
21
|
+
|
|
22
|
+
params_ranges = {"sheet_thickness": [0.8, 1.8],
|
|
23
|
+
"slant_depth": [10., 50.],}
|
|
24
|
+
doe = DOE(params_ranges)
|
|
25
|
+
|
|
26
|
+
:param ranges:
|
|
27
|
+
:param name:
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
self._ranges = collections.OrderedDict()
|
|
31
|
+
if ranges is not None:
|
|
32
|
+
for param_name, l in ranges.items():
|
|
33
|
+
r = Range.closed(float(min(l)), float(max(l)))
|
|
34
|
+
self._ranges[param_name] = r
|
|
35
|
+
|
|
36
|
+
def add_range(self, param_name, l):
|
|
37
|
+
"""add range
|
|
38
|
+
|
|
39
|
+
:param param_name: str
|
|
40
|
+
:param range: [min, max]
|
|
41
|
+
:return:
|
|
42
|
+
"""
|
|
43
|
+
r = Range.closed(float(min(l)), float(max(l)))
|
|
44
|
+
self._ranges[param_name] = r
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def ranges(self):
|
|
48
|
+
return self._ranges
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def dim_num(self):
|
|
52
|
+
return len(self._ranges)
|
|
53
|
+
|
|
54
|
+
def gen_sobol01(self, n=1):
|
|
55
|
+
S = Sobol()
|
|
56
|
+
X = S.i4_sobol_generate(dim_num=self.dim_num, n=n, skip=1)
|
|
57
|
+
df = pd.DataFrame(X, columns=self._ranges.keys())
|
|
58
|
+
df["doe_id"] = range(1, len(X)+1)
|
|
59
|
+
df.set_index("doe_id", inplace=True)
|
|
60
|
+
return df
|
|
61
|
+
|
|
62
|
+
def gen_sobol(self, n=1):
|
|
63
|
+
S = Sobol()
|
|
64
|
+
X = S.i4_sobol_generate(dim_num=self.dim_num, n=n, skip=1)
|
|
65
|
+
df = pd.DataFrame(X, columns=self._ranges.keys())
|
|
66
|
+
df["doe_id"] = range(1, len(X)+1)
|
|
67
|
+
df.set_index("doe_id", inplace=True)
|
|
68
|
+
for param_name, r in self._ranges.items():
|
|
69
|
+
df[param_name] *= r.length
|
|
70
|
+
df[param_name] += r.min
|
|
71
|
+
return df
|
|
72
|
+
|
|
73
|
+
def to_data(self, name, df_doe, uid=None):
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
:param df_doe: design table
|
|
77
|
+
:return: sdata.Data
|
|
78
|
+
"""
|
|
79
|
+
data = sdata.Data(name=name, uuid=uid, table=df_doe, description="my DoE")
|
|
80
|
+
for parameter_name, r in self.ranges.items():
|
|
81
|
+
data.metadata.add(parameter_name, r, unit="?", description=f"parameter range {parameter_name}",
|
|
82
|
+
label=rf"${parameter_name}$")
|
|
83
|
+
return data
|
|
84
|
+
|
|
85
|
+
if __name__ == '__main__':
|
|
86
|
+
import logging
|
|
87
|
+
try:
|
|
88
|
+
from itertools import combinations
|
|
89
|
+
import matplotlib.pyplot as plt
|
|
90
|
+
def plot_doe(df, figsize=(10,10), alpha=.5, s=5, dpi=150):
|
|
91
|
+
dim_num = len(df.columns)
|
|
92
|
+
fig, axs = plt.subplots(dim_num-1, dim_num-1, figsize=figsize, dpi=dpi)
|
|
93
|
+
for i, j in list(combinations(range(dim_num), 2)):
|
|
94
|
+
xi = df.columns[i]
|
|
95
|
+
xj = df.columns[j]
|
|
96
|
+
axs[i][j-1].scatter(df.iloc[:,i], df.iloc[:,j], alpha=alpha, s=s)
|
|
97
|
+
axs[i][j-1].set_xlabel(xi)
|
|
98
|
+
axs[i][j-1].set_ylabel(xj)
|
|
99
|
+
fig.tight_layout()
|
|
100
|
+
except Exception as exp:
|
|
101
|
+
logging.warning(f"doe: {exp}")
|