def verifySignature(self, msg: Dict[str, str]): signature = msg.get(f.SIG.nm) identifier = msg.get(IDENTIFIER) msgWithoutSig = {k: v for k, v in msg.items() if k != f.SIG.nm} # TODO This assumes the current key is the cryptonym. This is a BAD # ASSUMPTION!!! Indy needs to provide the current key. ser = serialize_msg_for_signing(msgWithoutSig) signature = b58decode(signature.encode()) typ = msg.get(TYPE) # TODO: Maybe keeping ACCEPT_INVITE open is a better option than keeping # an if condition here? if typ == ACCEPT_INVITE: verkey = msg.get(VERKEY) else: try: link = self.getLinkForMsg(msg) verkey = self.getVerkeyForLink(link) except (ConnectionNotFound, VerkeyNotFound): # This is for verification of `NOTIFY` events link = self.wallet.getConnectionBy(remote=identifier) # TODO: If verkey is None, it should be fetched from Indy. # Assuming CID for now. verkey = link.remoteVerkey v = DidVerifier(verkey, identifier=identifier) if not v.verify(signature, ser): raise SignatureRejected else: if typ == ACCEPT_INVITE: self.logger.info('Signature accepted.') return True
def verifySignature(self, msg: Dict[str, str]): signature = msg.get(f.SIG.nm) identifier = msg.get(IDENTIFIER) msgWithoutSig = {k: v for k, v in msg.items() if k != f.SIG.nm} # TODO This assumes the current key is the cryptonym. This is a BAD # ASSUMPTION!!! Indy needs to provide the current key. ser = serialize_msg_for_signing(msgWithoutSig) signature = b58decode(signature.encode()) typ = msg.get(TYPE) # TODO: Maybe keeping ACCEPT_INVITE open is a better option than keeping # an if condition here? if typ == ACCEPT_INVITE: verkey = msg.get(VERKEY) else: try: link = self.getLinkForMsg(msg) verkey = self.getVerkeyForLink(link) except (ConnectionNotFound, VerkeyNotFound): # This is for verification of `NOTIFY` events link = self.wallet.getConnectionBy(remote=identifier) # TODO: If verkey is None, it should be fetched from Indy. # Assuming CID for now. verkey = link.remoteVerkey v = DidVerifier(verkey, identifier=identifier) if not v.verify(signature, ser): raise SignatureRejected else: if typ == ACCEPT_INVITE: self.logger.info('Signature accepted.') return True
def remoteVerkey(self): # This property should be used to fetch verkey compared to # targetVerkey, its a more consistent name and takes care of # abbreviated verkey v = DidVerifier(verkey=self.targetVerkey, identifier=self.remoteIdentifier) return v.verkey
def authenticate(self, msg: Dict, identifier: str = None, signature: str = None) -> str: try: if not signature: try: signature = msg[f.SIG.nm] if not signature: raise EmptySignature(msg.get(f.IDENTIFIER.nm), msg.get(f.REQ_ID.nm)) except KeyError: raise MissingSignature(msg.get(f.IDENTIFIER.nm), msg.get(f.REQ_ID.nm)) if not identifier: try: identifier = msg[f.IDENTIFIER.nm] if not identifier: raise EmptyIdentifier(None, msg.get(f.REQ_ID.nm)) except KeyError: raise MissingIdentifier(identifier, msg.get(f.REQ_ID.nm)) try: sig = base58.b58decode(signature) except Exception as ex: raise InvalidSignatureFormat from ex ser = self.serializeForSig(msg, topLevelKeysToIgnore=[f.SIG.nm]) verkey = self.getVerkey(identifier) if verkey is None: raise CouldNotAuthenticate( 'Can not find verkey for DID {}'.format(identifier)) vr = DidVerifier(verkey, identifier=identifier) isVerified = vr.verify(sig, ser) if not isVerified: raise InvalidSignature except SigningException as e: raise e except Exception as ex: raise CouldNotAuthenticate from ex return identifier
def remoteVerkey(self): if not hasattr(self, '_remoteVerkey'): return None if self._remoteVerkey is None: return None # This property should be used to fetch verkey compared to # remoteVerkey, its a more consistent name and takes care of # abbreviated verkey v = DidVerifier(verkey=self._remoteVerkey, identifier=self.remoteIdentifier) return v.verkey
def _updateLinkWithLatestInfo(self, link: Link, reply): link.remoteVerkey = DidVerifier( reply[VERKEY], identifier=link.remoteIdentifier).verkey if DATA in reply and reply[DATA]: data = json.loads(reply[DATA]) ep = data.get(ENDPOINT) if ep: # TODO: Validate its an IP port pair or a malicious entity # can crash the code if 'ha' in ep: ip, port = ep['ha'].split(":") link.remoteEndPoint = (ip, int(port)) if PUBKEY in ep: link.remotePubkey = ep[PUBKEY] else: link.remotePubkey = friendlyVerkeyToPubkey( link.remoteVerkey) if link.remoteVerkey else None link.linkLastSynced = datetime.now() self.notifyMsgListener(" Link {} synced".format(link.name))
def chkVerifyForRetrievedIdentity(signerWallet, verifierWallet, idr): sig = signMsg(signerWallet, idr) verkey = verifierWallet.getIdentity(idr).verkey assert verifyMsg(DidVerifier(verkey, idr), sig)
def test_create_verifier_with_odd_length_verkey(): with pytest.raises(InvalidKey, message="invalid verkey {} accepted".format( ODD_LENGTH_VERKEY)) as excinfo: verifier = DidVerifier(ODD_LENGTH_VERKEY) excinfo.match(r'verkey {}'.format(ODD_LENGTH_VERKEY))
def test_create_verifier(): verifier = DidVerifier(SAMPLE_ABBR_VERKEY, identifier=SAMPLE_IDENTIFIER) assert verifier.verkey == EXPECTED_VERKEY
def test_DidVerifier_init_invalid_args(): for verkey in (None, ''): with pytest.raises(ValueError) as excinfo: DidVerifier(verkey, identifier=SAMPLE_IDENTIFIER) assert "'verkey' should be a non-empty string" == str(excinfo.value)