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..699b598a 100644 --- a/src/keri/vc/proving.py +++ b/src/keri/vc/proving.py @@ -3,18 +3,14 @@ keri.vc.proving module """ - -from collections.abc import Iterable -from typing import Union - -from .. import help +from typing import Optional 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" @@ -25,8 +21,9 @@ def credential(schema, issuer, data, recipient=None, - private=False, - salt=None, + private:bool=False, + private_credential_nonce:Optional[str]=None, + private_subject_nonce:Optional[str]=None, status=None, source=None, rules=None, @@ -42,7 +39,8 @@ def credential(schema, recipient (Option[str|None]): qb64 identifier prefix of the recipient data (dict): of the values being assigned to the subject of this credential private (bool): apply nonce used for privacy preserving ACDC - salt (string): salt for nonce + private_credential_nonce (Optional[str]): nonce used for privacy vc + private_subject_nonce (Optional[str]): nonce used for subject source (dict | list): of source credentials to which this credential is chained rules (dict | list): ACDC rules section for credential version (Version): version instance @@ -64,8 +62,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 687fd22c..0ed2a116 100644 --- a/src/keri/vdr/credentialing.py +++ b/src/keri/vdr/credentialing.py @@ -5,14 +5,15 @@ 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 +773,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 +784,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 +807,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..d967257c 100644 --- a/tests/vc/test_proving.py +++ b/tests/vc/test_proving.py @@ -253,22 +253,22 @@ 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__",' + + assert cred.raw == (b'{"v":"ACDC10JSON00021c_","d":"EMMDzhHHlpQP0XNMRThDeIFkYD1WkDHF7Tp-8kt8X5pn",' 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'Z_ozM1uAnFvSfC0N1jaQ42aKU5sCZ5Q","a":{"d":"EK3MRnlg-bMUnHtYKyZ8HD_IbBeI0v4N8' + b'YB4UnNVBqrv","u":"0ABhYmNkZWYwMTIzNDU2Nzg5","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"}}')