From a40b9db4ce6c44e9b8e14e993446b899803f93f4 Mon Sep 17 00:00:00 2001 From: Kevin Griffin Date: Fri, 13 Dec 2024 16:55:34 -0500 Subject: [PATCH] V1.2.1 (#906) * pass through salts for vc create to facilitate command line multisig Signed-off-by: Kevin Griffin * fixes nonce pass through to support multisig vc create with --private. Version bump. Signed-off-by: Kevin Griffin * updates type hints for all Signed-off-by: Kevin Griffin --------- Signed-off-by: Kevin Griffin --- Makefile | 2 +- setup.py | 2 +- src/keri/__init__.py | 2 +- src/keri/app/cli/commands/vc/create.py | 21 ++++++++-- src/keri/vc/proving.py | 53 +++++++++++++------------- src/keri/vdr/credentialing.py | 15 ++++++-- tests/vc/test_proving.py | 22 +++++------ 7 files changed, 68 insertions(+), 49 deletions(-) diff --git a/Makefile b/Makefile index 7e6a53bc..22ee28c9 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: build-keri -VERSION=1.2.0 +VERSION=1.2.1 define DOCKER_WARNING In order to use the multi-platform build enable the containerd image store diff --git a/setup.py b/setup.py index a466e63c..5584535e 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ from setuptools import find_packages, setup setup( name='keri', - version='1.2.0', # also change in src/keri/__init__.py + version='1.2.1', # also change in src/keri/__init__.py license='Apache Software License 2.0', description='Key Event Receipt Infrastructure', long_description="KERI Decentralized Key Management Infrastructure", diff --git a/src/keri/__init__.py b/src/keri/__init__.py index e8823ef7..3167ff79 100644 --- a/src/keri/__init__.py +++ b/src/keri/__init__.py @@ -1,5 +1,5 @@ # -*- encoding: utf-8 -*- -__version__ = '1.2.0' # also change in setup.py +__version__ = '1.2.1' # also change in setup.py diff --git a/src/keri/app/cli/commands/vc/create.py b/src/keri/app/cli/commands/vc/create.py index b16e9a17..294e0257 100644 --- a/src/keri/app/cli/commands/vc/create.py +++ b/src/keri/app/cli/commands/vc/create.py @@ -1,5 +1,6 @@ import argparse import json +from typing import Optional from hio import help from hio.base import doing @@ -38,6 +39,10 @@ parser.add_argument('--alias', '-a', help='human readable alias for the new identifier prefix', required=True) parser.add_argument("--private", help="flag to indicate if this credential needs privacy preserving features", action="store_true") +parser.add_argument("--private-credential-nonce", help="nonce for vc", + action="store_true") +parser.add_argument("--private-subject-nonce", help="nonce for subject", + action="store_true") parser.add_argument('--passcode', '-p', help='21 character encryption passcode for keystore (is not saved)', dest="bran", default=None) # passcode => bran parser.add_argument("--time", help="timestamp for the credential creation", required=False, default=None) @@ -101,7 +106,10 @@ def issueCredential(args): rules=rules, credential=credential, timestamp=args.time, - private=args.private) + private=args.private, + private_credential_nonce=args.private_credential_nonce, + private_subject_nonce=args.private_subject_nonce, + ) doers = [issueDoer] return doers @@ -114,7 +122,8 @@ class CredentialIssuer(doing.DoDoer): """ def __init__(self, name, alias, base, bran, registryName=None, schema=None, edges=None, recipient=None, data=None, - rules=None, credential=None, timestamp=None, private=False): + rules=None, credential=None, timestamp=None, private:bool=False, private_credential_nonce:Optional[str]=None, + private_subject_nonce:Optional[str]=None,): """ Create DoDoer for issuing a credential and managing the processes needed to complete issuance Parameters: @@ -126,7 +135,9 @@ def __init__(self, name, alias, base, bran, registryName=None, schema=None, edge data: (dict) credential data dict credential: (dict) full credential to issue when joining a multisig issuance out (str): Filename for credential output - private: (bool) privacy preserving + private (bool): apply nonce used for privacy preserving ACDC + private_credential_nonce (Optional[str]): nonce used for privacy vc + private_subject_nonce (Optional[str]): nonce used for subject """ self.name = name @@ -175,7 +186,9 @@ def __init__(self, name, alias, base, bran, registryName=None, schema=None, edge source=edges, rules=rules, data=data, - private=private) + private=private, + private_credential_nonce=private_credential_nonce, + private_subject_nonce=private_subject_nonce) else: self.creder = serdering.SerderACDC(sad=credential) # proving.Creder(ked=credential) self.credentialer.validate(creder=self.creder) diff --git a/src/keri/vc/proving.py b/src/keri/vc/proving.py index bd0a3e01..5f92717f 100644 --- a/src/keri/vc/proving.py +++ b/src/keri/vc/proving.py @@ -4,52 +4,51 @@ """ -from collections.abc import Iterable -from typing import Union - -from .. import help +from typing import Optional, Union from .. import core +from .. import help from ..core import coring, serdering from ..core.coring import (Kinds, versify) -from ..db import subing -from ..kering import Version from ..help import helping +from ..kering import Version KERI_REGISTRY_TYPE = "KERICredentialRegistry" logger = help.ogler.getLogger() -def credential(schema, - issuer, - data, - recipient=None, - private=False, - salt=None, - status=None, - source=None, - rules=None, - version=Version, - kind=Kinds.json): +def credential(schema:str, + issuer:str, + data:dict, + recipient:Optional[str]=None, + private:bool=False, + private_credential_nonce:Optional[str]=None, + private_subject_nonce:Optional[str]=None, + status:str=None, + source:Union[dict, list]=None, + rules:Union[dict, list]=None, + version:Version=Version, + kind:Kinds=Kinds.json): """Utility function to create an ACDC. Creates dict SAD for credential from parameters and Saidifyies it before creation. Parameters: - schema (SAID): of schema for this credential + schema (str): SAID of schema for this credential issuer (str): qb64 identifier prefix of the issuer - status (str): qb64 said of the credential registry - recipient (Option[str|None]): qb64 identifier prefix of the recipient data (dict): of the values being assigned to the subject of this credential + recipient (Optional[str]): qb64 identifier prefix of the recipient private (bool): apply nonce used for privacy preserving ACDC - salt (string): salt for nonce - source (dict | list): of source credentials to which this credential is chained - rules (dict | list): ACDC rules section for credential + private_credential_nonce (Optional[str]): nonce used for privacy vc + private_subject_nonce (Optional[str]): nonce used for subject + status (str): qb64 said of the credential registry + source (Union[dict, list]): of source credentials to which this credential is chained + rules (Union[dict, list]): ACDC rules section for credential version (Version): version instance - kind (Serials): serialization kind + kind (Kinds): serialization kind Returns: - SerderACDC: credential instance + serdering.SerderACDC: credential instance """ vs = versify(protocol=coring.Protocols.acdc, version=version, kind=kind, size=0) @@ -64,8 +63,8 @@ def credential(schema, ) if private: - vc["u"] = salt if salt is not None else core.Salter().qb64 - subject["u"] = salt if salt is not None else core.Salter().qb64 + vc["u"] = private_credential_nonce if private_credential_nonce is not None else core.Salter().qb64 + subject["u"] = private_subject_nonce if private_subject_nonce is not None else core.Salter().qb64 if recipient is not None: subject['i'] = recipient diff --git a/src/keri/vdr/credentialing.py b/src/keri/vdr/credentialing.py index 416bb0af..93c47e6a 100644 --- a/src/keri/vdr/credentialing.py +++ b/src/keri/vdr/credentialing.py @@ -5,14 +5,16 @@ VC issuer support """ +from typing import Optional + from hio.base import doing from hio.help import decking from keri.vdr import viring -from .. import kering, help +from .. import help +from .. import kering, core from ..app import agenting from ..app.habbing import GroupHab -from .. import kering, core from ..core import parsing, coring, scheming, serdering from ..core.coring import Seqner, MtrDex from ..core.eventing import TraitDex @@ -772,7 +774,8 @@ def __init__(self, hby, rgy, registrar, verifier): super(Credentialer, self).__init__(doers=doers) - def create(self, regname, recp: str, schema, source, rules, data, private=False): + def create(self, regname, recp: str, schema, source, rules, data, private: bool = False, + private_credential_nonce: Optional[str] = None, private_subject_nonce: Optional[str] = None): """ Create and validate a credential returning the fully populated Creder Parameters: @@ -782,7 +785,9 @@ def create(self, regname, recp: str, schema, source, rules, data, private=False) source: rules: data: - private: add nonce for privacy preserving + private (bool): apply nonce used for privacy preserving ACDC + private_credential_nonce (Optional[str]): nonce used for privacy vc + private_subject_nonce (Optional[str]): nonce used for subject Returns: Creder: Creder class for the issued credential @@ -803,6 +808,8 @@ def create(self, regname, recp: str, schema, source, rules, data, private=False) data=data, source=source, private=private, + private_credential_nonce=private_credential_nonce, + private_subject_nonce=private_subject_nonce, rules=rules, status=registry.regk) self.validate(creder) diff --git a/tests/vc/test_proving.py b/tests/vc/test_proving.py index 798478be..383e38e5 100644 --- a/tests/vc/test_proving.py +++ b/tests/vc/test_proving.py @@ -253,25 +253,25 @@ def test_privacy_preserving_credential(mockHelpingNowIso8601): engagementContextRole="Project Manager", ) - salt = core.Salter(raw=b'0123456789abcdef').qb64 cred = credential(schema="EZllThM1rLBSMZ_ozM1uAnFvSfC0N1jaQ42aKU5sCZ5Q", recipient="EM_S2MdMaKgP6P2Yyno6-flV6GqrwPencTIw8tCMR7iB", private=True, - salt=salt, + private_credential_nonce=core.Salter(raw=b'0123456789abcdef').qb64, + private_subject_nonce=core.Salter(raw=b'abcdef0123456789').qb64, issuer="EMZeK1yLZd1JV6Ktdq_YUt-YbyoTWB9UMcFzuiDly2Y6", data=d, status="ETQoH02zJRCTNz-Wl3nnkUD_RVSzSwcoNvmfa18AWt3M") assert cred.size == len(cred.raw) assert "u" in cred.sad - print(cred.raw) - assert cred.raw == (b'{"v":"ACDC10JSON00021c_","d":"ELFOCm58xUlId994cS6m6bsfYOkNHEKoe15Cav-Sj8__",' - b'"u":"0AAwMTIzNDU2Nzg5YWJjZGVm","i":"EMZeK1yLZd1JV6Ktdq_YUt-YbyoTWB9UMcFzuiDl' - b'y2Y6","ri":"ETQoH02zJRCTNz-Wl3nnkUD_RVSzSwcoNvmfa18AWt3M","s":"EZllThM1rLBSM' - b'Z_ozM1uAnFvSfC0N1jaQ42aKU5sCZ5Q","a":{"d":"EFwWs1d_fe_VeLZ0vQQKO-gkRvGrpfWAR' - b'bI4e9tzcqlV","u":"0AAwMTIzNDU2Nzg5YWJjZGVm","i":"EM_S2MdMaKgP6P2Yyno6-flV6Gq' - b'rwPencTIw8tCMR7iB","dt":"2021-06-27T21:26:21.233257+00:00","LEI":"254900OPPU' - b'84GM83MG36","personLegalName":"John Doe","engagementContextRole":"Project Ma' - b'nager"}}') + + assert cred.raw == (b'{"v":"ACDC10JSON00021c_","d":"EMMDzhHHlpQP0XNMRThDeIFkYD1WkDHF7Tp-8kt8X5pn",' + b'"u":"0AAwMTIzNDU2Nzg5YWJjZGVm","i":"EMZeK1yLZd1JV6Ktdq_YUt-YbyoTWB9UMcFzuiDly2Y6",' + b'"ri":"ETQoH02zJRCTNz-Wl3nnkUD_RVSzSwcoNvmfa18AWt3M",' + b'"s":"EZllThM1rLBSMZ_ozM1uAnFvSfC0N1jaQ42aKU5sCZ5Q",' + b'"a":{"d":"EK3MRnlg-bMUnHtYKyZ8HD_IbBeI0v4N8YB4UnNVBqrv","u":"0ABhYmNkZWYwMTIzNDU2Nzg5",' + b'"i":"EM_S2MdMaKgP6P2Yyno6-flV6GqrwPencTIw8tCMR7iB","dt":"2021-06-27T21:26:21.233257+00:00",' + b'"LEI":"254900OPPU84GM83MG36","personLegalName":"John Doe","engagementContextRole":"Project ' + b'Manager"}}') """End Test"""