def checkVerificationPolicy(self, dataOrInterest, stepCount, onVerified, onVerifyFailed, wireFormat = None): """ If there is a rule matching the data or interest, and the matching certificate is missing, download it. If there is no matching rule, verification fails. Otherwise, verify the signature using the public key in the IdentityStorage. :param dataOrInterest: The Data object or interest with the signature to check. :type dataOrInterest: Data or Interest :param int stepCount: The number of verification steps that have been done, used to track the verification progress. :param onVerified: If the signature is verified, this calls onVerified(dataOrInterest). :type onVerified: function object :param onVerifyFailed: If the signature check fails, this calls onVerifyFailed(dataOrInterest). :type onVerifyFailed: function object :return: None for no further step for looking up a certificate chain. :rtype: ValidationRequest """ if stepCount > self._maxDepth: onVerifyFailed(dataOrInterest) return None signature = self._extractSignature(dataOrInterest, wireFormat) # no signature -> fail if signature is None: onVerifyFailed(dataOrInterest) return None if not KeyLocator.canGetFromSignature(signature): # We only support signature types with key locators. onVerifyFailed(dataOrInterest) return None keyLocator = None try: keyLocator = KeyLocator.getFromSignature(signature) except: # No key locator -> fail. onVerifyFailed(dataOrInterest) return None signatureName = keyLocator.getKeyName() # no key name in KeyLocator -> fail if signatureName.size() == 0: onVerifyFailed(dataOrInterest) return None objectName = dataOrInterest.getName() matchType = "data" #for command interests, we need to ignore the last 4 components when matching the name if isinstance(dataOrInterest, Interest): objectName = objectName.getPrefix(-4) matchType = "interest" # first see if we can find a rule to match this packet try: matchedRule = self._findMatchingRule(objectName, matchType) except: matchedRule = None # no matching rule -> fail if matchedRule is None: onVerifyFailed(dataOrInterest) return None signatureMatches = self._checkSignatureMatch(signatureName, objectName, matchedRule) if not signatureMatches: onVerifyFailed(dataOrInterest) return None # before we look up keys, refresh any certificate directories self._refreshManager.refreshAnchors() # now finally check that the data or interest was signed correctly # if we don't actually have the certificate yet, create a # ValidationRequest for it foundCert = self._refreshManager.getCertificate(signatureName) if foundCert is None: foundCert = self._certificateCache.getCertificate(signatureName) if foundCert is None: certificateInterest = Interest(signatureName) def onCertificateDownloadComplete(certificate): certificate = IdentityCertificate(certificate) self._certificateCache.insertCertificate(certificate) self.checkVerificationPolicy(dataOrInterest, stepCount+1, onVerified, onVerifyFailed) nextStep = ValidationRequest(certificateInterest, onCertificateDownloadComplete, onVerifyFailed, 2, stepCount+1) return nextStep # for interests, we must check that the timestamp is fresh enough # I do this after (possibly) downloading the certificate to avoid # filling the cache with bad keys if isinstance(dataOrInterest, Interest): keyName = foundCert.getPublicKeyName() timestamp = dataOrInterest.getName().get(-4).toNumber() if not self._interestTimestampIsFresh(keyName, timestamp): onVerifyFailed(dataOrInterest) return None # certificate is known, verify the signature if self._verify(signature, dataOrInterest.wireEncode()): onVerified(dataOrInterest) if isinstance(dataOrInterest, Interest): self._updateTimestampForKey(keyName, timestamp) else: onVerifyFailed(dataOrInterest)
def checkVerificationPolicy(self, dataOrInterest, stepCount, onVerified, onVerifyFailed, wireFormat=None): """ If there is a rule matching the data or interest, and the matching certificate is missing, download it. If there is no matching rule, verification fails. Otherwise, verify the signature using the public key in the IdentityStorage. :param dataOrInterest: The Data object or interest with the signature to check. :type dataOrInterest: Data or Interest :param int stepCount: The number of verification steps that have been done, used to track the verification progress. :param onVerified: If the signature is verified, this calls onVerified(dataOrInterest). :type onVerified: function object :param onVerifyFailed: If the signature check fails, this calls onVerifyFailed(dataOrInterest). :type onVerifyFailed: function object :return: None for no further step for looking up a certificate chain. :rtype: ValidationRequest """ if stepCount > self._maxDepth: onVerifyFailed(dataOrInterest) return None signature = self._extractSignature(dataOrInterest, wireFormat) # no signature -> fail if signature is None: onVerifyFailed(dataOrInterest) return None if not KeyLocator.canGetFromSignature(signature): # We only support signature types with key locators. onVerifyFailed(dataOrInterest) return None keyLocator = None try: keyLocator = KeyLocator.getFromSignature(signature) except: # No key locator -> fail. onVerifyFailed(dataOrInterest) return None signatureName = keyLocator.getKeyName() # no key name in KeyLocator -> fail if signatureName.size() == 0: onVerifyFailed(dataOrInterest) return None objectName = dataOrInterest.getName() matchType = "data" #for command interests, we need to ignore the last 4 components when matching the name if isinstance(dataOrInterest, Interest): objectName = objectName.getPrefix(-4) matchType = "interest" # first see if we can find a rule to match this packet try: matchedRule = self._findMatchingRule(objectName, matchType) except: matchedRule = None # no matching rule -> fail if matchedRule is None: onVerifyFailed(dataOrInterest) return None signatureMatches = self._checkSignatureMatch(signatureName, objectName, matchedRule) if not signatureMatches: onVerifyFailed(dataOrInterest) return None # before we look up keys, refresh any certificate directories self._refreshManager.refreshAnchors() # now finally check that the data or interest was signed correctly # if we don't actually have the certificate yet, create a # ValidationRequest for it foundCert = self._refreshManager.getCertificate(signatureName) if foundCert is None: foundCert = self._certificateCache.getCertificate(signatureName) if foundCert is None: certificateInterest = Interest(signatureName) def onCertificateDownloadComplete(certificate): certificate = IdentityCertificate(certificate) self._certificateCache.insertCertificate(certificate) self.checkVerificationPolicy(dataOrInterest, stepCount + 1, onVerified, onVerifyFailed) nextStep = ValidationRequest(certificateInterest, onCertificateDownloadComplete, onVerifyFailed, 2, stepCount + 1) return nextStep # for interests, we must check that the timestamp is fresh enough # I do this after (possibly) downloading the certificate to avoid # filling the cache with bad keys if isinstance(dataOrInterest, Interest): keyName = foundCert.getPublicKeyName() timestamp = dataOrInterest.getName().get(-4).toNumber() if not self._interestTimestampIsFresh(keyName, timestamp): onVerifyFailed(dataOrInterest) return None # certificate is known, verify the signature if self._verify(signature, dataOrInterest.wireEncode()): onVerified(dataOrInterest) if isinstance(dataOrInterest, Interest): self._updateTimestampForKey(keyName, timestamp) else: onVerifyFailed(dataOrInterest)