Skip to content

Commit 8b83b9e

Browse files
Support EcdsaSecp256r1Signature2019 linked data proof (openwallet-foundation#3443)
* sign working Signed-off-by: George Mulhearn <[email protected]> * fmt and ld proof tests Signed-off-by: George Mulhearn <[email protected]> * easy unit test fixes Signed-off-by: George Mulhearn <[email protected]> * fix up pres exch flow, run scenario Signed-off-by: George Mulhearn <[email protected]> * ruff Signed-off-by: George Mulhearn <[email protected]> * lint Signed-off-by: George Mulhearn <[email protected]> * poke sonarqube Signed-off-by: George Mulhearn <[email protected]> * improve coverage Signed-off-by: George Mulhearn <[email protected]> * improve coverage Signed-off-by: George Mulhearn <[email protected]> * route p256 fallback improve Signed-off-by: George Mulhearn <[email protected]> * rm prints Signed-off-by: George Mulhearn <[email protected]> --------- Signed-off-by: George Mulhearn <[email protected]> Co-authored-by: George Mulhearn <[email protected]>
1 parent f495a37 commit 8b83b9e

23 files changed

+680
-25
lines changed

acapy_agent/protocols/present_proof/dif/pres_exch_handler.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
DocumentLoader,
3232
Ed25519Signature2018,
3333
Ed25519Signature2020,
34+
EcdsaSecp256r1Signature2019,
3435
WalletKeyPair,
3536
)
3637
from ....vc.ld_proofs.constants import (
@@ -45,7 +46,7 @@
4546
ProofPurposeStr,
4647
)
4748
from ....wallet.error import WalletError, WalletNotFoundError
48-
from ....wallet.key_type import BLS12381G2, ED25519
49+
from ....wallet.key_type import BLS12381G2, ED25519, P256
4950
from .pres_exch import (
5051
Constraints,
5152
DIFField,
@@ -79,6 +80,7 @@ class DIFPresExchHandler:
7980
ISSUE_SIGNATURE_SUITE_KEY_TYPE_MAPPING = {
8081
Ed25519Signature2018: ED25519,
8182
Ed25519Signature2020: ED25519,
83+
EcdsaSecp256r1Signature2019: P256,
8284
}
8385

8486
if BbsBlsSignature2020.BBS_SUPPORTED:
@@ -193,6 +195,8 @@ async def get_sign_key_credential_subject_id(
193195
filtered_creds_list = []
194196
if self.proof_type == BbsBlsSignature2020.signature_type:
195197
reqd_key_type = BLS12381G2
198+
elif self.proof_type == EcdsaSecp256r1Signature2019.signature_type:
199+
reqd_key_type = P256
196200
else:
197201
reqd_key_type = ED25519
198202
for cred in applicable_creds:

acapy_agent/protocols/present_proof/dif/tests/test_pres_exch_handler.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
)
2525
from .....wallet.did_method import KEY, SOV, DIDMethods
2626
from .....wallet.error import WalletNotFoundError
27-
from .....wallet.key_type import BLS12381G2, ED25519, KeyTypes
27+
from .....wallet.key_type import BLS12381G2, ED25519, P256, KeyTypes
2828
from .. import pres_exch_handler as test_module
2929
from ..pres_exch import (
3030
Constraints,
@@ -2070,6 +2070,70 @@ async def test_get_sign_key_credential_subject_id_error(self):
20702070
VC_RECORDS
20712071
)
20722072

2073+
async def test_get_sign_key_credential_subject_id_secp256r1(self):
2074+
dif_pres_exch_handler = DIFPresExchHandler(
2075+
self.profile, proof_type="EcdsaSecp256r1Signature2019"
2076+
)
2077+
2078+
VC_RECORDS = [
2079+
VCRecord(
2080+
contexts=[
2081+
"https://www.w3.org/2018/credentials/v1",
2082+
"https://www.w3.org/2018/credentials/examples/v1",
2083+
],
2084+
expanded_types=[
2085+
"https://www.w3.org/2018/credentials#VerifiableCredential",
2086+
"https://example.org/examples#UniversityDegreeCredential",
2087+
],
2088+
issuer_id="https://example.edu/issuers/565049",
2089+
subject_ids=["did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL"],
2090+
proof_types=["EcdsaSecp256r1Signature2019"],
2091+
schema_ids=["https://example.org/examples/degree.json"],
2092+
cred_value={"...": "..."},
2093+
given_id="http://example.edu/credentials/3732",
2094+
cred_tags={"some": "tag"},
2095+
),
2096+
VCRecord(
2097+
contexts=[
2098+
"https://www.w3.org/2018/credentials/v1",
2099+
"https://www.w3.org/2018/credentials/examples/v1",
2100+
],
2101+
expanded_types=[
2102+
"https://www.w3.org/2018/credentials#VerifiableCredential",
2103+
"https://example.org/examples#UniversityDegreeCredential",
2104+
],
2105+
issuer_id="https://example.edu/issuers/565049",
2106+
subject_ids=[
2107+
"did:sov:LjgpST2rjsoxYegQDRm7EL",
2108+
"did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL",
2109+
],
2110+
proof_types=["EcdsaSecp256r1Signature2019"],
2111+
schema_ids=["https://example.org/examples/degree.json"],
2112+
cred_value={"...": "..."},
2113+
given_id="http://example.edu/credentials/3732",
2114+
cred_tags={"some": "tag"},
2115+
),
2116+
]
2117+
with mock.patch.object(
2118+
DIFPresExchHandler,
2119+
"_did_info_for_did",
2120+
mock.CoroutineMock(),
2121+
) as mock_did_info:
2122+
did_info = DIDInfo(
2123+
did="did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL",
2124+
verkey="verkey",
2125+
metadata={},
2126+
method=KEY,
2127+
key_type=P256,
2128+
)
2129+
mock_did_info.return_value = did_info
2130+
(
2131+
issuer_id,
2132+
filtered_creds,
2133+
) = await dif_pres_exch_handler.get_sign_key_credential_subject_id(VC_RECORDS)
2134+
assert issuer_id == "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL"
2135+
assert len(filtered_creds) == 2
2136+
20732137
async def test_get_sign_key_credential_subject_id_bbsbls(self):
20742138
dif_pres_exch_handler = DIFPresExchHandler(
20752139
self.profile, proof_type="BbsBlsSignature2020"

acapy_agent/protocols/present_proof/v2_0/formats/dif/handler.py

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
BbsBlsSignature2020,
1616
Ed25519Signature2018,
1717
Ed25519Signature2020,
18+
EcdsaSecp256r1Signature2019,
1819
)
1920
from ......vc.vc_di.manager import VcDiManager
2021
from ......vc.vc_ld.manager import VcLdpManager
@@ -232,12 +233,16 @@ async def create_pres(
232233
and (
233234
Ed25519Signature2020.signature_type not in proof_types
234235
)
236+
and (
237+
EcdsaSecp256r1Signature2019.signature_type
238+
not in proof_types
239+
)
235240
):
236241
raise V20PresFormatHandlerError(
237242
"Only BbsBlsSignature2020 and/or "
238243
"Ed25519Signature2018 and/or "
239-
"Ed25519Signature2018 and/or "
240-
"Ed25519Signature2020 signature types "
244+
"Ed25519Signature2020 and/or "
245+
"EcdsaSecp256r1Signature2019 signature types "
241246
"are supported"
242247
)
243248
elif (
@@ -251,11 +256,16 @@ async def create_pres(
251256
and (
252257
Ed25519Signature2020.signature_type not in proof_types
253258
)
259+
and (
260+
EcdsaSecp256r1Signature2019.signature_type
261+
not in proof_types
262+
)
254263
):
255264
raise V20PresFormatHandlerError(
256-
"Only BbsBlsSignature2020, Ed25519Signature2018 and "
257-
"Ed25519Signature2020 signature types "
258-
"are supported"
265+
"Only BbsBlsSignature2020, Ed25519Signature2018, "
266+
"Ed25519Signature2020 and "
267+
"EcdsaSecp256r1Signature2019 "
268+
"signature types are supported"
259269
)
260270
else:
261271
for proof_format in proof_types:
@@ -268,6 +278,17 @@ async def create_pres(
268278
Ed25519Signature2018.signature_type
269279
)
270280
break
281+
if (
282+
proof_format
283+
== EcdsaSecp256r1Signature2019.signature_type
284+
):
285+
proof_type = [
286+
EcdsaSecp256r1Signature2019.signature_type
287+
]
288+
dif_handler_proof_type = (
289+
EcdsaSecp256r1Signature2019.signature_type
290+
)
291+
break
271292
elif (
272293
proof_format == BbsBlsSignature2020.signature_type
273294
):
@@ -291,9 +312,10 @@ async def create_pres(
291312
# TODO di_vc allowed ...
292313
raise V20PresFormatHandlerError(
293314
"Currently, only: ldp_vp with "
294-
"BbsBlsSignature2020, Ed25519Signature2018 and "
295-
"Ed25519Signature2020 signature types; and "
296-
"di_vc with anoncreds-2023 signatures are supported"
315+
"BbsBlsSignature2020, Ed25519Signature2018, "
316+
"Ed25519Signature2020 and EcdsaSecp256r1Signature2019 "
317+
"signature types; and di_vc with anoncreds-2023 "
318+
"signatures are supported"
297319
)
298320

299321
if one_of_uri_groups:

acapy_agent/protocols/present_proof/v2_0/formats/dif/tests/test_handler.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,52 @@ async def test_create_pres_pd_claim_format_ed255(self):
10421042
)
10431043
assert output[1].data.json_ == DIF_PRES
10441044

1045+
async def test_create_pres_pd_claim_format_secp256r1(self):
1046+
test_pd = deepcopy(DIF_PRES_REQUEST_B)
1047+
test_pd["presentation_definition"]["format"] = {
1048+
"ldp_vp": {"proof_type": ["EcdsaSecp256r1Signature2019"]}
1049+
}
1050+
del test_pd["presentation_definition"]["input_descriptors"][0]["constraints"][
1051+
"limit_disclosure"
1052+
]
1053+
dif_pres_request = V20PresRequest(
1054+
formats=[
1055+
V20PresFormat(
1056+
attach_id="dif",
1057+
format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][
1058+
V20PresFormat.Format.DIF.api
1059+
],
1060+
)
1061+
],
1062+
request_presentations_attach=[
1063+
AttachDecorator.data_json(test_pd, ident="dif")
1064+
],
1065+
)
1066+
record = V20PresExRecord(
1067+
pres_ex_id="pxid",
1068+
thread_id="thid",
1069+
connection_id="conn_id",
1070+
initiator="init",
1071+
role="role",
1072+
state="state",
1073+
pres_request=dif_pres_request,
1074+
verified="false",
1075+
auto_present=True,
1076+
error_msg="error",
1077+
)
1078+
1079+
with mock.patch.object(
1080+
DIFPresExchHandler,
1081+
"create_vp",
1082+
mock.CoroutineMock(),
1083+
) as mock_create_vp:
1084+
mock_create_vp.return_value = DIF_PRES
1085+
output = await self.handler.create_pres(record, {})
1086+
assert isinstance(output[0], V20PresFormat) and isinstance(
1087+
output[1], AttachDecorator
1088+
)
1089+
assert output[1].data.json_ == DIF_PRES
1090+
10451091
async def test_create_pres_pd_claim_format_bls12381g2(self):
10461092
test_pd = deepcopy(DIF_PRES_REQUEST_B)
10471093
test_pd["presentation_definition"]["format"] = {

acapy_agent/protocols/present_proof/v2_0/routes.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
BbsBlsSignature2020,
4848
Ed25519Signature2018,
4949
Ed25519Signature2020,
50+
EcdsaSecp256r1Signature2019,
5051
)
5152
from ....wallet.error import WalletNotFoundError
5253
from ..dif.pres_exch import ClaimFormat, InputDescriptors, SchemaInputDescriptor
@@ -685,12 +686,17 @@ async def present_proof_credentials_list(request: web.BaseRequest):
685686
and (
686687
Ed25519Signature2020.signature_type not in proof_types
687688
)
689+
and (
690+
EcdsaSecp256r1Signature2019.signature_type
691+
not in proof_types
692+
)
688693
):
689694
raise web.HTTPBadRequest(
690695
reason=(
691696
"Only BbsBlsSignature2020 and/or "
692697
"Ed25519Signature2018 and/or "
693-
"Ed25519Signature2020 signature types "
698+
"Ed25519Signature2020 and/or "
699+
"EcdsaSecp256r1Signature2019 signature types "
694700
"are supported"
695701
)
696702
)
@@ -705,12 +711,17 @@ async def present_proof_credentials_list(request: web.BaseRequest):
705711
and (
706712
Ed25519Signature2020.signature_type not in proof_types
707713
)
714+
and (
715+
EcdsaSecp256r1Signature2019.signature_type
716+
not in proof_types
717+
)
708718
):
709719
raise web.HTTPBadRequest(
710720
reason=(
711721
"Only BbsBlsSignature2020, Ed25519Signature2018"
712-
" and Ed25519Signature2020 signature types are"
713-
" supported"
722+
" and Ed25519Signature2020,"
723+
" EcdsaSecp256r1Signature2019"
724+
" signature types are supported"
714725
)
715726
)
716727
else:
@@ -727,6 +738,14 @@ async def present_proof_credentials_list(request: web.BaseRequest):
727738
):
728739
proof_type = [Ed25519Signature2020.signature_type]
729740
break
741+
elif (
742+
proof_format
743+
== EcdsaSecp256r1Signature2019.signature_type
744+
):
745+
proof_type = [
746+
EcdsaSecp256r1Signature2019.signature_type
747+
]
748+
break
730749
elif (
731750
proof_format == BbsBlsSignature2020.signature_type
732751
):
@@ -746,7 +765,8 @@ async def present_proof_credentials_list(request: web.BaseRequest):
746765
reason=(
747766
"Currently, only ldp_vp with "
748767
"BbsBlsSignature2020, Ed25519Signature2018 and "
749-
"Ed25519Signature2020 signature types are supported"
768+
"Ed25519Signature2020, EcdsaSecp256r1Signature2019"
769+
" signature types are supported"
750770
)
751771
)
752772
if one_of_uri_groups:

