ccf 7.0.0.dev2__py3-none-any.whl → 7.0.0.dev3__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.
- ccf/cose.py +106 -118
- ccf/ledger.py +6 -6
- ccf/receipt.py +22 -1
- {ccf-7.0.0.dev2.data → ccf-7.0.0.dev3.data}/scripts/submit_recovery_share.sh +3 -5
- {ccf-7.0.0.dev2.dist-info → ccf-7.0.0.dev3.dist-info}/METADATA +3 -3
- {ccf-7.0.0.dev2.dist-info → ccf-7.0.0.dev3.dist-info}/RECORD +11 -11
- {ccf-7.0.0.dev2.data → ccf-7.0.0.dev3.data}/scripts/keygenerator.sh +0 -0
- {ccf-7.0.0.dev2.dist-info → ccf-7.0.0.dev3.dist-info}/WHEEL +0 -0
- {ccf-7.0.0.dev2.dist-info → ccf-7.0.0.dev3.dist-info}/entry_points.txt +0 -0
- {ccf-7.0.0.dev2.dist-info → ccf-7.0.0.dev3.dist-info}/licenses/LICENSE +0 -0
- {ccf-7.0.0.dev2.dist-info → ccf-7.0.0.dev3.dist-info}/top_level.txt +0 -0
ccf/cose.py
CHANGED
|
@@ -4,18 +4,17 @@
|
|
|
4
4
|
import argparse
|
|
5
5
|
import sys
|
|
6
6
|
|
|
7
|
-
from typing import Optional,
|
|
7
|
+
from typing import Optional, Any
|
|
8
8
|
|
|
9
9
|
import base64
|
|
10
|
+
import cwt
|
|
11
|
+
import cwt.const
|
|
12
|
+
import cwt.utils
|
|
13
|
+
import cwt.enums
|
|
10
14
|
import cbor2
|
|
11
15
|
import json
|
|
12
|
-
|
|
16
|
+
import hashlib
|
|
13
17
|
from datetime import datetime
|
|
14
|
-
import pycose.headers # type: ignore
|
|
15
|
-
from pycose.keys.ec2 import EC2Key # type: ignore
|
|
16
|
-
from pycose.keys.curves import P256, P384, P521, CoseCurve # type: ignore
|
|
17
|
-
from pycose.keys.keyparam import EC2KpCurve, EC2KpX, EC2KpY, EC2KpD # type: ignore
|
|
18
|
-
from pycose.messages import Sign1Message # type: ignore
|
|
19
18
|
from cryptography.hazmat.primitives.asymmetric import ec
|
|
20
19
|
from cryptography.hazmat.primitives.asymmetric.ec import (
|
|
21
20
|
EllipticCurvePrivateKey,
|
|
@@ -24,7 +23,10 @@ from cryptography.hazmat.primitives.asymmetric.ec import (
|
|
|
24
23
|
from cryptography.hazmat.backends import default_backend
|
|
25
24
|
from cryptography.x509 import load_pem_x509_certificate
|
|
26
25
|
from cryptography.hazmat.primitives import hashes
|
|
27
|
-
from cryptography.hazmat.primitives.serialization import
|
|
26
|
+
from cryptography.hazmat.primitives.serialization import (
|
|
27
|
+
load_pem_private_key,
|
|
28
|
+
load_pem_public_key,
|
|
29
|
+
)
|
|
28
30
|
from cryptography.x509.base import CertificatePublicKeyTypes
|
|
29
31
|
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
|
|
30
32
|
|
|
@@ -41,7 +43,6 @@ GOV_MSG_TYPES = [
|
|
|
41
43
|
] + GOV_MSG_TYPES_WITH_PROPOSAL_ID
|
|
42
44
|
|
|
43
45
|
# See https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs/
|
|
44
|
-
# should move to a pycose.header value after RFC publication
|
|
45
46
|
|
|
46
47
|
COSE_PHDR_VDP_LABEL = 396
|
|
47
48
|
COSE_PHDR_VDS_LABEL = 395
|
|
@@ -54,59 +55,18 @@ CCF_PROOF_LEAF_LABEL = 1
|
|
|
54
55
|
CCF_PROOF_PATH_LABEL = 2
|
|
55
56
|
|
|
56
57
|
|
|
57
|
-
def
|
|
58
|
-
"""
|
|
59
|
-
Returns an initialized COSE Key object of type EC2Key.
|
|
60
|
-
:param ext_key: Python cryptography key.
|
|
61
|
-
:return: an initialized EC key
|
|
62
|
-
"""
|
|
63
|
-
if hasattr(ext_key, "private_numbers"):
|
|
64
|
-
priv_nums = ext_key.private_numbers()
|
|
65
|
-
pub_nums = priv_nums.public_numbers
|
|
66
|
-
else:
|
|
67
|
-
priv_nums = None
|
|
68
|
-
pub_nums = ext_key.public_numbers()
|
|
69
|
-
|
|
70
|
-
curve: Type[CoseCurve]
|
|
71
|
-
if pub_nums.curve.name == "secp256r1":
|
|
72
|
-
curve = P256
|
|
73
|
-
elif pub_nums.curve.name == "secp384r1":
|
|
74
|
-
curve = P384
|
|
75
|
-
elif pub_nums.curve.name == "secp521r1":
|
|
76
|
-
curve = P521
|
|
77
|
-
else:
|
|
78
|
-
raise NotImplementedError("unsupported curve")
|
|
79
|
-
|
|
80
|
-
cose_key = {}
|
|
81
|
-
if pub_nums:
|
|
82
|
-
cose_key.update(
|
|
83
|
-
{
|
|
84
|
-
EC2KpCurve: curve,
|
|
85
|
-
EC2KpX: pub_nums.x.to_bytes(curve.size, "big"),
|
|
86
|
-
EC2KpY: pub_nums.y.to_bytes(curve.size, "big"),
|
|
87
|
-
}
|
|
88
|
-
)
|
|
89
|
-
if priv_nums:
|
|
90
|
-
cose_key.update(
|
|
91
|
-
{
|
|
92
|
-
EC2KpD: priv_nums.private_value.to_bytes(curve.size, "big"),
|
|
93
|
-
}
|
|
94
|
-
)
|
|
95
|
-
return EC2Key.from_dict(cose_key)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def default_algorithm_for_key(key) -> str:
|
|
58
|
+
def default_algorithm_for_key(key) -> int:
|
|
99
59
|
"""
|
|
100
60
|
Get the default algorithm for a given key, based on its
|
|
101
61
|
type and parameters.
|
|
102
62
|
"""
|
|
103
63
|
if isinstance(key, EllipticCurvePublicKey):
|
|
104
64
|
if isinstance(key.curve, ec.SECP256R1):
|
|
105
|
-
return
|
|
65
|
+
return cwt.enums.COSEAlgs.ES256
|
|
106
66
|
elif isinstance(key.curve, ec.SECP384R1):
|
|
107
|
-
return
|
|
67
|
+
return cwt.enums.COSEAlgs.ES384
|
|
108
68
|
elif isinstance(key.curve, ec.SECP521R1):
|
|
109
|
-
return
|
|
69
|
+
return cwt.enums.COSEAlgs.ES512
|
|
110
70
|
else:
|
|
111
71
|
raise NotImplementedError("unsupported curve")
|
|
112
72
|
else:
|
|
@@ -125,30 +85,36 @@ def cert_fingerprint(cert_pem: Pem):
|
|
|
125
85
|
return cert.fingerprint(hashes.SHA256()).hex().encode("utf-8")
|
|
126
86
|
|
|
127
87
|
|
|
88
|
+
def key_fingerprint_from_cert(cert_pem: Pem):
|
|
89
|
+
cert = load_pem_x509_certificate(cert_pem.encode("ascii"), default_backend())
|
|
90
|
+
pub_key = cert.public_key().public_bytes(
|
|
91
|
+
Encoding.DER, PublicFormat.SubjectPublicKeyInfo
|
|
92
|
+
)
|
|
93
|
+
return hashlib.sha256(pub_key).hexdigest()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def key_fingerprint_from_key(key_pem: Pem):
|
|
97
|
+
key = load_pem_public_key(key_pem.encode("ascii"), default_backend())
|
|
98
|
+
pub_key = key.public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo)
|
|
99
|
+
return hashlib.sha256(pub_key).hexdigest()
|
|
100
|
+
|
|
101
|
+
|
|
128
102
|
def create_cose_sign1(
|
|
129
103
|
payload: bytes,
|
|
130
104
|
key_priv_pem: Pem,
|
|
131
105
|
cert_pem: Pem,
|
|
132
106
|
additional_protected_header: Optional[dict] = None,
|
|
133
107
|
) -> bytes:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
key = load_pem_private_key(key_priv_pem.encode("ascii"), None, default_backend())
|
|
145
|
-
if key_type == "ec":
|
|
146
|
-
cose_key = from_cryptography_eckey_obj(key)
|
|
147
|
-
else:
|
|
148
|
-
raise NotImplementedError("unsupported key type")
|
|
149
|
-
msg.key = cose_key
|
|
150
|
-
|
|
151
|
-
return msg.encode()
|
|
108
|
+
cose_ctx = cwt.COSE.new(alg_auto_inclusion=True, deterministic_header=True)
|
|
109
|
+
cose_key = cwt.COSEKey.from_pem(key_priv_pem, kid=cert_fingerprint(cert_pem))
|
|
110
|
+
# kid is passed explicitly in the protected header, because kid_auto_inclusion
|
|
111
|
+
# sets the kid in the unprotected header
|
|
112
|
+
phdr: dict[Any, Any] = {int(cwt.COSEHeaders.KID): cert_fingerprint(cert_pem)}
|
|
113
|
+
additional_header = additional_protected_header or {}
|
|
114
|
+
phdr.update(additional_header)
|
|
115
|
+
return cose_ctx.encode_and_sign(
|
|
116
|
+
payload, cose_key, protected=cwt.utils.ResolvedHeader(phdr)
|
|
117
|
+
)
|
|
152
118
|
|
|
153
119
|
|
|
154
120
|
def create_cose_sign1_prepare(
|
|
@@ -160,10 +126,14 @@ def create_cose_sign1_prepare(
|
|
|
160
126
|
alg = default_algorithm_for_key(cert.public_key())
|
|
161
127
|
kid = cert_fingerprint(cert_pem)
|
|
162
128
|
|
|
163
|
-
protected_header
|
|
129
|
+
protected_header: dict[str | int, Any] = {
|
|
130
|
+
int(cwt.COSEHeaders.ALG): alg,
|
|
131
|
+
int(cwt.COSEHeaders.KID): kid,
|
|
132
|
+
}
|
|
164
133
|
protected_header.update(additional_protected_header or {})
|
|
165
|
-
|
|
166
|
-
|
|
134
|
+
protected_header = cwt.utils.sort_keys_for_deterministic_encoding(protected_header)
|
|
135
|
+
phdr_encoded = cbor2.dumps(protected_header)
|
|
136
|
+
tbs = cbor2.dumps(["Signature1", phdr_encoded, b"", payload])
|
|
167
137
|
|
|
168
138
|
assert cert.signature_hash_algorithm
|
|
169
139
|
digester = hashes.Hash(cert.signature_hash_algorithm)
|
|
@@ -182,25 +152,42 @@ def create_cose_sign1_finish(
|
|
|
182
152
|
alg = default_algorithm_for_key(cert.public_key())
|
|
183
153
|
kid = cert_fingerprint(cert_pem)
|
|
184
154
|
|
|
185
|
-
protected_header
|
|
155
|
+
protected_header: dict[str | int, Any] = {
|
|
156
|
+
int(cwt.COSEHeaders.ALG): alg,
|
|
157
|
+
int(cwt.COSEHeaders.KID): kid,
|
|
158
|
+
}
|
|
186
159
|
protected_header.update(additional_protected_header or {})
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
msg
|
|
160
|
+
protected_header = cwt.utils.sort_keys_for_deterministic_encoding(protected_header)
|
|
161
|
+
phdr_encoded = cbor2.dumps(protected_header)
|
|
162
|
+
|
|
163
|
+
sig = base64.urlsafe_b64decode(signature)
|
|
164
|
+
assert isinstance(sig, bytes)
|
|
165
|
+
msg = cbor2.CBORTag(
|
|
166
|
+
cwt.const.COSE_TYPE_TO_TAG[cwt.const.COSETypes.SIGN1],
|
|
167
|
+
[phdr_encoded, {}, payload, sig],
|
|
168
|
+
)
|
|
169
|
+
return cbor2.dumps(msg)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def verify_cose_sign1_with_cert(certificate, cose_sign1, use_key=True, payload=None):
|
|
173
|
+
cose_ctx = cwt.COSE.new()
|
|
174
|
+
cert_pem = certificate.decode()
|
|
175
|
+
cose_key = cwt.COSEKey.from_pem(
|
|
176
|
+
cert_pem,
|
|
177
|
+
kid=(
|
|
178
|
+
key_fingerprint_from_cert(cert_pem)
|
|
179
|
+
if use_key
|
|
180
|
+
else cert_fingerprint(cert_pem)
|
|
181
|
+
),
|
|
182
|
+
)
|
|
183
|
+
return cose_ctx.decode_with_headers(cose_sign1, cose_key, detached_payload=payload)
|
|
197
184
|
|
|
198
|
-
if payload:
|
|
199
|
-
# Detached payload
|
|
200
|
-
msg.payload = payload
|
|
201
185
|
|
|
202
|
-
|
|
203
|
-
|
|
186
|
+
def verify_cose_sign1_with_key(key, cose_sign1, payload=None):
|
|
187
|
+
cose_ctx = cwt.COSE.new()
|
|
188
|
+
key_pem = key.decode()
|
|
189
|
+
cose_key = cwt.COSEKey.from_pem(key_pem, kid=key_fingerprint_from_key(key_pem))
|
|
190
|
+
return cose_ctx.decode_with_headers(cose_sign1, cose_key, detached_payload=payload)
|
|
204
191
|
|
|
205
192
|
|
|
206
193
|
def verify_receipt(
|
|
@@ -210,52 +197,53 @@ def verify_receipt(
|
|
|
210
197
|
Verify a COSE Sign1 receipt as defined in https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs/,
|
|
211
198
|
using the CCF tree algorithm defined in https://datatracker.ietf.org/doc/draft-birkholz-cose-receipts-ccf-profile/
|
|
212
199
|
"""
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
# it to verify the proofs.
|
|
216
|
-
expected_kid = (
|
|
217
|
-
sha256(key.public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo))
|
|
218
|
-
.digest()
|
|
219
|
-
.hex()
|
|
220
|
-
.encode()
|
|
200
|
+
key_pem = key.public_bytes(Encoding.PEM, PublicFormat.SubjectPublicKeyInfo).decode(
|
|
201
|
+
"ascii"
|
|
221
202
|
)
|
|
222
|
-
|
|
223
|
-
cose_key =
|
|
224
|
-
|
|
225
|
-
receipt.key = cose_key
|
|
203
|
+
expected_kid = key_fingerprint_from_key(key_pem)
|
|
204
|
+
cose_key = cwt.COSEKey.from_pem(key_pem, kid=expected_kid)
|
|
205
|
+
cose_ctx = cwt.COSE.new()
|
|
226
206
|
|
|
207
|
+
receipt = cbor2.loads(receipt_bytes)
|
|
208
|
+
assert receipt.tag == cwt.const.COSE_TYPE_TO_TAG[cwt.const.COSETypes.SIGN1]
|
|
209
|
+
phdr, uhdr, payload, sig = receipt.value
|
|
210
|
+
phdr = cbor2.loads(phdr)
|
|
211
|
+
|
|
212
|
+
assert phdr[4] == expected_kid.encode("utf-8")
|
|
213
|
+
|
|
214
|
+
assert COSE_PHDR_VDS_LABEL in phdr, "Verifiable data structure type is required"
|
|
227
215
|
assert (
|
|
228
|
-
COSE_PHDR_VDS_LABEL
|
|
229
|
-
), "Verifiable data structure type is required"
|
|
230
|
-
assert (
|
|
231
|
-
receipt.phdr[COSE_PHDR_VDS_LABEL] == COSE_PHDR_VDS_CCF_LEDGER_SHA256
|
|
216
|
+
phdr[COSE_PHDR_VDS_LABEL] == COSE_PHDR_VDS_CCF_LEDGER_SHA256
|
|
232
217
|
), "vds(395) protected header must be CCF_LEDGER_SHA256(2)"
|
|
233
218
|
|
|
234
|
-
assert COSE_PHDR_VDP_LABEL in
|
|
235
|
-
proof =
|
|
219
|
+
assert COSE_PHDR_VDP_LABEL in uhdr, "Verifiable data proof is required"
|
|
220
|
+
proof = uhdr[COSE_PHDR_VDP_LABEL]
|
|
236
221
|
assert COSE_RECEIPT_INCLUSION_PROOF_LABEL in proof, "Inclusion proof is required"
|
|
237
222
|
inclusion_proofs = proof[COSE_RECEIPT_INCLUSION_PROOF_LABEL]
|
|
238
223
|
assert inclusion_proofs, "At least one inclusion proof is required"
|
|
224
|
+
|
|
225
|
+
ic_phdr = None
|
|
239
226
|
for inclusion_proof in inclusion_proofs:
|
|
240
227
|
assert isinstance(inclusion_proof, bytes), "Inclusion proof must be bstr"
|
|
241
228
|
proof = cbor2.loads(inclusion_proof)
|
|
242
229
|
assert CCF_PROOF_LEAF_LABEL in proof, "Leaf must be present"
|
|
243
230
|
leaf = proof[CCF_PROOF_LEAF_LABEL]
|
|
244
|
-
|
|
245
|
-
|
|
231
|
+
if claim_digest != leaf[2]:
|
|
232
|
+
raise ValueError(f"Claim digest mismatch: {leaf[2]!r} != {claim_digest!r}")
|
|
233
|
+
accumulator = hashlib.sha256(
|
|
234
|
+
leaf[0] + hashlib.sha256(leaf[1].encode()).digest() + leaf[2]
|
|
246
235
|
).digest()
|
|
247
236
|
assert CCF_PROOF_PATH_LABEL in proof, "Path must be present"
|
|
248
237
|
path = proof[CCF_PROOF_PATH_LABEL]
|
|
249
238
|
for left, digest in path:
|
|
250
239
|
if left:
|
|
251
|
-
accumulator = sha256(digest + accumulator).digest()
|
|
240
|
+
accumulator = hashlib.sha256(digest + accumulator).digest()
|
|
252
241
|
else:
|
|
253
|
-
accumulator = sha256(accumulator + digest).digest()
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return receipt.phdr
|
|
242
|
+
accumulator = hashlib.sha256(accumulator + digest).digest()
|
|
243
|
+
ic_phdr, _, _ = cose_ctx.decode_with_headers(
|
|
244
|
+
receipt_bytes, cose_key, detached_payload=accumulator
|
|
245
|
+
)
|
|
246
|
+
return ic_phdr
|
|
259
247
|
|
|
260
248
|
|
|
261
249
|
_SIGN_DESCRIPTION = """Create and sign a COSE Sign1 message for CCF governance
|
ccf/ledger.py
CHANGED
|
@@ -20,7 +20,7 @@ from cryptography.hazmat.primitives.asymmetric import utils, ec
|
|
|
20
20
|
|
|
21
21
|
from ccf.merkletree import MerkleTree
|
|
22
22
|
from ccf.tx_id import TxID
|
|
23
|
-
|
|
23
|
+
import ccf.cose
|
|
24
24
|
import ccf.receipt
|
|
25
25
|
from hashlib import sha256
|
|
26
26
|
|
|
@@ -474,11 +474,11 @@ class BaseValidator:
|
|
|
474
474
|
@staticmethod
|
|
475
475
|
def _verify_root_cose_signature(service_cert, root, cose_sign1):
|
|
476
476
|
try:
|
|
477
|
-
|
|
478
|
-
service_cert.encode("ascii"),
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
477
|
+
ccf.cose.verify_cose_sign1_with_cert(
|
|
478
|
+
certificate=service_cert.encode("ascii"),
|
|
479
|
+
cose_sign1=cose_sign1,
|
|
480
|
+
use_key=True,
|
|
481
|
+
payload=root,
|
|
482
482
|
)
|
|
483
483
|
except Exception as exc:
|
|
484
484
|
raise InvalidRootCoseSignatureException(
|
ccf/receipt.py
CHANGED
|
@@ -5,6 +5,7 @@ import base64
|
|
|
5
5
|
from hashlib import sha256
|
|
6
6
|
from typing import List
|
|
7
7
|
from cryptography.x509 import Certificate
|
|
8
|
+
from cryptography.x509.verification import PolicyBuilder, Store
|
|
8
9
|
from cryptography.hazmat.primitives import hashes
|
|
9
10
|
from cryptography.hazmat.primitives.asymmetric import ec, utils
|
|
10
11
|
|
|
@@ -54,7 +55,9 @@ def check_endorsement(endorsee: Certificate, endorser: Certificate):
|
|
|
54
55
|
|
|
55
56
|
|
|
56
57
|
def check_endorsements(
|
|
57
|
-
node_cert: Certificate,
|
|
58
|
+
node_cert: Certificate,
|
|
59
|
+
service_cert: Certificate,
|
|
60
|
+
endorsements: List[Certificate],
|
|
58
61
|
):
|
|
59
62
|
"""
|
|
60
63
|
Check a node certificate is endorsed by a service certificate, transitively through a list of endorsements.
|
|
@@ -64,3 +67,21 @@ def check_endorsements(
|
|
|
64
67
|
check_endorsement(cert_i, endorsement)
|
|
65
68
|
cert_i = endorsement
|
|
66
69
|
check_endorsement(cert_i, service_cert)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def check_cert_chain(
|
|
73
|
+
node_cert: Certificate,
|
|
74
|
+
service_cert: Certificate,
|
|
75
|
+
endorsements: List[Certificate],
|
|
76
|
+
):
|
|
77
|
+
"""
|
|
78
|
+
Use default cryptography policy to verify CCF cert chain
|
|
79
|
+
"""
|
|
80
|
+
builder = PolicyBuilder()
|
|
81
|
+
builder = builder.store(Store([service_cert]))
|
|
82
|
+
|
|
83
|
+
# This would ideally be `build_server_verifier`, but that requires a
|
|
84
|
+
# Subject which is either a valid DNSName or IPAddress. Our node cert's
|
|
85
|
+
# Subject is "CCF Node", and we may not have a better value in SAN
|
|
86
|
+
verifier = builder.build_client_verifier()
|
|
87
|
+
verifier.verify(leaf=node_cert, intermediates=endorsements)
|
|
@@ -66,12 +66,10 @@ if [ -z "${member_id_cert}" ]; then
|
|
|
66
66
|
exit 1
|
|
67
67
|
fi
|
|
68
68
|
|
|
69
|
-
if
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
if ! command -v ccf_cose_sign1 > /dev/null; then
|
|
70
|
+
echo "Error: This script requires the ccf_cose_sign1 CLI tool, distributed as part of the CCF Python package. Please install it via 'pip install ccf' in the current Python environment"
|
|
71
|
+
exit 1
|
|
72
72
|
fi
|
|
73
|
-
source env/bin/activate
|
|
74
|
-
pip install -q ccf
|
|
75
73
|
|
|
76
74
|
# Compute member ID, as the SHA-256 fingerprint of the signing certificate
|
|
77
75
|
member_id=$(openssl x509 -in "$member_id_cert" -noout -fingerprint -sha256 | cut -d "=" -f 2 | sed 's/://g' | awk '{print tolower($0)}')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ccf
|
|
3
|
-
Version: 7.0.0.
|
|
3
|
+
Version: 7.0.0.dev3
|
|
4
4
|
Summary: Set of tools and utilities for the Confidential Consortium Framework (CCF)
|
|
5
5
|
Author-email: CCF Team <CCF-Sec@microsoft.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/microsoft/ccf
|
|
@@ -11,9 +11,9 @@ Requires-Python: >=3.8
|
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
Requires-Dist: loguru==0.*,>=0.5
|
|
14
|
-
Requires-Dist: cryptography<
|
|
14
|
+
Requires-Dist: cryptography<47,>=44
|
|
15
15
|
Requires-Dist: string-color==1.*,>=1.2.1
|
|
16
|
-
Requires-Dist:
|
|
16
|
+
Requires-Dist: cwt==3.*,>=3.1.0
|
|
17
17
|
Requires-Dist: setuptools<81,>=74
|
|
18
18
|
Requires-Dist: packaging<26,>=24
|
|
19
19
|
Dynamic: license-file
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
ccf/__init__.py,sha256=7h-KCpYSfH_Z8x5CFAoDlHfY0wqRNqOn8vTsaGW8dGA,101
|
|
2
2
|
ccf/_versionifier.py,sha256=17vUCXFp_VixNCuhBmMS9SCM74JnHR1OIZnMQSspSs4,2951
|
|
3
|
-
ccf/cose.py,sha256=
|
|
4
|
-
ccf/ledger.py,sha256=
|
|
3
|
+
ccf/cose.py,sha256=hueXb_gvswxRkDAcUacmSIdkfqAFegZIWkA66M4yKVk,14950
|
|
4
|
+
ccf/ledger.py,sha256=X6ljpGPB8HJ6eAw9F3KkEz_meJpMbPALSr0Fbn6R_cg,42240
|
|
5
5
|
ccf/ledger_code.py,sha256=_malocCXly7TdBwBt8ldY6_yNfFwvyCb5Zkp8T4t9fg,3859
|
|
6
6
|
ccf/ledger_viz.py,sha256=l1p2wKgLDayxquVa9-yzsMcLx9vvygCV8EZ_PrVpvMg,6430
|
|
7
7
|
ccf/merkletree.py,sha256=JHUnGYYHJfi18YUNGiHmNCa1AwmCAwLAN3ias5j61ws,2931
|
|
8
8
|
ccf/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
ccf/read_ledger.py,sha256=UzmEKAMS2GJmwuaenKBJbkBDZIWeCa9xcXdpZB51SEg,9370
|
|
10
|
-
ccf/receipt.py,sha256=
|
|
10
|
+
ccf/receipt.py,sha256=dySVvy-IqvsB8pj5uooIokbQR853vpT7uC0TQ-IWIQk,2765
|
|
11
11
|
ccf/split_ledger.py,sha256=wspNZUFPMSvMgGxmwP3QuSbx7QDzTjrC6ecFFJSp14o,5900
|
|
12
12
|
ccf/tx_id.py,sha256=E7XJyUoJ-a8h7Fp36zNQdhSYdyuNdFV-r_aXhoWl1ks,736
|
|
13
13
|
ccf/verify_ledger_secrets_chain.py,sha256=_UDc4wNro2mNUVbErDkhl24jLeJC0Vr-kECeZEdeHME,3590
|
|
14
|
-
ccf-7.0.0.
|
|
15
|
-
ccf-7.0.0.
|
|
16
|
-
ccf-7.0.0.
|
|
17
|
-
ccf-7.0.0.
|
|
18
|
-
ccf-7.0.0.
|
|
19
|
-
ccf-7.0.0.
|
|
20
|
-
ccf-7.0.0.
|
|
21
|
-
ccf-7.0.0.
|
|
14
|
+
ccf-7.0.0.dev3.data/scripts/keygenerator.sh,sha256=r9i8rURcDUPU8c9NKkxrjweU1qU09Hv3SWc3IFQ648A,2391
|
|
15
|
+
ccf-7.0.0.dev3.data/scripts/submit_recovery_share.sh,sha256=v1L_PjduUASCVYjOJiG7lDwtcSwQPOd3G2CY9ipSUXU,3289
|
|
16
|
+
ccf-7.0.0.dev3.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
17
|
+
ccf-7.0.0.dev3.dist-info/METADATA,sha256=xjxa_WRC7OcqnzILwOHCd20okt7bhm__gTZZF5aYdgE,991
|
|
18
|
+
ccf-7.0.0.dev3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
+
ccf-7.0.0.dev3.dist-info/entry_points.txt,sha256=3hbXI2LSOY06QitxM8GQqT9NwY7rCp1RtSU9gGG20A4,365
|
|
20
|
+
ccf-7.0.0.dev3.dist-info/top_level.txt,sha256=I0tWtkKe6KRqXt0nIp8W-ln8j431-vDBb39bQGKkL9Q,4
|
|
21
|
+
ccf-7.0.0.dev3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|