diff --git a/aries_cloudagent/issuer/indy.py b/aries_cloudagent/issuer/indy.py index 516ab91f91..08b350c46b 100644 --- a/aries_cloudagent/issuer/indy.py +++ b/aries_cloudagent/issuer/indy.py @@ -6,9 +6,9 @@ import indy.anoncreds from ..core.error import BaseError +from ..messaging.util import encode from .base import BaseIssuer -from .util import encode class IssuerError(BaseError): diff --git a/aries_cloudagent/issuer/util.py b/aries_cloudagent/issuer/util.py deleted file mode 100644 index 4d2a7aeb42..0000000000 --- a/aries_cloudagent/issuer/util.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Issuer utils.""" - -from hashlib import sha256 -from typing import Any - -I32_BOUND = 2 ** 31 - - -def encode(orig: Any) -> str: - """ - Encode a credential value as an int. - - Encode credential attribute value, purely stringifying any int32 - and leaving numeric int32 strings alone, but mapping any other - input to a stringified 256-bit (but not 32-bit) integer. - Predicates in indy-sdk operate - on int32 values properly only when their encoded values match their raw values. - - Args: - orig: original value to encode - - Returns: - encoded value - - """ - - if isinstance(orig, int) and -I32_BOUND <= orig < I32_BOUND: - return str(int(orig)) # python bools are ints - - try: - i32orig = int(str(orig)) # don't encode floats as ints - if -I32_BOUND <= i32orig < I32_BOUND: - return str(i32orig) - except (ValueError, TypeError): - pass - - rv = int.from_bytes(sha256(str(orig).encode()).digest(), "big") - while -I32_BOUND <= rv < I32_BOUND: - rv = int.from_bytes( - sha256(rv.encode()).digest(), "big" - ) # sha256 maps no 32-bit int to another: terminates - - return str(rv) diff --git a/aries_cloudagent/messaging/tests/test_util.py b/aries_cloudagent/messaging/tests/test_util.py index f317d8c454..d519c56c4e 100644 --- a/aries_cloudagent/messaging/tests/test_util.py +++ b/aries_cloudagent/messaging/tests/test_util.py @@ -1,10 +1,15 @@ +import re + from datetime import datetime, timezone from unittest import mock, TestCase from ..util import ( + canon, datetime_now, datetime_to_str, + encode, epoch_to_str, + I32_BOUND, str_to_datetime, str_to_epoch, time_now @@ -59,3 +64,101 @@ def test_epoch(self): assert epoch_now == str_to_epoch(dt_now) and isinstance(epoch_now, int) assert epoch_to_str(epoch_now) == datetime_to_str(dt_now.replace(microsecond=0)) + + def test_canon(self): + assert canon("a B c") == 'abc' + assert canon(None) is None + assert canon("") == "" + assert canon("canon") == "canon" + + def test_encode(self): + values = { + "address2": { + "raw": "101 Wilson Lane", + "encoded": "68086943237164982734333428280784300550565381723532936263016368251445461241953" + }, + "zip": { + "raw": "87121", + "encoded": "87121" + }, + "city": { + "raw": "SLC", + "encoded": "101327353979588246869873249766058188995681113722618593621043638294296500696424" + }, + "address1": { + "raw": "101 Tela Lane", + "encoded": "63690509275174663089934667471948380740244018358024875547775652380902762701972" + }, + "state": { + "raw": "UT", + "encoded": "93856629670657830351991220989031130499313559332549427637940645777813964461231" + }, + "Empty": { + "raw": "", + "encoded": "102987336249554097029535212322581322789799900648198034993379397001115665086549" + }, + "Null": { + "raw": None, + "encoded": "99769404535520360775991420569103450442789945655240760487761322098828903685777" + }, + "str None": { + "raw": "None", + "encoded": "99769404535520360775991420569103450442789945655240760487761322098828903685777" + }, + "bool True": { + "raw": True, + "encoded": "1" + }, + "bool False": { + "raw": False, + "encoded": "0", + }, + "str True": { + "raw": "True", + "encoded": "27471875274925838976481193902417661171675582237244292940724984695988062543640" + }, + "str False": { + "raw": "False", + "encoded": "43710460381310391454089928988014746602980337898724813422905404670995938820350" + }, + "max i32": { + "raw": 2147483647, + "encoded": "2147483647" + }, + "max i32 + 1": { + "raw": 2147483648, + "encoded": "26221484005389514539852548961319751347124425277437769688639924217837557266135" + }, + "min i32": { + "raw": -2147483648, + "encoded": "-2147483648" + }, + "min i32 - 1": { + "raw": -2147483649, + "encoded": "68956915425095939579909400566452872085353864667122112803508671228696852865689" + }, + "float 0.0": { + "raw": 0.0, + "encoded": "62838607218564353630028473473939957328943626306458686867332534889076311281879" + }, + "str 0.0": { + "raw": "0.0", + "encoded": "62838607218564353630028473473939957328943626306458686867332534889076311281879" + }, + "chr 0": { + "raw": chr(0), + "encoded": "49846369543417741186729467304575255505141344055555831574636310663216789168157" + }, + "chr 1": { + "raw": chr(1), + "encoded": "34356466678672179216206944866734405838331831190171667647615530531663699592602" + }, + "chr 2": { + "raw": chr(2), + "encoded": "99398763056634537812744552006896172984671876672520535998211840060697129507206" + } + } + + for tag, value in values.items(): + print('{}: {} -> {}'.format(tag, value["raw"], encode(value["raw"]))) + assert encode(value["raw"]) == value["encoded"] diff --git a/aries_cloudagent/messaging/util.py b/aries_cloudagent/messaging/util.py index b3d19c32b4..5d182e7fc1 100644 --- a/aries_cloudagent/messaging/util.py +++ b/aries_cloudagent/messaging/util.py @@ -1,12 +1,17 @@ """Utils for messages.""" -from datetime import datetime, timedelta, timezone + import logging -from math import floor import re -from typing import Union + +from datetime import datetime, timedelta, timezone +from hashlib import sha256 +from math import floor +from typing import Any, Union + LOGGER = logging.getLogger(__name__) +I32_BOUND = 2 ** 31 def datetime_to_str(dt: Union[str, datetime]) -> str: @@ -98,6 +103,39 @@ def time_now() -> str: return datetime_to_str(datetime_now()) +def encode(orig: Any) -> str: + """ + Encode a credential value as an int. + + Encode credential attribute value, purely stringifying any int32 + and leaving numeric int32 strings alone, but mapping any other + input to a stringified 256-bit (but not 32-bit) integer. + Predicates in indy-sdk operate + on int32 values properly only when their encoded values match their raw values. + + Args: + orig: original value to encode + + Returns: + encoded value + + """ + + if isinstance(orig, int) and -I32_BOUND <= orig < I32_BOUND: + return str(int(orig)) # python bools are ints + + try: + i32orig = int(str(orig)) # don't encode floats as ints + if -I32_BOUND <= i32orig < I32_BOUND: + return str(i32orig) + except (ValueError, TypeError): + pass + + rv = int.from_bytes(sha256(str(orig).encode()).digest(), "big") + + return str(rv) + + def canon(raw_attr_name: str) -> str: """ Canonicalize input attribute name for indy proofs and credential offers. diff --git a/aries_cloudagent/verifier/indy.py b/aries_cloudagent/verifier/indy.py index 293d3460ab..bb39a8815f 100644 --- a/aries_cloudagent/verifier/indy.py +++ b/aries_cloudagent/verifier/indy.py @@ -5,6 +5,7 @@ import indy.anoncreds +from ..messaging.util import canon, encode from .base import BaseVerifier @@ -22,6 +23,69 @@ def __init__(self, wallet): self.logger = logging.getLogger(__name__) self.wallet = wallet + @staticmethod + def check_encoding(pres_req: dict, pres: dict) -> bool: + """ + Check for tampering in presentation. + + Visit encoded attribute values against raw, and predicate bounds, + in presentation, cross-reference against presentation request. + + Args: + pres_req: presentation request + pres: corresponding presentation + + Returns: + True for OK, False for tamper evidence + + """ + for (uuid, req_pred) in pres_req["requested_predicates"].items(): + canon_attr = canon(req_pred["name"]) + for ge_proof in pres["proof"]["proofs"][ + pres["requested_proof"]["predicates"][ + uuid + ]["sub_proof_index"] + ]["primary_proof"]["ge_proofs"]: + pred = ge_proof["predicate"] + if pred["attr_name"] == canon_attr: + if pred["value"] != req_pred["p_value"]: + return False + break + else: + return False # missing predicate in proof + + for (uuid, req_attr) in pres_req["requested_attributes"].items(): + if "name" in req_attr: + pres_req_attr_spec = { + req_attr["name"]: pres["requested_proof"]["revealed_attrs"][uuid] + } + else: + group_spec = pres["requested_proof"].get( + "revealed_attr_groups", + {} + ).get(uuid) + if group_spec is None: + return False + pres_req_attr_spec = { + attr: { + "sub_proof_index": group_spec["sub_proof_index"], + **pres["requested_proof"]["revealed_attr_groups"][ + uuid + ]["values"][attr] + } for attr in req_attr["names"] + } + + for (attr, spec) in pres_req_attr_spec.items(): + primary_enco = pres["proof"]["proofs"][ + spec["sub_proof_index"] + ]["primary_proof"]["eq_proof"]["revealed_attrs"].get(canon(attr)) + if primary_enco != spec["encoded"]: + return False + if primary_enco != encode(spec["raw"]): + return False + + return True + async def verify_presentation( self, presentation_request, presentation, schemas, credential_definitions ) -> bool: @@ -35,6 +99,13 @@ async def verify_presentation( credential_definitions: credential definition data """ + if not IndyVerifier.check_encoding(presentation_request, presentation): + self.logger.error( + f"Presentation on nonce={presentation_request['nonce']} " + "demonstrates tampering with raw values" + ) + return False + verified = await indy.anoncreds.verifier_verify_proof( json.dumps(presentation_request), json.dumps(presentation), diff --git a/aries_cloudagent/verifier/tests/test_indy.py b/aries_cloudagent/verifier/tests/test_indy.py index 96c1b8eb5b..f6b18eee64 100644 --- a/aries_cloudagent/verifier/tests/test_indy.py +++ b/aries_cloudagent/verifier/tests/test_indy.py @@ -1,21 +1,467 @@ import json +import pytest + +from copy import deepcopy from asynctest import TestCase as AsyncTestCase from asynctest import mock as async_mock -import pytest +from ..indy import IndyVerifier + + +INDY_PROOF_REQ_NAME = { + "nonce": "15606741555044336341559", + "name": "proof_req", + "version": "0.0", + "requested_attributes": { + "19_uuid": { + "name": "Preferred Name", + "restrictions": [ + { + "cred_def_id": "LjgpST2rjsoxYegQDRm7EL:3:CL:19:tag" + } + ] + } + }, + "requested_predicates": {} +} +INDY_PROOF_NAME = json.loads( + """{ + "proof": { + "proofs": [ + { + "primary_proof": { + "eq_proof": { + "revealed_attrs": { + "preferredname": "94607763023542937648705576709896212619553924110058781320304650334433495169960" + }, + "a_prime": "...", + "e": "...", + "v": "...", + "m": { + "master_secret": "...", + "musthave": "..." + }, + "m2": "..." + }, + "ge_proofs": [] + }, + "non_revoc_proof": null + } + ], + "aggregated_proof": { + "c_hash": "...", + "c_list": [ + [ + 1, + 152, + 172, + 159 + ] + ] + } + }, + "requested_proof": { + "revealed_attrs": { + "19_uuid": { + "sub_proof_index": 0, + "raw": "Chicken Hawk", + "encoded": "94607763023542937648705576709896212619553924110058781320304650334433495169960" + } + }, + "self_attested_attrs": {}, + "unrevealed_attrs": {}, + "predicates": {} + }, + "identifiers": [ + { + "schema_id": "LjgpST2rjsoxYegQDRm7EL:2:non-revo:1579888926.0", + "cred_def_id": "LjgpST2rjsoxYegQDRm7EL:3:CL:19:tag", + "rev_reg_id": null, + "timestamp": null + } + ] + }""" +) -from aries_cloudagent.verifier.indy import IndyVerifier +INDY_PROOF_REQ_PRED_NAMES = { + "nonce": "12301197819298309547817", + "name": "proof_req", + "version": "0.0", + "requested_attributes": { + "18_uuid": { + "names": [ + "effectiveDate", + "jurisdictionId", + "endDate", + "legalName", + "orgTypeId" + ], + "restrictions": [ + { + "cred_def_id": "LjgpST2rjsoxYegQDRm7EL:3:CL:18:tag" + } + ], + "non_revoked": { + "from": 1579892963, + "to": 1579892963 + } + } + }, + "requested_predicates": { + "18_id_GE_uuid": { + "name": "id", + "p_type": ">=", + "p_value": 4, + "restrictions": [ + { + "cred_def_id": "LjgpST2rjsoxYegQDRm7EL:3:CL:18:tag" + } + ], + "non_revoked": { + "from": 1579892963, + "to": 1579892963 + } + }, + "18_busid_GE_uuid": { + "name": "busId", + "p_type": ">=", + "p_value": 11198760, + "restrictions": [ + { + "cred_def_id": "LjgpST2rjsoxYegQDRm7EL:3:CL:18:tag" + } + ], + "non_revoked": { + "from": 1579892963, + "to": 1579892963 + } + } + } +} +INDY_PROOF_PRED_NAMES = { + "proof": { + "proofs": [ + { + "primary_proof": { + "eq_proof": { + "revealed_attrs": { + "effectivedate": "29898645652691622994103043707423726726370719600737126045061047957925549204159", + "enddate": "102987336249554097029535212322581322789799900648198034993379397001115665086549", + "jurisdictionid": "1", + "legalname": "106000828387368179355563788886235175190145445419967766011746391966411797095112", + "orgtypeid": "2" + }, + "a_prime": "15004053730967415956444780426929245426212215338862984979494015601906315582840747306504594441147441231491693951307278868750626954115009843921712832446544313561614118651520859494434080523236571958503756731624044004577892061145780190353067193496632483652558392939182437813999901132281095751156851493821923092362225145694407463842363472935374563198989094026343235461171230866928987229440390088485243428084237480758852248249770191814659757536925909483623366615812343227994433513635227834136882757394235805747686707186194818800509367263735891033464810268941516104197138946893490285348940539273855011764023467736767154303840", + "e": "337235637061060569047727820825037317712308782222370290484075504679799877011498224496826887984625822621748120654975531604507028064312710", + "v": "1404574530639210172781710601270953478414552186112985513475784201805119858770941821816370201652610496512142438596496007803868074196519046400754620766301997215969127187833134416898687892635798644651536667962849945968608408680347359937747715599800353850666709655353571249823190377976481837350280859973291095846106817174217510384400072134061086282647508604512946800721425580606901739211324799734725830882957974114794011791236006123406974194631084620463349145771704097181067806553409326685136263002734388842031423620455266365851581883497063570426034222596154597920580362387253753317413050267993785894175555001456331223234400596625730555935567545822248399326429854362227165802672227905967242505077485029657064067770641969647406371744932313880132835781524174868335472062214928455106355639700336515509695339440337721239602256387991397127509846614577908429409389332146746885470613002111095896313068354016587589778644661193149185049", + "m": { + "master_secret": "268741899404098839327031223989228937242803085201179726908056281850709820406283972250249379228789368664433583241086441517910928033266925485611584652328638784395957058632060633630", + "busid": "2687197004064133543257369626470144380098036289489284489320086515026620206692616047425976133587124290887441908383692364439260071404270430528078491104384060203570606253676528361400", + "id": "6686713960986576137959547581149682718587656100042127047852747024276212127252400140409890726173570723819441146289878657604374865560165489933600436341950054222778208816245032311193" + }, + "m2": "1180732317592917288409508571561928260151012766032216949553655321777067495114084046539503538100319204468787213948625648828272873800122130063408401311370987" + }, + "ge_proofs": [ + { + "u": { + "0": "15775609194986735920510151800942995799222803216082415810148803816296803079801357496664353906579826995829149362968465835795491271435248746459334118965204125314594582971550392227954", + "2": "5303150256152520023495176881750201750170184894234097909710215547442554470805609846521764595898911334528530696240025838754931022084938196723161868181531727845300439592437899863887", + "3": "3356711078459696620189646681109895593397921422760359051406583045001333345458592898545852513866307624143916692556089833035405496562577023756005223378326300905996972689863856066875", + "1": "9999991890173781186974768504758157527548652482914116775165195164578745484991479122468109103928320060297494255214338396428491092606606051561499468708339979065194763516537003502062" + }, + "r": { + "DELTA": "1435090146724677611480872211988213747514582597135551797832629955760022689079479873681839403744643599039883834204615937515288097736927712499250203649611222666450687692819628191366070914555251320872315378202337414304735555708434851449005494065128333408295370378734399236857073675785782330461793283646613324794741612075132251003819809779185772616720952264615331933630593162857145006881047266047864525898689246790061753791575361871922643386721142202508891103428155725164118848489256450446385140752308548079412012057535799088600334139468432242004848224338715577616491890083382988533414746224157485737168172255373805848589505587117269746736884630803388115258573174965628402748672653106950672620945656786479587908733067646954", + "2": "1256008392268065460119207279471943768595068414860014149178278435399371400930962253759162888062020269227529923329167742931240473191566641468995735758696802138379814852469042293401437137956018945170092817785505583108837356735852654194156319248319729732466320634812831259869290012647072233952795236462156213752008019954481267917886292498492055846838619027167304191382208021540244250507570410888356448310603088364351895116324030484480320862223729665151544010778941061938440283026451178172286282191179070116776836046514823559685428369094109958537683453915206656040875788707049636999992215238431149080323327641760705766913474027428111260788981734182250598573031877786769378931547452684486997457718460021235476398326984192784", + "0": "1106819115015372998825208031668263762670044285179584053573615157030968633235403572251376628759852167093842839880087972608252236859761641404161906797947710722723839146345785722305071566665021165225324459369096631275993154775947819333058721055644040212303789659749985973470385218248603826878093609862767077416104661216163222886987607841769251824856950498177308519655255200045046063857789306026581362754683975573850037114774186895901788964351934533171525025276070855270632786783019588176816118329221122549398793872640055312900842112041891936494042853798319986365192512964078607266631918748545903216736690057842950922926661694759259530843862322858400156976838479950950178486526234308178957984785053903260967594398611911474", + "3": "1344309321242892215222847471501532826517184846819833677474602495849657271930678291855112591971466462816524573183554788643533109793416521709602069842696124889558288092186793062177006244758779556603409762571362221142413760629539533275654542467194539359678435299002566931998816165917234259226849828723125451685169672272552524344813036153633311318760938874320338280443847065712732394378892985736654998112090834297537844732478643713076998558297751199030671616253345870616092528684635775411928128373368327191277066131632614473951005152162823879892345970535505519113833062530738837915987508410926372810518540478552946670006272356196419957933718303344632112441115930033837912179851905872564389256853587645059720488720795906498", + "1": "601693817301763663113031272722721908754633550776510238958619960119672962844730314111437951375084589705366750107667669458320527173785853103929038523863706300574327283273485302578112396814149563941340189390051835244496748959403476105143355455812570759887645896592114448469303958006046663589996470308366068555479184906610439541373120510006128200782324694975090482529033281708168823833732457689747330091963586305323138559502300486975246644545238909598413498252470653544977963083975726047754021026165970401681664501179243533611966433308438886961268871140737772352678991735861225177227793364352974323624694500485545573621034350559474030565509027433457718466600471361048730018443642651540442802817989514889987171548775560085" + }, + "mj": "2687197004064133543257369626470144380098036289489284489320086515026620206692616047425976133587124290887441908383692364439260071404270430528078491104384060203570606253676528361400", + "alpha": "55264634475788812054149982413198771839810724235465324658821557285735947681415835295178267002738090787902834904063083682990582592095393028970773939852521059447360650213986737569312363077820486616943853008592650537183003498185887824618357246364458614494253289122927160626742649252943244636915456680482390825080294565093068093917997001255757200832353046300646785756652682640188703523223073037006585218839054980180609464837830370157522462983934135435603408143309318659202555550473599548567996557919032937165600303958449173855781262863161799425917680286809410314205550551542955745937751254083650878398344461109371177805333303453760504594222290495116260958547048583654306199387054245295488649024179114894686831993370968945510894767150406222332165620064150891563554498413420757277508788138394747656372783710437243804659113648361274361422790365575", + "t": { + "2": "1276353167840913477021397624773394332173592088650367702185572394040398533199538101776458275797662881371280361310311170677242402214354355702620614537036611922064060504606618126681639882263139365680565350790281701009940301284340534766480451762902788628875609130151618956111512660983755135355570760793108220842022869639781026918247205511538713530652099730605791686827103126406846076633375908411453922078354225032716111673736810973402770388177401531928271370790938081733309345905963052715943136682338494175330354955277424030755355371412956250746882945100461786601740318616758180741835591171045104436982446340050589105952", + "0": "52506109491039096251755479392960889070840776962363540274456217953760113102006029814040519995494713986268145627084927516727099691151450378385140332116480118436738261593744184296007314732823898043080011956933010369575980799348117283597824162615912372823633177749168952698401203464607973674241038357379577293158404669765882906589960120865518413803711729942613061301420107178603192154873722316947550106277771120767826035047479123749931790881679576800340417944013614994751361795012191068369383577242249201927422484806926120532089036692818076818060938822432774203557319821915034796962936855918437128832683302834778450852076", + "1": "113031374658594175812052384858113115052077482873081996361152721528334589441352531310470368095073157716273853401381658707580502108484382463859531044307244944300120928991532655473230562771713806228238940140492981669914382036157400059197253018428984542349187927786210979478008036674432605219414300881116700073904513558719492127462395417843765324361843076852973933175787635618464392198807598044268223652564648024618437362752148593227485835178720349721798423100634521510710239416375840314170338898512726956877281625226003452828033987655579773273571285524048285234475184043290899568731903112287738739915600509899766360789888", + "DELTA": "48234611140928682288937615809872962358698394776719271528059766394227502012090856649758227578113306604028516575292703546202775777621049060595611852517094547384541819122623967215175704296901562660240718967260151010609870475975072516070346770954330313963878747194405855012585768501635077016535846206257741952202337055842434195875166686634891739392750890861333875772954056854354284061793365725202163447856793288398072711194949704852318180275797984445814279136152858759907525062790250675184786142234427994860090376938644764493873560454829155051260697226196758890394411645758956396137763703934929680277278644873416013261035", + "3": "89994605437763910628730772379416923861874648327020237340785010128698483324987645925227420742287632948945347297152300219419713493590120999381541274609870183955909628256613851122899039933589797230083354701292272442523280565440597314568786864750837443422276701528731625877274094155541825495114060437788769205202442723879088098866185978654728309516302335284177924161235100925296934812127598754913984676011716654143603885735997160890946409226842054727795290304131313120189570773196857529159798597569189742987994905034522112705638567954037460125246215182613760404547369876267284411245030884496328403051974209422359756153509" + }, + "predicate": { + "attr_name": "busid", + "p_type": "GE", + "value": 11198760 + } + }, + { + "u": { + "0": "13639548796026429922431564475630909149287414026758460721805236736313279517016438050089911517098811596997747189614439260518531845477684148307804856579405503329745365642794423965550", + "2": "12692415150154152887167590190910159618471206042982658652940787170770193806407265717354418163057121876574358366510055892372348735991661901637525227498965237677355250159501068181772", + "3": "6699159556719214469836363462599679663866420825429540116943002714507804742697411533141864346616123740789790632843719915716457061440487115732563925309886301301835201778554620543295", + "1": "2018654799729593932888298230804022878883145101317651811950082851492082577094184498971399238402895197739207931768086301073280634251050932415705600476284738694155135236800581664160" + }, + "r": { + "1": "825587756964975640126314737718300012891046538726331178577448524710910340957817679849290109848304786342311186386453239759474660538454793939540876256076287017677140704068118361949660090673111340635478762304690817532764517905140299716866605223450803768338360729151901747687349983483402342999368967231581939563361347289212973086454185400770130710116840233323953976914342262402301362679497329671787598650893202541829399630505463177921655009726556920408538662140155815031458475909120161960047235187953148398737965729023268444789967620657212914775071615366971436269789139928904779054710447116218434690464549160131819794059427689273427325814904354192089075836597740878803445045080385629565176143354201573860707045668850877586", + "2": "1466408189748340763973829793343949568330918709265623621614464341218317503955515434953266875378586538446326464353600075579788794127665478299651259465473747112701101990004860122720151191106445704432013015062973865716673386400413561687311954374930156679604666267815298214479078026652043482916898087471155683856282470644588563159648375551108786970597383143516158031628710096807215305878905007543811401502472821013567629888746492557864905681554913361277548019219082051265255078152509205293776781790132507115787621452248689332496610099725566623311760857590035073594921664074567131690599897210005475078142722295326868452002437292574903183037228401231409631285848202575278151773369676950274790626198680132560950102001994557758", + "0": "993248502537248262082444202395290853332499246354083708269674970707520839045168624341335318664418224639164402187209309139427257892643191846187663592057257899679944076599283980872521437340751206357777926871742796186382563827967273141200749480590415594087209691507734426984052841712131263160951495974745152392404724577427973267669378931113495076274617344076060846279028767371296979484895771867209047720463195305161885422275388748188299814182891315332800557749699941587327916028930365349641271736635219800975554147836564077611147631789530042925759823398087582121686407890628257624663383236878047170688254415445440912626941967028065807021170264150964938678824504194752040131898249057197187446968567390619785928296680096859", + "3": "353677912339120670248802964352055631737613331947764251954000578577314223482877266750851861467829550374246392637478716468616296688578414836737374015352059254057436572686513161681724599053168679581126352074962010335889993562619355121275432902043064229165956511160994192882167562213269670332262473472293819501037932879123080023576285854568501212240875918139761976977842939660466373041805369493971290555885442554468124891943099059169515428968196495673746803133324864149723509564523971808556630671471618581233229134929554792186889060256901637092067130348403992303346483664985586122149628146304160243882639275298266216270358565584574585823864941692911554602002331492551293859949912337984877479524597804956696499812250631744", + "DELTA": "725960022886687948013207416539699149371621853290822104811918058808196468403337509381122781137942343897440199450987104988666229964851227549448628470704889721866971126265999067769808855341632931627785927114398786533559660381398895352266657934136549351825103362166280268159652759301507640976500533521688660251972577237532256300306442315564311264115224457865178259661593100327194825492692234619818096596609477148829377559407992257373097100180145505767561403356284282388735420784241021016181364636135275395790815788682767997871662899508826815736302921531147145381730507095314577476550947092200539059112480501048978059997520366967856033897452966490827003353334313372398949710717623991939354590550708881302450618430658953556" + }, + "mj": "6686713960986576137959547581149682718587656100042127047852747024276212127252400140409890726173570723819441146289878657604374865560165489933600436341950054222778208816245032311193", + "alpha": "54312418620368017823413444392364697511954099195960921763340447211826963863335156427497199363801396644023918819073111783414569539781613083737557451917064836287105910850065875966424715696905777194811070071499968289670886194094119693198719726955718469770568556811780821894560508716495412081426259363632509089906620904790770113618876886851367553577555822830824722182497761114967889600421573310792308390968429341290356015872285765321156360499004114406293720515635636721256956836801168192621092752489119545742530767529595705696014856308531466145146269599634259697543058622520958051728230537251854292098956994695268415292349999637984082162556184322623578612708830627477718675001902228134597558345283147625462346943667586065769392740787755841399970302076200764539143397370091692013055692886714129148712005056929884477612627289722508451690081998890", + "t": { + "3": "76842650074027971332631982512373611181628371639695357946107030911055453488768447213460618917725534086368162318588252003797289252473279448248400376609193928062810022884201102892017821282461806593568305060473753735848560048445524907113838106958747793434918052694775405184619214354190540002998204225798499364075579094271521191419027986291013493577021803670203051346914082929873231509819450163988354047777312127725561922611471445963909565688013793926876707562644935391518355932605047591545917637465241017629839541260483606708345518662351776889719949822005165906622964213143757683950646046295114922019124075069329268061942", + "2": "104991045405164906316724339229643785709360971949973916361929774804163421784479300621496063132861029493850348596359070365652827572699577454378465299784873962729586537933990712981855548459986825452865420618489151243413027040820258308949176618728507177438646401022030966936494703173837070422031040550750643315987178063356959004909489540688791639398005266908038895531691252968451136025538449648159989963830846794193607106472742567850015960071634812903985081979755017126350806404047244177458032873066418448813920685609285163826032405474833353441325867090653794998832828049943461795570528006274431422907140560130037296666626", + "0": "93372553202246858510371387492221683266873274595585378473760313800346458391438909787465170333251843314544241604938410847073082151810448655558028921073676767770394665021417900636520680814177493616534162641758512946743051333557436759523671912141418810442158225543010238061117969558203880853763255647243160765086932831295304550412607848190595598510980669944139696363322475177492264636536910201776020324858798972778323663795303339939472573927415127166116444898790357846635883222746031584554927383535016321617425087697872601850303134185636960112124926520878185699975818343081756286170638877967660840814776000077787223928056", + "1": "88156501142569212422367853754801651086852287000049991938144173063936879655987557042149874374683234911554850776079721311154420204826376746982087019508277766132575858575556680538019849786965963718649479179859820106973881788608463705644074554956818391872137271784803047333543321479251515998725336896820211102747123583803854741248907240437683401575881169746704849524328003061107258995982062254548684849294595639491104266371155934951313704136302996039897528196270331875472554549327417349243990461246127383357748906616773662459665620147625796186736530089927957522542298814250937114283836911153790542409683746775259226224961", + "DELTA": "6178997688515360528852083990605883033892934661031543684879979804577432521872124008044788245406591933749401429548633356472853716766388636618335206416158216292785839570827245139150787585027801572977051847786797012358936548986405917266204321163760568135873831346087680040040301251630530064206552793273933549993844498438010903850013120770715837075880286264742500598494248510064600863411203212869270221192303957773402376357672080257393369434247825409313396018869267942811592657266119556377402842108726474978400793026037873416208879964428023321485607453655856252140587803891157033568210852205447175844430607889546700526279" + }, + "predicate": { + "attr_name": "id", + "p_type": "GE", + "value": 4 + } + } + ] + }, + "non_revoc_proof": { + "x_list": { + "rho": "12B28F49BF5F2CDA105B904CD594EB5B5F558025CDDB7D0F3057D19830F81694", + "r": "010F2B872DC4BECAE085D9FA1FB98184C3E00181A678F2B256140482B4DEDFCE", + "r_prime": "1AAF1AB0071B64FE22AC42219962B9ABA02147B09DFDC4C1FD088E6706D312FC", + "r_prime_prime": "1630D0800ADE33816BCA96EE89EC1E312BE80220510FAFAAC52BED567B187017", + "r_prime_prime_prime": "14D06B2F7B369880821DAAFD40D74FE3B495EE3A7CB7E937FDC4E9707330F301", + "o": "147F16718A0CCB2EC137ECA3952C801FB2281B06CB4ADC24092CE31CA2EAC5AD", + "o_prime": "14F4668810341353E0C25485C4F3CF459BCB69DD74FF73376A23ACAA550E09C5", + "m": "0EAC754EE9AC81C495AC3BB302511034965965AF337BC4F43850A1636E70314E", + "m_prime": "07CA764055E9920E7C4417C3A63BF610C145F25D618A41DAC785210D7320F0EF", + "t": "199D84A1133FB103E4E77CC6F917A12355AD4A29DCCC24999A2C67EBD62B5306", + "t_prime": "07154F39841E3D75E1E07179875B94D655E3BDD4A349E0BBAA43422CC527AACB", + "m2": "0D4380FF8ACDC21611BC8AB83127950441DA42A49A347BEC6F32044F033D3017", + "s": "0A65AE9D0C0D4CDAA5D4EECB48BC6DFD2279BD2C040AC0D9011918A9E0A7A866", + "c": "0ABFC02DDF76995C48CADEE8447665EB933446FEC42E7074FB11720E141CFC07" + }, + "c_list": { + "e": "6 418D8713ED93CD8C065EA42D110C581C2CE07A58771077B1C2016E53AA2E7461 4 2032A4917D0877B9723CDCD82B32AC96C534B0CAA5ED2EE3FFD605214511CB1F 4 0D8E5DA074651A0DE91F86F663F071EA4D4CD4CBA438F7A4D182C8D23D01B485", + "d": "6 37635F35298D224C0E3F01EB06DC8AC1D8A7E048027162077E0204801F22FF94 4 1E64440E13B08BD249B5C35B637C70BDA471926F5F3896400ED25EDA4678B73D 4 3A5BB704B473894CD54C91D1D159A7BD8FA8092545F93D1BC195D52D3EC96EDE", + "a": "6 6000DC780B9D7C71575A328DE2BACB78A2737E9C1CE64BC8BCE98BD8486EAAB4 4 39555F38DB15EC820DA3A7A61820F831A003D414D4A0EF60D1D37ABD8B5E1070 4 25FBA1AD320F02D9082118E978B4FE261280951BCE1FED15F65771AE04F8E270", + "g": "6 5D293948EF43989ACBB8262B8C7F10A551AD71190D70B9AAA62943C4FE6A4C42 4 2B3E1ED0A00163DCA9AD9B69DDA124290CF8F580F60595B5E9D506A3C0D9A903 4 29C2B6F7AD7F7B223FC40BD9C1147FCE831B26ACB477855C9D3EABD7B0341342", + "w": "21 1371C921AE2377A1CD9F0D3E863B09487B6DFC0DC5F2BA32133E4F5EF2ACA5641 21 10B84BA9167755980B1DCD97AB698D56E3C9CDCBE7A85F0776A2C96B3BE9519BE 6 6676ADACEC607381F87211DAE4DE6A630B74FAF580DBC383D8450C7852BC09C4 4 379C9A4FF46DEBF21223823D5B2323F7A56A394157E94DB95914A9E5BB27FAEC 6 7121D621C85D9BA22371A0862909FF25198F0EF690207AEE3910FB0E0A7A4F62 4 1C052A0276360F0D8AEBA71BD65ECB233FFDB700F031EA03146CF00BC2F2D5B6", + "s": "21 1272F477F5A0F83CCB316DA088F6A6A12C131D0DC9BC699023F534624B8EE255A 21 13816855011465BE2E8972F52EE4692873A763513A764BD92B8B7CBBBAA27D7E8 6 7B190F599B5F0EA53802135BBD655B080743FE60CC22329F69770D6B765F0AAA 4 2AAA191CA59348C6A920BD1D1AE37A7C96F424B6D8E921B54EA5C1C7C56297AA 6 80254CA5DFBAD3C39BC757534922FBD0846AB86500D5D168109EB6B8A9D2BE33 4 1CC93B3769A7BE2AF52CCE391D2BB57F9D907F530038EF84B3EC4AB54D62D872", + "u": "21 11E538813B74EFC8676EF5AC87AA05A0FF58913B7C68E264FCF5ED0D57F6BC781 21 12EE7BE65E15CF4C500E2D92DB02670FBD8B51C6BD0B35AE139E9CE9658B15CC2 6 856B3C0C152F75A449AD73DFAD7DFD87A99AAA606E3D8E392D765E3C987D7B47 4 34245F01BD7C4144DBEBE7AB35303BF02FB5717EC6B080BC9C2C930D929D4ED7 6 8113F127D8762B174DCB32AEE370297BF7CFCCF797510B53D53564AEC9105909 4 3B2434AD9AB4E7ABA7125800D14470A098AE04FA523CB60A6FFF62D371B95E13" + } + } + } + ], + "aggregated_proof": { + "c_hash": "37672016063516849654668323232510746418703126727195560560658262517075578769045", + "c_list": [ + [ + 4, + 0, + 0, + 0, + 0, + 0 + ], + [ + 4, + 17, + 153, + 0, + 0, + 0, + 0 + ], + [ + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 4, + 1, + 134, + 126, + 0, + 0, + 0, + 0 + ], + [ + 10, + 250, + 248, + 125, + 158, + 54, + 165, + 91, + 59, + 1 + ], + [ + 4, + 167, + 169, + 22, + 44 + ], + [ + 31, + 254, + 53 + ], + [ + 118, + 218, + 1, + 27, + 51, + 96 + ], + [ + 1, + 254, + 120, + 236 + ], + [ + 3, + 127, + 97, + 134, + 148, + 32, + 128 + ], + [ + 10, + 124, + 191, + 32 + ], + [ + 32, + 59, + 96, + 254, + 165 + ], + [ + 195, + 171, + 64, + 72, + 40, + 235 + ], + [ + 2, + 175, + 185, + 172, + 248 + ], + [ + 2, + 152, + 166, + 185, + 65 + ], + [ + 3, + 63, + 176, + 24, + 2 + ], + [ + 2, + 96, + 182, + 196, + 220, + 182, + 246 + ], + [ + 48, + 242, + 116, + 58, + 18, + 199 + ] + ] + } + }, + "requested_proof": { + "revealed_attrs": {}, + "revealed_attr_groups": { + "18_uuid": { + "sub_proof_index": 0, + "values": { + "effectiveDate": { + "raw": "2018-01-01", + "encoded": "29898645652691622994103043707423726726370719600737126045061047957925549204159" + }, + "endDate": { + "raw": "", + "encoded": "102987336249554097029535212322581322789799900648198034993379397001115665086549" + }, + "jurisdictionId": { + "raw": "1", + "encoded": "1" + }, + "legalName": { + "raw": "Flan Nebula", + "encoded": "106000828387368179355563788886235175190145445419967766011746391966411797095112" + }, + "orgTypeId": { + "raw": "2", + "encoded": "2" + } + } + } + }, + "self_attested_attrs": {}, + "unrevealed_attrs": {}, + "predicates": { + "18_busid_GE_uuid": { + "sub_proof_index": 0 + }, + "18_id_GE_uuid": { + "sub_proof_index": 0 + } + } + }, + "identifiers": [ + { + "schema_id": "LjgpST2rjsoxYegQDRm7EL:2:bc-reg:1.0", + "cred_def_id": "LjgpST2rjsoxYegQDRm7EL:3:CL:18:tag", + "rev_reg_id": "LjgpST2rjsoxYegQDRm7EL:4:LjgpST2rjsoxYegQDRm7EL:3:CL:18:tag:CL_ACCUM:0", + "timestamp": 1579892963 + } + ] +} @pytest.mark.indy class TestIndyVerifier(AsyncTestCase): def test_init(self): verifier = IndyVerifier("wallet") assert verifier.wallet == "wallet" + assert repr(verifier) == "" @async_mock.patch("indy.anoncreds.verifier_verify_proof") async def test_verify_presentation(self, mock_verify): + IndyVerifier.check_encoding = async_mock.MagicMock(return_value=True) mock_verify.return_value = "val" verifier = IndyVerifier("wallet") @@ -33,3 +479,145 @@ async def test_verify_presentation(self, mock_verify): ) assert verified == "val" + + @async_mock.patch("indy.anoncreds.verifier_verify_proof") + async def test_check_encoding_attr(self, mock_verify): + mock_verify.return_value = True + verifier = IndyVerifier("wallet") + verified = await verifier.verify_presentation( + INDY_PROOF_REQ_NAME, + INDY_PROOF_NAME, + "schemas", + "credential_definitions" + ) + + mock_verify.assert_called_once_with( + json.dumps(INDY_PROOF_REQ_NAME), + json.dumps(INDY_PROOF_NAME), + json.dumps("schemas"), + json.dumps("credential_definitions"), + json.dumps({}), + json.dumps({}), + ) + + assert verified == True + + @async_mock.patch("indy.anoncreds.verifier_verify_proof") + async def test_check_encoding_attr_tamper_raw(self, mock_verify): + mock_verify.return_value = True + verifier = IndyVerifier("wallet") + + INDY_PROOF_X = deepcopy(INDY_PROOF_NAME) + INDY_PROOF_X["requested_proof"]["revealed_attrs"]["19_uuid"]["raw"] = "Mock chicken" + + verified = await verifier.verify_presentation( + INDY_PROOF_REQ_NAME, + INDY_PROOF_X, + "schemas", + "credential_definitions" + ) + + mock_verify.assert_not_called() + + assert verified == False + + @async_mock.patch("indy.anoncreds.verifier_verify_proof") + async def test_check_encoding_attr_tamper_encoded(self, mock_verify): + mock_verify.return_value = True + verifier = IndyVerifier("wallet") + + INDY_PROOF_X = deepcopy(INDY_PROOF_NAME) + INDY_PROOF_X["requested_proof"]["revealed_attrs"]["19_uuid"]["encoded"] = "1234567890" + + verified = await verifier.verify_presentation( + INDY_PROOF_REQ_NAME, + INDY_PROOF_X, + "schemas", + "credential_definitions" + ) + + mock_verify.assert_not_called() + + assert verified == False + + @async_mock.patch("indy.anoncreds.verifier_verify_proof") + async def test_check_pred_names(self, mock_verify): + mock_verify.return_value = True + verifier = IndyVerifier("wallet") + verified = await verifier.verify_presentation( + INDY_PROOF_REQ_PRED_NAMES, + INDY_PROOF_PRED_NAMES, + "schemas", + "credential_definitions" + ) + + mock_verify.assert_called_once_with( + json.dumps(INDY_PROOF_REQ_PRED_NAMES), + json.dumps(INDY_PROOF_PRED_NAMES), + json.dumps("schemas"), + json.dumps("credential_definitions"), + json.dumps({}), + json.dumps({}), + ) + + assert verified == True + + @async_mock.patch("indy.anoncreds.verifier_verify_proof") + async def test_check_pred_names_tamper_pred_value(self, mock_verify): + mock_verify.return_value = True + verifier = IndyVerifier("wallet") + + INDY_PROOF_X = deepcopy(INDY_PROOF_PRED_NAMES) + INDY_PROOF_X["proof"]["proofs"][0]["primary_proof"]["ge_proofs"][0]["predicate"]["value"] = 0 + + verified = await verifier.verify_presentation( + INDY_PROOF_REQ_PRED_NAMES, + INDY_PROOF_X, + "schemas", + "credential_definitions" + ) + + mock_verify.assert_not_called() + + assert verified == False + + @async_mock.patch("indy.anoncreds.verifier_verify_proof") + async def test_check_pred_names_tamper_pred_req_attr(self, mock_verify): + mock_verify.return_value = True + verifier = IndyVerifier("wallet") + + INDY_PROOF_REQ_X = deepcopy(INDY_PROOF_REQ_PRED_NAMES) + INDY_PROOF_REQ_X["requested_predicates"]["18_busid_GE_uuid"]["name"] = "dummy" + + verified = await verifier.verify_presentation( + INDY_PROOF_REQ_X, + INDY_PROOF_PRED_NAMES, + "schemas", + "credential_definitions" + ) + + mock_verify.assert_not_called() + + assert verified == False + + @async_mock.patch("indy.anoncreds.verifier_verify_proof") + async def test_check_pred_names_tamper_attr_groups(self, mock_verify): + mock_verify.return_value = True + verifier = IndyVerifier("wallet") + + INDY_PROOF_X = deepcopy(INDY_PROOF_PRED_NAMES) + INDY_PROOF_X["requested_proof"]["revealed_attr_groups"]["x_uuid"] = ( + INDY_PROOF_X["requested_proof"]["revealed_attr_groups"].pop("18_uuid") + ) + + verified = await verifier.verify_presentation( + INDY_PROOF_REQ_PRED_NAMES, + INDY_PROOF_X, + "schemas", + "credential_definitions" + ) + + mock_verify.assert_not_called() + + assert verified == False +