acapy_agent/vc/ld_proofs/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from .suites import _BbsBlsSignatureProof2020 as BbsBlsSignatureProof2020
1515
from .suites import _Ed25519Signature2018 as Ed25519Signature2018
1616
from .suites import _Ed25519Signature2020 as Ed25519Signature2020
17+
from .suites import _EcdsaSecp256r1Signature2019 as EcdsaSecp256r1Signature2019
1718
from .suites import _JwsLinkedDataSignature as JwsLinkedDataSignature
1819
from .suites import _LinkedDataProof as LinkedDataProof
1920
from .suites import _LinkedDataSignature as LinkedDataSignature
@@ -36,6 +37,7 @@
3637
"JwsLinkedDataSignature",
3738
"Ed25519Signature2018",
3839
"Ed25519Signature2020",
40+
"EcdsaSecp256r1Signature2019",
3941
"BbsBlsSignature2020",
4042
"BbsBlsSignatureProof2020",
4143
# Key pairs

acapy_agent/vc/ld_proofs/suites/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
)
55
from .ed25519_signature_2018 import Ed25519Signature2018 as _Ed25519Signature2018
66
from .ed25519_signature_2020 import Ed25519Signature2020 as _Ed25519Signature2020
7+
from .ecdsa_secp256r1_signature_2019 import (
8+
EcdsaSecp256r1Signature2019 as _EcdsaSecp256r1Signature2019,
9+
)
710
from .jws_linked_data_signature import JwsLinkedDataSignature as _JwsLinkedDataSignature
811
from .linked_data_proof import LinkedDataProof as _LinkedDataProof
912
from .linked_data_signature import LinkedDataSignature as _LinkedDataSignature
@@ -14,6 +17,7 @@
1417
"_JwsLinkedDataSignature",
1518
"_Ed25519Signature2018",
1619
"_Ed25519Signature2020",
20+
"_EcdsaSecp256r1Signature2019",
1721
"_BbsBlsSignature2020",
1822
"_BbsBlsSignatureProof2020",
1923
]

0 commit comments

Comments
 (0)