def _verify(self, signatureInfo, signedBlob, failureReason): """ Check the type of signatureInfo to get the KeyLocator. Look in the IdentityStorage for the public key with the name in the KeyLocator and use it to verify the signedBlob. If the public key can't be found, return false. (This is a generalized method which can verify both a Data packet and an interest.) :param Signature signatureInfo: An object of a subclass of Signature, e.g. Sha256WithRsaSignature. :param SignedBlob signedBlob: the SignedBlob with the signed portion to verify. :param Array<str> failureReason: If verification fails, set failureReason[0] to the failure reason string. :return: True if the signature verifies, False if not. :rtype: boolean """ publicKeyDer = None if KeyLocator.canGetFromSignature(signatureInfo): publicKeyDer = self._getPublicKeyDer( KeyLocator.getFromSignature(signatureInfo), failureReason) if publicKeyDer.isNull(): return False if self.verifySignature( signatureInfo, signedBlob, publicKeyDer): return True else: failureReason[0] = ( "The signature did not verify with the given public key") return False
def _verify(self, signatureInfo, signedBlob, failureReason): """ Check the type of signatureInfo to get the KeyLocator. Look in the IdentityStorage for the public key with the name in the KeyLocator and use it to verify the signedBlob. If the public key can't be found, return false. (This is a generalized method which can verify both a Data packet and an interest.) :param Signature signatureInfo: An object of a subclass of Signature, e.g. Sha256WithRsaSignature. :param SignedBlob signedBlob: the SignedBlob with the signed portion to verify. :param Array<str> failureReason: If verification fails, set failureReason[0] to the failure reason string. :return: True if the signature verifies, False if not. :rtype: boolean """ publicKeyDer = None if KeyLocator.canGetFromSignature(signatureInfo): publicKeyDer = self._getPublicKeyDer( KeyLocator.getFromSignature(signatureInfo), failureReason) if publicKeyDer.isNull(): return False if self.verifySignature(signatureInfo, signedBlob, publicKeyDer): return True else: failureReason[0] = ( "The signature did not verify with the given public key") return False
def __str__(self): """ Get a string representation of this certificate. :return: The string representation. :rtype: str """ result = "" result += "Certificate name:\n" result += " " + self.getName().toUri() + "\n" result += "Validity:\n" result += " NotBefore: " + Schedule.toIsoString( self.getValidityPeriod().getNotBefore()) + "\n" result += " NotAfter: " + Schedule.toIsoString( self.getValidityPeriod().getNotAfter()) + "\n" # TODO: Print the extension. result += "Public key bits:\n" try: result += Common.base64Encode(self.getPublicKey().toBytes(), True) except: # No public key. pass result += "Signature Information:\n" result += " Signature Type: " if type(self.getSignature()) is Sha256WithEcdsaSignature: result += "SignatureSha256WithEcdsa\n" elif type(self.getSignature()) is Sha256WithRsaSignature: result += "SignatureSha256WithRsa\n" else: result += "<unknown>\n" if KeyLocator.canGetFromSignature(self.getSignature()): result += " Key Locator: " keyLocator = KeyLocator.getFromSignature(self.getSignature()) if keyLocator.getType() == KeyLocatorType.KEYNAME: if keyLocator.getKeyName().equals(self.getKeyName()): result += "Self-Signed " result += "Name=" + keyLocator.getKeyName().toUri() + "\n" else: result += "<no KeyLocator key name>\n" return result
def __str__(self): """ Get a string representation of this certificate. :return: The string representation. :rtype: str """ result = "" result += "Certificate name:\n" result += " " + self.getName().toUri() + "\n" result += "Validity:\n" result += " NotBefore: " + Schedule.toIsoString( self.getValidityPeriod().getNotBefore()) + "\n" result += " NotAfter: " + Schedule.toIsoString( self.getValidityPeriod().getNotAfter()) + "\n" # TODO: Print the extension. result += "Public key bits:\n" try: result += Common.base64Encode(self.getPublicKey().toBytes(), True) except: # No public key. pass result += "Signature Information:\n" result += " Signature Type: " if isinstance(self.getSignature(), Sha256WithEcdsaSignature): result += "SignatureSha256WithEcdsa\n" elif isinstance(self.getSignature(), Sha256WithRsaSignature): result += "SignatureSha256WithRsa\n" else: result += "<unknown>\n" if KeyLocator.canGetFromSignature(self.getSignature()): result += " Key Locator: " keyLocator = KeyLocator.getFromSignature(self.getSignature()) if keyLocator.getType() == KeyLocatorType.KEYNAME: if keyLocator.getKeyName().equals(self.getKeyName()): result += "Self-Signed " result += "Name=" + keyLocator.getKeyName().toUri() + "\n" else: result += "<no KeyLocator key name>\n" return result
def _getKeyLocatorNameFromSignature(signatureInfo, state): """ A helper method for getKeyLocatorName. :param Signature signatureInfo: :param ValidationState state: :rtype: Name """ if not KeyLocator.canGetFromSignature(signatureInfo): state.fail(ValidationError (ValidationError.INVALID_KEY_LOCATOR, "KeyLocator is missing")) return Name() keyLocator = KeyLocator.getFromSignature(signatureInfo) if keyLocator.getType() != KeyLocatorType.KEYNAME: state.fail(ValidationError (ValidationError.INVALID_KEY_LOCATOR, "KeyLocator type is not Name")) return Name() return keyLocator.getKeyName()
def _getKeyLocatorNameFromSignature(signatureInfo, state): """ A helper method for getKeyLocatorName. :param Signature signatureInfo: :param ValidationState state: :rtype: Name """ if not KeyLocator.canGetFromSignature(signatureInfo): state.fail( ValidationError(ValidationError.INVALID_KEY_LOCATOR, "KeyLocator is missing")) return Name() keyLocator = KeyLocator.getFromSignature(signatureInfo) if keyLocator.getType() != KeyLocatorType.KEYNAME: state.fail( ValidationError(ValidationError.INVALID_KEY_LOCATOR, "KeyLocator type is not Name")) return Name() return keyLocator.getKeyName()
def _verify(self, signatureInfo, signedBlob): """ Check the type of signatureInfo to get the KeyLocator. Look in the IdentityStorage for the public key with the name in the KeyLocator and use it to verify the signedBlob. If the public key can't be found, return false. (This is a generalized method which can verify both a Data packet and an interest.) :param Signature signatureInfo: An object of a subclass of Signature, e.g. Sha256WithRsaSignature. :param SignedBlob signedBlob: the SignedBlob with the signed portion to verify. :return: True if the signature verifies, False if not. :rtype: boolean """ publicKeyDer = None if KeyLocator.canGetFromSignature(signatureInfo): publicKeyDer = self._getPublicKeyDer(KeyLocator.getFromSignature(signatureInfo)) if publicKeyDer.isNull(): return False return self.verifySignature(signatureInfo, signedBlob, publicKeyDer)
def _verify(self, signatureInfo, signedBlob): """ Check the type of signatureInfo to get the KeyLocator. Look in the IdentityStorage for the public key with the name in the KeyLocator and use it to verify the signedBlob. If the public key can't be found, return false. (This is a generalized method which can verify both a Data packet and an interest.) :param Signature signatureInfo: An object of a subclass of Signature, e.g. Sha256WithRsaSignature. :param SignedBlob signedBlob: the SignedBlob with the signed portion to verify. :return: True if the signature verifies, False if not. :rtype: boolean """ publicKeyDer = None if KeyLocator.canGetFromSignature(signatureInfo): publicKeyDer = self._getPublicKeyDer( KeyLocator.getFromSignature(signatureInfo)) if publicKeyDer.isNull(): return False return self.verifySignature(signatureInfo, signedBlob, publicKeyDer)
def checkVerificationPolicy(self, dataOrInterest, stepCount, onVerified, onValidationFailed, 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). NOTE: The library will log any exceptions raised by this callback, but for better error handling the callback should catch and properly handle any exceptions. :type onVerified: function object :param onValidationFailed: If the signature check fails, this calls onValidationFailed(dataOrInterest, reason). NOTE: The library will log any exceptions raised by this callback, but for better error handling the callback should catch and properly handle any exceptions. :type onValidationFailed: function object :return: None for no further step for looking up a certificate chain. :rtype: ValidationRequest """ if stepCount > self._maxDepth: try: onValidationFailed( dataOrInterest, "The verification stepCount " + stepCount + " exceeded the maxDepth " + self._maxDepth) except: logging.exception("Error in onValidationFailed") return None signature = self._extractSignature(dataOrInterest, wireFormat) # no signature -> fail if signature is None: try: onValidationFailed( dataOrInterest, "Cannot extract the signature from " + dataOrInterest.getName().toUri()) except: logging.exception("Error in onValidationFailed") return None if not KeyLocator.canGetFromSignature(signature): # We only support signature types with key locators. try: onValidationFailed( dataOrInterest, "The signature type does not support a KeyLocator") except: logging.exception("Error in onValidationFailed") return None keyLocator = None try: keyLocator = KeyLocator.getFromSignature(signature) except Exception as ex: # No key locator -> fail. try: onValidationFailed( dataOrInterest, "Error in KeyLocator.getFromSignature: " + str(ex)) except: logging.exception("Error in onValidationFailed") return None signatureName = keyLocator.getKeyName() # no key name in KeyLocator -> fail if signatureName.size() == 0: try: onValidationFailed( dataOrInterest, "The signature KeyLocator doesn't have a key name") except: logging.exception("Error in onValidationFailed") 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: try: onValidationFailed( dataOrInterest, "No matching rule found for " + objectName.toUri()) except: logging.exception("Error in onValidationFailed") return None failureReason = ["unknown"] signatureMatches = self._checkSignatureMatch(signatureName, objectName, matchedRule, failureReason) if not signatureMatches: try: onValidationFailed(dataOrInterest, failureReason[0]) except: logging.exception("Error in onValidationFailed") 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(data): try: certificate = IdentityCertificate(data) except: try: onValidationFailed( dataOrInterest, "Cannot decode certificate " + data.getName().toUri()) except: logging.exception("Error in onValidationFailed") return None self._certificateCache.insertCertificate(certificate) self.checkVerificationPolicy(dataOrInterest, stepCount + 1, onVerified, onValidationFailed) nextStep = ValidationRequest(certificateInterest, onCertificateDownloadComplete, onValidationFailed, 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, failureReason): try: onValidationFailed(dataOrInterest, failureReason[0]) except: logging.exception("Error in onValidationFailed") return None # certificate is known, verify the signature if self._verify(signature, dataOrInterest.wireEncode(), failureReason): try: onVerified(dataOrInterest) except: logging.exception("Error in onVerified") if isinstance(dataOrInterest, Interest): self._updateTimestampForKey(keyName, timestamp) else: try: onValidationFailed(dataOrInterest, failureReason[0]) except: logging.exception("Error in onValidationFailed")
def matchesData(self, data, wireFormat=None): """ Check if the given Data packet can satisfy this Interest. This method considers the Name, MinSuffixComponents, MaxSuffixComponents, PublisherPublicKeyLocator, and Exclude. It does not consider the ChildSelector or MustBeFresh. This uses the given wireFormat to get the Data packet encoding for the full Name. :param Data data: The Data packet to check. :param wireFormat: (optional) A WireFormat object used to encode the Data packet to get its full Name. If omitted, use WireFormat.getDefaultWireFormat(). :type wireFormat: A subclass of WireFormat :return: True if the given Data packet can satisfy this Interest. :rtype: bool """ # Imitate ndn-cxx Interest::matchesData. interestNameLength = self.getName().size() dataName = data.getName() fullNameLength = dataName.size() + 1 # Check MinSuffixComponents. hasMinSuffixComponents = (self.getMinSuffixComponents() != None) minSuffixComponents = (self.getMinSuffixComponents() if hasMinSuffixComponents else 0) if not (interestNameLength + minSuffixComponents <= fullNameLength): return False # Check MaxSuffixComponents. hasMaxSuffixComponents = (self.getMaxSuffixComponents() != None) if (hasMaxSuffixComponents and not (interestNameLength + self.getMaxSuffixComponents() >= fullNameLength)): return False # Check the prefix. if interestNameLength == fullNameLength: if self.getName().get(-1).isImplicitSha256Digest(): if not self.getName().equals(data.getFullName(wireFormat)): return False else: # The Interest Name is the same length as the Data full Name, # but the last component isn't a digest so there's no # possibility of matching. return False else: # The Interest Name should be a strict prefix of the Data full Name. if not self.getName().isPrefixOf(dataName): return False # Check the Exclude. # The Exclude won't be violated if the Interest Name is the same as the # Data full Name. if self.getExclude().size( ) > 0 and fullNameLength > interestNameLength: if interestNameLength == fullNameLength - 1: # The component to exclude is the digest. if self.getExclude().matches( data.getFullName(wireFormat).get(interestNameLength)): return False else: # The component to exclude is not the digest. if self.getExclude().matches(dataName.get(interestNameLength)): return False # Check the KeyLocator. publisherPublicKeyLocator = self.getKeyLocator() if publisherPublicKeyLocator.getType() != None: signature = data.getSignature() if not KeyLocator.canGetFromSignature(signature): # No KeyLocator in the Data packet. return False if not publisherPublicKeyLocator.equals( (KeyLocator.getFromSignature(signature))): return False return True
def _getCertificateInterest(self, stepCount, matchType, objectName, signature, failureReason): """ This is a helper for checkVerificationPolicy to verify the rule and return a certificate interest to fetch the next certificate in the hierarchy if needed. :param int stepCount: The number of verification steps that have been done, used to track the verification progress. :param str matchType: Either "data" or "interest". :param Name objectName: The name of the data or interest packet. :param Signature signature: The Signature object for the data or interest packet. :param Array<str> failureReason: If can't determine the interest, set failureReason[0] to the failure reason. :return: None if can't determine the interest, otherwise the interest for the ValidationRequest to fetch the next certificate. However, if the interest has an empty name, the validation succeeded and no need to fetch a certificate. :rtype: Interest """ if stepCount > self._maxDepth: failureReason[0] = ("The verification stepCount " + stepCount + " exceeded the maxDepth " + self._maxDepth) return None # 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: failureReason[ 0] = "No matching rule found for " + objectName.toUri() return None if not KeyLocator.canGetFromSignature(signature): # We only support signature types with key locators. failureReason[ 0] = "The signature type does not support a KeyLocator" return None keyLocator = KeyLocator.getFromSignature(signature) signatureName = keyLocator.getKeyName() # No key name in KeyLocator -> fail. if signatureName.size() == 0: failureReason[ 0] = "The signature KeyLocator doesn't have a key name" return None signatureMatches = self._checkSignatureMatch(signatureName, objectName, matchedRule, failureReason) if not signatureMatches: return None # Before we look up keys, refresh any certificate directories. self._refreshManager.refreshAnchors() # If we don't actually have the certificate yet, return a # certificateInterest for it. if self._isSecurityV1: foundCert = self._refreshManager.getCertificate(signatureName) if foundCert is None: foundCert = self._certificateCache.getCertificate( signatureName) if foundCert is None: return Interest(signatureName) else: foundCert = self._refreshManager.getCertificateV2(signatureName) if foundCert is None: foundCert = self._certificateCacheV2.find(signatureName) if foundCert is None: return Interest(signatureName) return Interest()
def _getCertificateInterest(self, stepCount, matchType, objectName, signature, failureReason): """ This is a helper for checkVerificationPolicy to verify the rule and return a certificate interest to fetch the next certificate in the hierarchy if needed. :param int stepCount: The number of verification steps that have been done, used to track the verification progress. :param str matchType: Either "data" or "interest". :param Name objectName: The name of the data or interest packet. :param Signature signature: The Signature object for the data or interest packet. :param Array<str> failureReason: If can't determine the interest, set failureReason[0] to the failure reason. :return: None if can't determine the interest, otherwise the interest for the ValidationRequest to fetch the next certificate. However, if the interest has an empty name, the validation succeeded and no need to fetch a certificate. :rtype: Interest """ if stepCount > self._maxDepth: failureReason[0] = ("The verification stepCount " + stepCount + " exceeded the maxDepth " + self._maxDepth) return None # 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: failureReason[0] = "No matching rule found for " + objectName.toUri() return None if not KeyLocator.canGetFromSignature(signature): # We only support signature types with key locators. failureReason[0] = "The signature type does not support a KeyLocator" return None keyLocator = KeyLocator.getFromSignature(signature) signatureName = keyLocator.getKeyName() # No key name in KeyLocator -> fail. if signatureName.size() == 0: failureReason[0] = "The signature KeyLocator doesn't have a key name" return None signatureMatches = self._checkSignatureMatch( signatureName, objectName, matchedRule, failureReason) if not signatureMatches: return None # Before we look up keys, refresh any certificate directories. self._refreshManager.refreshAnchors() # If we don't actually have the certificate yet, return a # certificateInterest for it. if self._isSecurityV1: foundCert = self._refreshManager.getCertificate(signatureName) if foundCert is None: foundCert = self._certificateCache.getCertificate(signatureName) if foundCert is None: return Interest(signatureName) else: foundCert = self._refreshManager.getCertificateV2(signatureName) if foundCert is None: foundCert = self._certificateCacheV2.find(signatureName) if foundCert is None: return Interest(signatureName) return Interest()
def matchesData(self, data, wireFormat = None): """ Check if the given Data packet can satisfy this Interest. This method considers the Name, MinSuffixComponents, MaxSuffixComponents, PublisherPublicKeyLocator, and Exclude. It does not consider the ChildSelector or MustBeFresh. This uses the given wireFormat to get the Data packet encoding for the full Name. :param Data data: The Data packet to check. :param wireFormat: (optional) A WireFormat object used to encode the Data packet to get its full Name. If omitted, use WireFormat.getDefaultWireFormat(). :type wireFormat: A subclass of WireFormat :return: True if the given Data packet can satisfy this Interest. :rtype: bool """ # Imitate ndn-cxx Interest::matchesData. interestNameLength = self.getName().size() dataName = data.getName() fullNameLength = dataName.size() + 1 # Check MinSuffixComponents. hasMinSuffixComponents = (self.getMinSuffixComponents() != None) minSuffixComponents = (self.getMinSuffixComponents() if hasMinSuffixComponents else 0) if not (interestNameLength + minSuffixComponents <= fullNameLength): return False # Check MaxSuffixComponents. hasMaxSuffixComponents = (self.getMaxSuffixComponents() != None) if (hasMaxSuffixComponents and not (interestNameLength + self.getMaxSuffixComponents() >= fullNameLength)): return False # Check the prefix. if interestNameLength == fullNameLength: if self.getName().get(-1).isImplicitSha256Digest(): if not self.getName().equals(data.getFullName(wireFormat)): return False else: # The Interest Name is the same length as the Data full Name, # but the last component isn't a digest so there's no # possibility of matching. return False else: # The Interest Name should be a strict prefix of the Data full Name. if not self.getName().isPrefixOf(dataName): return False # Check the Exclude. # The Exclude won't be violated if the Interest Name is the same as the # Data full Name. if self.getExclude().size() > 0 and fullNameLength > interestNameLength: if interestNameLength == fullNameLength - 1: # The component to exclude is the digest. if self.getExclude().matches( data.getFullName(wireFormat).get(interestNameLength)): return False else: # The component to exclude is not the digest. if self.getExclude().matches(dataName.get(interestNameLength)): return False # Check the KeyLocator. publisherPublicKeyLocator = self.getKeyLocator() if publisherPublicKeyLocator.getType() != None: signature = data.getSignature() if not KeyLocator.canGetFromSignature(signature): # No KeyLocator in the Data packet. return False if not publisherPublicKeyLocator.equals( (KeyLocator.getFromSignature(signature))): return False return True
def checkVerificationPolicy(self, dataOrInterest, stepCount, onVerified, onValidationFailed, 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). NOTE: The library will log any exceptions raised by this callback, but for better error handling the callback should catch and properly handle any exceptions. :type onVerified: function object :param onValidationFailed: If the signature check fails, this calls onValidationFailed(dataOrInterest, reason). NOTE: The library will log any exceptions raised by this callback, but for better error handling the callback should catch and properly handle any exceptions. :type onValidationFailed: function object :return: None for no further step for looking up a certificate chain. :rtype: ValidationRequest """ if stepCount > self._maxDepth: try: onValidationFailed( dataOrInterest, "The verification stepCount " + stepCount + " exceeded the maxDepth " + self._maxDepth) except: logging.exception("Error in onValidationFailed") return None signature = self._extractSignature(dataOrInterest, wireFormat) # no signature -> fail if signature is None: try: onValidationFailed( dataOrInterest, "Cannot extract the signature from " + dataOrInterest.getName().toUri()) except: logging.exception("Error in onValidationFailed") return None if not KeyLocator.canGetFromSignature(signature): # We only support signature types with key locators. try: onValidationFailed( dataOrInterest, "The signature type does not support a KeyLocator") except: logging.exception("Error in onValidationFailed") return None keyLocator = None try: keyLocator = KeyLocator.getFromSignature(signature) except Exception as ex: # No key locator -> fail. try: onValidationFailed( dataOrInterest, "Error in KeyLocator.getFromSignature: " + str(ex)) except: logging.exception("Error in onValidationFailed") return None signatureName = keyLocator.getKeyName() # no key name in KeyLocator -> fail if signatureName.size() == 0: try: onValidationFailed( dataOrInterest, "The signature KeyLocator doesn't have a key name") except: logging.exception("Error in onValidationFailed") 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: try: onValidationFailed( dataOrInterest, "No matching rule found for " + objectName.toUri()) except: logging.exception("Error in onValidationFailed") return None failureReason = ["unknown"] signatureMatches = self._checkSignatureMatch( signatureName, objectName, matchedRule, failureReason) if not signatureMatches: try: onValidationFailed(dataOrInterest, failureReason[0]) except: logging.exception("Error in onValidationFailed") 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(data): try: certificate = IdentityCertificate(data) except: try: onValidationFailed( dataOrInterest, "Cannot decode certificate " + data.getName().toUri()) except: logging.exception("Error in onValidationFailed") return None self._certificateCache.insertCertificate(certificate) self.checkVerificationPolicy(dataOrInterest, stepCount+1, onVerified, onValidationFailed) nextStep = ValidationRequest(certificateInterest, onCertificateDownloadComplete, onValidationFailed, 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, failureReason): try: onValidationFailed(dataOrInterest, failureReason[0]) except: logging.exception("Error in onValidationFailed") return None # certificate is known, verify the signature if self._verify(signature, dataOrInterest.wireEncode(), failureReason): try: onVerified(dataOrInterest) except: logging.exception("Error in onVerified") if isinstance(dataOrInterest, Interest): self._updateTimestampForKey(keyName, timestamp) else: try: onValidationFailed(dataOrInterest, failureReason[0]) except: logging.exception("Error in onValidationFailed")