Beispiel #1
0
    def test_key_management(self):
        for tpm in self.backEndList:
            identityName = Name("/Test/KeyName")
            keyId = Name.Component("1")
            keyName = PibKey.constructKeyName(identityName, keyId)

            # The key should not exist.
            self.assertEquals(False, tpm.hasKey(keyName))
            self.assertTrue(tpm.getKeyHandle(keyName) == None)

            # Create a key, which should exist.
            self.assertTrue(
              tpm.createKey(identityName, RsaKeyParams(keyId)) != None)
            self.assertTrue(tpm.hasKey(keyName))
            self.assertTrue(tpm.getKeyHandle(keyName) != None)

            # Create a key with the same name, which should throw an error.
            try:
                tpm.createKey(identityName, RsaKeyParams(keyId))
                self.fail("Did not throw the expected exception")
            except Tpm.Error:
                pass
            else:
                self.fail("Did not throw the expected exception")

            # Delete the key, then it should not exist.
            tpm.deleteKey(keyName)
            self.assertEquals(False, tpm.hasKey(keyName))
            self.assertTrue(tpm.getKeyHandle(keyName) == None)
    def __init__(self, identity, dataset, keyChain, face):
        self._identity = identity
        self._keyChain = keyChain
        self._face = face

        # storage_ is for the KEK and KDKs.
        self._storage = InMemoryStorageRetaining()

        # The NAC identity is: <identity>/NAC/<dataset>
        # Generate the NAC key.
        nacIdentity = self._keyChain.createIdentityV2(
          Name(identity.getName())
          .append(EncryptorV2.NAME_COMPONENT_NAC).append(dataset),
          RsaKeyParams())
        self._nacKey = nacIdentity.getDefaultKey()
        if self._nacKey.getKeyType() != KeyType.RSA:
            logging.getLogger(__name__).info(
              "Cannot re-use existing KEK/KDK pair, as it is not an RSA key, regenerating")
            self._nacKey = self._keyChain.createKey(nacIdentity, RsaKeyParams())

        nacKeyId = self._nacKey.getName().get(-1)

        kekPrefix = Name(self._nacKey.getIdentityName()).append(
          EncryptorV2.NAME_COMPONENT_KEK)

        kekData = Data(self._nacKey.getDefaultCertificate())
        kekData.setName(Name(kekPrefix).append(nacKeyId))
        kekData.getMetaInfo().setFreshnessPeriod(
          AccessManagerV2.DEFAULT_KEK_FRESHNESS_PERIOD_MS)
        self._keyChain.sign(kekData, SigningInfo(self._identity))
        # kek looks like a cert, but doesn't have ValidityPeriod
        self._storage.insert(kekData)

        def serveFromStorage(prefix, interest, face, interestFilterId, filter):
            data = self._storage.find(interest)
            if data != None:
                logging.getLogger(__name__).info("Serving " +
                  data.getName().toUri() + " from in-memory-storage")
                try:
                    face.putData(data)
                except:
                    logging.exception("AccessManagerV2: Error in Face.putData")
            else:
                logging.getLogger(__name__).info("Didn't find data for " +
                  interest.getName().toUri())
                # TODO: Send NACK?

        def onRegisterFailed(prefix):
            logging.getLogger(__name__).error(
              "AccessManagerV2: Failed to register prefix " + prefix.toUri())

        self._kekRegisteredPrefixId = self._face.registerPrefix(
          kekPrefix, serveFromStorage, onRegisterFailed)

        kdkPrefix = Name(self._nacKey.getIdentityName()).append(
          EncryptorV2.NAME_COMPONENT_KDK).append(nacKeyId)
        self._kdkRegisteredPrefixId_ = self._face.registerPrefix(
          kdkPrefix, serveFromStorage, onRegisterFailed)
Beispiel #3
0
def generateRsaKeys():
    params = RsaKeyParams()
    decryptKey = RsaAlgorithm.generateKey(params)
    decryptionKeyBlob = decryptKey.getKeyBits()
    encryptKey = RsaAlgorithm.deriveEncryptKey(decryptionKeyBlob)
    encryptionKeyBlob = encryptKey.getKeyBits()

    return (encryptionKeyBlob, decryptionKeyBlob)
Beispiel #4
0
    def test_random_key_id(self):
        tpm = self.backEndMemory

        identityName = Name("/Test/KeyName");

        keyNames = set()
        for i in range(100):
            key = tpm.createKey(identityName, RsaKeyParams())
            keyName = key.getKeyName()

            saveSize = len(keyNames)
            keyNames.add(keyName)
            self.assertTrue(len(keyNames) > saveSize)
Beispiel #5
0
    def generateRSAKeyPair(self, identityName, isKsk = False, keySize = 2048):
        """
        Generate a pair of RSA keys for the specified identity.

        :param Name identityName: The name of the identity.
        :param bool isKsk: (optional) true for generating a Key-Signing-Key
          (KSK), false for a Data-Signing-Key (DSK). If omitted, generate a
          Data-Signing-Key.
        :param int keySize: (optional) The size of the key. If omitted, use a
          default secure key size.
        :return: The generated key name.
        :rtype: Name
        """
        keyName = self._generateKeyPair(identityName, isKsk, RsaKeyParams(keySize))
        return keyName
Beispiel #6
0
    def _generateKeyPair(self):
        """
        Generate an RSA key pair according to _keySize.

        :return: A tuple (privateKeyBlob, publicKeyBlob) where "privateKeyBlob"
          is the encoding Blob of the private key and "publicKeyBlob" is the
          encoding Blob of the public key.
        :rtype: (Blob, Blob)
        """
        params = RsaKeyParams(self._keySize)
        privateKey = RsaAlgorithm.generateKey(params)
        privateKeyBlob = privateKey.getKeyBits()

        publicKey = RsaAlgorithm.deriveEncryptKey(privateKeyBlob)
        publicKeyBlob = publicKey.getKeyBits()

        return (privateKeyBlob, publicKeyBlob)
Beispiel #7
0
    def test_rsa_signing(self):
        for tpm in self.backEndList:
            # Create an RSA key.
            identityName = Name("/Test/KeyName")

            key = tpm.createKey(identityName, RsaKeyParams())
            keyName = key.getKeyName()

            content = Blob([0x01, 0x02, 0x03, 0x04])
            signature = key.sign(DigestAlgorithm.SHA256, content.toBytes())

            publicKey = key.derivePublicKey()

            result = VerificationHelpers.verifySignature(
              content, signature, publicKey)
            self.assertEquals(True, result)

            tpm.deleteKey(keyName)
            self.assertEquals(False, tpm.hasKey(keyName))
Beispiel #8
0
    def test_content_asymmetric_encrypt_small(self):
        for input in encryptorRsaTestInputs:
            rawContent = Blob(
                bytearray([
                    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc,
                    0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x63, 0x6f, 0x6e, 0x74,
                    0x65, 0x6e, 0x74, 0x73
                ]), False)

            data = Data()
            rsaParams = RsaKeyParams(1024)

            keyName = Name("test")

            decryptKey = RsaAlgorithm.generateKey(rsaParams)
            encryptKey = RsaAlgorithm.deriveEncryptKey(decryptKey.getKeyBits())

            eKey = encryptKey.getKeyBits()
            dKey = decryptKey.getKeyBits()

            encryptParams = EncryptParams(input.type)

            Encryptor.encryptData(data, rawContent, keyName, eKey,
                                  encryptParams)

            self.assertTrue(
                data.getName().equals(Name("/FOR").append(keyName)),
                input.testName)

            extractContent = EncryptedContent()
            extractContent.wireDecode(data.getContent())
            self.assertTrue(
                keyName.equals(extractContent.getKeyLocator().getKeyName()),
                input.testName)
            self.assertEqual(extractContent.getInitialVector().size(), 0,
                             input.testName)
            self.assertEqual(extractContent.getAlgorithmType(), input.type,
                             input.testName)

            recovered = extractContent.getPayload()
            decrypted = RsaAlgorithm.decrypt(dKey, recovered, encryptParams)
            self.assertTrue(rawContent.equals(decrypted), input.testName)
Beispiel #9
0
    def test_rsa_signing(self):
        for tpm in self.backEndList:
            # Create an RSA key.
            identityName = Name("/Test/KeyName")

            key = tpm.createKey(identityName, RsaKeyParams())
            keyName = key.getKeyName()

            content = Blob([0x01, 0x02, 0x03, 0x04])
            signature = key.sign(DigestAlgorithm.SHA256, content.toBytes())

            publicKey = key.derivePublicKey()

            # TODO: Move verify to PublicKey?
            result = PolicyManager._verifySha256WithRsaSignature(
                signature, SignedBlob(content, 0, content.size()), publicKey)
            self.assertEquals(True, result)

            tpm.deleteKey(keyName)
            self.assertEquals(False, tpm.hasKey(keyName))
Beispiel #10
0
    def test_rsa_decryption(self):
        for tpm in self.backEndList:
            # Create an rsa key.
            identityName = Name("/Test/KeyName")

            key = tpm.createKey(identityName, RsaKeyParams())
            keyName = key.getKeyName()

            content = Blob([0x01, 0x02, 0x03, 0x04])

            publicKey = key.derivePublicKey()

            # TODO: Move encrypt to PublicKey?
            cipherText = RsaAlgorithm.encrypt(
              publicKey, content, EncryptParams(EncryptAlgorithmType.RsaOaep))

            plainText = key.decrypt(cipherText.toBytes())

            self.assertTrue(plainText.equals(content))

            tpm.deleteKey(keyName)
            self.assertEquals(False, tpm.hasKey(keyName))
Beispiel #11
0
    def test_content_asymmetric_encrypt_large(self):
        for input in encryptorRsaTestInputs:
            largeContent = Blob(bytearray([
                0x73, 0x5a, 0xbd, 0x47, 0x0c, 0xfe, 0xf8, 0x7d,
                0x2e, 0x17, 0xaa, 0x11, 0x6f, 0x23, 0xc5, 0x10,
                0x23, 0x36, 0x88, 0xc4, 0x2a, 0x0f, 0x9a, 0x72,
                0x54, 0x31, 0xa8, 0xb3, 0x51, 0x18, 0x9f, 0x0e,
                0x1b, 0x93, 0x62, 0xd9, 0xc4, 0xf5, 0xf4, 0x3d,
                0x61, 0x9a, 0xca, 0x05, 0x65, 0x6b, 0xc6, 0x41,
                0xf9, 0xd5, 0x1c, 0x67, 0xc1, 0xd0, 0xd5, 0x6f,
                0x7b, 0x70, 0xb8, 0x8f, 0xdb, 0x19, 0x68, 0x7c,
                0xe0, 0x2d, 0x04, 0x49, 0xa9, 0xa2, 0x77, 0x4e,
                0xfc, 0x60, 0x0d, 0x7c, 0x1b, 0x93, 0x6c, 0xd2,
                0x61, 0xc4, 0x6b, 0x01, 0xe9, 0x12, 0x28, 0x6d,
                0xf5, 0x78, 0xe9, 0x99, 0x0b, 0x9c, 0x4f, 0x90,
                0x34, 0x3e, 0x06, 0x92, 0x57, 0xe3, 0x7a, 0x8f,
                0x13, 0xc7, 0xf3, 0xfe, 0xf0, 0xe2, 0x59, 0x48,
                0x15, 0xb9, 0xdb, 0x77, 0x07, 0x1d, 0x6d, 0xb5,
                0x65, 0x17, 0xdf, 0x76, 0x6f, 0xb5, 0x43, 0xde,
                0x71, 0xac, 0xf1, 0x22, 0xbf, 0xb2, 0xe5, 0xd9,
                0x22, 0xf1, 0x67, 0x76, 0x71, 0x0c, 0xff, 0x99,
                0x7b, 0x94, 0x9b, 0x24, 0x20, 0x80, 0xe3, 0xcc,
                0x06, 0x4a, 0xed, 0xdf, 0xec, 0x50, 0xd5, 0x87,
                0x3d, 0xa0, 0x7d, 0x9c, 0xe5, 0x13, 0x10, 0x98,
                0x14, 0xc3, 0x90, 0x10, 0xd9, 0x25, 0x9a, 0x59,
                0xe9, 0x37, 0x26, 0xfd, 0x87, 0xd7, 0xf4, 0xf9,
                0x11, 0x91, 0xad, 0x5c, 0x00, 0x95, 0xf5, 0x2b,
                0x37, 0xf7, 0x4e, 0xb4, 0x4b, 0x42, 0x7c, 0xb3,
                0xad, 0xd6, 0x33, 0x5f, 0x0b, 0x84, 0x57, 0x7f,
                0xa7, 0x07, 0x73, 0x37, 0x4b, 0xab, 0x2e, 0xfb,
                0xfe, 0x1e, 0xcb, 0xb6, 0x4a, 0xc1, 0x21, 0x5f,
                0xec, 0x92, 0xb7, 0xac, 0x97, 0x75, 0x20, 0xc9,
                0xd8, 0x9e, 0x93, 0xd5, 0x12, 0x7a, 0x64, 0xb9,
                0x4c, 0xed, 0x49, 0x87, 0x44, 0x5b, 0x4f, 0x90,
                0x34, 0x3e, 0x06, 0x92, 0x57, 0xe3, 0x7a, 0x8f,
                0x13, 0xc7, 0xf3, 0xfe, 0xf0, 0xe2, 0x59, 0x48,
                0x15, 0xb9, 0xdb, 0x77, 0x07, 0x1d, 0x6d, 0xb5,
                0x65, 0x17, 0xdf, 0x76, 0x6f, 0xb5, 0x43, 0xde,
                0x71, 0xac, 0xf1, 0x22, 0xbf, 0xb2, 0xe5, 0xd9
              ]), False)

            data = Data()
            rsaParams = RsaKeyParams(1024)

            keyName = Name("test")

            decryptKey = RsaAlgorithm.generateKey(rsaParams)
            encryptKey = RsaAlgorithm.deriveEncryptKey(decryptKey.getKeyBits())

            eKey = encryptKey.getKeyBits()
            dKey = decryptKey.getKeyBits()

            encryptParams = EncryptParams(input.type)
            Encryptor.encryptData(data, largeContent, keyName, eKey, encryptParams)

            self.assertTrue(data.getName().equals(Name("/FOR").append(keyName)),
                            input.testName)

            largeDataContent = data.getContent()

            # largeDataContent is a sequence of the two EncryptedContent.
            encryptedNonce = EncryptedContent()
            encryptedNonce.wireDecode(largeDataContent)
            self.assertTrue(keyName.equals(encryptedNonce.getKeyLocator().getKeyName()),
                            input.testName)
            self.assertEqual(encryptedNonce.getInitialVector().size(), 0,
                             input.testName)
            self.assertEqual(encryptedNonce.getAlgorithmType(), input.type,
                             input.testName)

            # Use the size of encryptedNonce to find the start of encryptedPayload.
            payloadContent = largeDataContent.buf()[encryptedNonce.wireEncode().size():]
            encryptedPayload = EncryptedContent()
            encryptedPayload.wireDecode(payloadContent)
            nonceKeyName = Name(keyName)
            nonceKeyName.append("nonce")
            self.assertTrue(nonceKeyName.equals(encryptedPayload.getKeyLocator().getKeyName()),
                            input.testName)
            self.assertEqual(encryptedPayload.getInitialVector().size(), 16,
                             input.testName)
            self.assertEqual(encryptedPayload.getAlgorithmType(), EncryptAlgorithmType.AesCbc,
                             input.testName)

            self.assertEqual(
              largeDataContent.size(),
              encryptedNonce.wireEncode().size() + encryptedPayload.wireEncode().size(),
              input.testName)

            blobNonce = encryptedNonce.getPayload()
            nonce = RsaAlgorithm.decrypt(dKey, blobNonce, encryptParams)

            encryptParams.setAlgorithmType(EncryptAlgorithmType.AesCbc)
            encryptParams.setInitialVector(encryptedPayload.getInitialVector())
            bufferPayload = encryptedPayload.getPayload()
            largePayload = AesAlgorithm.decrypt(nonce, bufferPayload, encryptParams)

            self.assertTrue(largeContent.equals(largePayload), input.testName)
Beispiel #12
0
class KeyChain(object):
    """
    Create a new KeyChain to use the optional identityManager and policyManager.

    :param IdentityManager identityManager: (optional) The identity manager as a
      subclass of IdentityManager. If omitted, use the default IdentityManager
      constructor.
    :param PolicyManager policyManager: (optional) The policy manager as a
      subclass of PolicyManager. If omitted, use NoVerifyPolicyManager.
    """
    def __init__(self, identityManager = None, policyManager = None):
        if identityManager == None:
            identityManager = IdentityManager()
        if policyManager == None:
            policyManager = NoVerifyPolicyManager()

        self._identityManager = identityManager
        self._policyManager = policyManager
        self._face = None

    def createIdentityAndCertificate(self, identityName, params = None):
        """
        Create an identity by creating a pair of Key-Signing-Key (KSK) for this
        identity and a self-signed certificate of the KSK. If a key pair or
        certificate for the identity already exists, use it.

        :param Name identityName: The name of the identity.
        :param KeyParams params: (optional) The key parameters if a key needs to
          be generated for the identity. If omitted, use DEFAULT_KEY_PARAMS.
        :return: The name of the default certificate of the identity.
        :rtype: Name
        """
        if params == None:
            params = KeyChain.DEFAULT_KEY_PARAMS
        return self._identityManager.createIdentityAndCertificate(
          identityName, params)

    def createIdentity(self, identityName, params = None):
        """
        Create an identity by creating a pair of Key-Signing-Key (KSK) for this
        identity and a self-signed certificate of the KSK. If a key pair or
        certificate for the identity already exists, use it.

        :deprecated: Use createIdentityAndCertificate which returns the
          certificate name instead of the key name. You can use
          IdentityCertificate.certificateNameToPublicKeyName to convert the
          certificate name to the key name.
        :param Name identityName: The name of the identity.
        :param KeyParams params: (optional) The key parameters if a key needs to
          be generated for the identity. If omitted, use DEFAULT_KEY_PARAMS.
        :return: The key name of the auto-generated KSK of the identity.
        :rtype: Name
        """
        return IdentityCertificate.certificateNameToPublicKeyName(
          self.createIdentityAndCertificate(identityName, params))

    def deleteIdentity(self, identityName):
        """
        Delete the identity from the public and private key storage. If the
        identity to be deleted is current default system default, the method
        will not delete the identity and will return immediately.
        :param Name identityName: The name of the identity to delete.
        """
        self._identityManager.deleteIdentity(identityName)

    def getDefaultIdentity(self):
        """
        Get the default identity.

        :return: The name of default identity.
        :rtype: Name
        :raises SecurityException: if the default identity is not set.
        """
        return self._identityManager.getDefaultIdentity()

    def getDefaultCertificateName(self):
        """
        Get the default certificate name of the default identity.

        :return: The requested certificate name.
        :rtype: Name
        :raises SecurityException: if the default identity is not set or the
          default key name for the identity is not set or the default
          certificate name for the key name is not set.
        """
        return self._identityManager.getDefaultCertificateName()

    def generateRSAKeyPair(self, identityName, isKsk = False, keySize = 2048):
        """
        Generate a pair of RSA keys for the specified identity.

        :param Name identityName: The name of the identity.
        :param bool isKsk: (optional) true for generating a Key-Signing-Key
          (KSK), false for a Data-Signing-Key (DSK). If omitted, generate a
          Data-Signing-Key.
        :param int keySize: (optional) The size of the key. If omitted, use a
          default secure key size.
        :return: The generated key name.
        :rtype: Name
        """
        return self._identityManager.generateRSAKeyPair(
          identityName, isKsk, keySize)

    def generateEcdsaKeyPair(self, identityName, isKsk = False, keySize = 2048):
        """
        Generate a pair of ECDSA keys for the specified identity.

        :param Name identityName: The name of the identity.
        :param bool isKsk: (optional) true for generating a Key-Signing-Key
          (KSK), false for a Data-Signing-Key (DSK). If omitted, generate a
          Data-Signing-Key.
        :param int keySize: (optional) The size of the key. If omitted, use a
          default secure key size.
        :return: The generated key name.
        :rtype: Name
        """
        return self._identityManager.generateEcdsaKeyPair(
          identityName, isKsk, keySize)

    def setDefaultKeyForIdentity(self, keyName, identityNameCheck = None):
        """
        Set a key as the default key of an identity. The identity name is
        inferred from keyName.

        :param Name keyName: The name of the key.
        :param Name identityNameCheck: (optional) The identity name to check
          that the keyName contains the same identity name. If an empty name, it
          is ignored.
        """
        if identityNameCheck == None:
            identityNameCheck = Name()
        return self._identityManager.setDefaultKeyForIdentity(
          keyName, identityNameCheck)

    def generateRSAKeyPairAsDefault(
          self, identityName, isKsk = False, keySize = 2048):
        """
        Generate a pair of RSA keys for the specified identity and set it as
        default key for the identity.

        :param NameidentityName: The name of the identity.
        :param bool isKsk: (optional) true for generating a Key-Signing-Key
          (KSK), false for a Data-Signing-Key (DSK). If omitted, generate a
          Data-Signing-Key.
        :param int keySize: (optional) The size of the key. If omitted, use a
          default secure key size.
        :return: The generated key name.
        :rtype: Name
        """
        return  self._identityManager.generateRSAKeyPairAsDefault(
          identityName, isKsk, keySize)

    def generateEcdsaKeyPairAsDefault(
          self, identityName, isKsk = False, keySize = 2048):
        """
        Generate a pair of ECDSA keys for the specified identity and set it as
        default key for the identity.

        :param NameidentityName: The name of the identity.
        :param bool isKsk: (optional) true for generating a Key-Signing-Key
          (KSK), false for a Data-Signing-Key (DSK). If omitted, generate a
          Data-Signing-Key.
        :param int keySize: (optional) The size of the key. If omitted, use a
          default secure key size.
        :return: The generated key name.
        :rtype: Name
        """
        return  self._identityManager.generateEcdsaKeyPairAsDefault(
          identityName, isKsk, keySize)

    def createSigningRequest(self, keyName):
        """
        Create a public key signing request.

        :param Name keyName: The name of the key.
        :return: The signing request data.
        :rtype: Blob
        """
        return self._identityManager.getPublicKey(keyName).getKeyDer()

    def installIdentityCertificate(self, certificate):
        """
        Install an identity certificate into the public key identity storage.

        :param IdentityCertificate certificate: The certificate to to added.
        """
        self._identityManager.addCertificate(certificate)

    def setDefaultCertificateForKey(self, certificate):
        """
        Set the certificate as the default for its corresponding key.

        :param IdentityCertificate certificate: The certificate.
        """
        self._identityManager.setDefaultCertificateForKey(certificate)

    def getCertificate(self, certificateName):
        """
        Get a certificate with the specified name.

        :param Name certificateName: The name of the requested certificate.
        :return: The requested certificate.
        :rtype: IdentityCertificate
        """
        return self._identityManager.getCertificate(certificateName)

    def getIdentityCertificate(self, certificateName):
        """
        :deprecated: Use getCertificate.
        """
        return self._identityManager.getCertificate(certificateName)

    def revokeKey(self, keyName):
        """
        Revoke a key.

        :param Name keyName: The name of the key that will be revoked.
        """
        # TODO: Implement.
        pass

    def revokeCertificate(self, certificateName):
        """
        Revoke a certificate.

        :param Name certificateName: The name of the certificate that will be
          revoked.
        """
        # TODO: Implement.
        pass

    def getIdentityManager(self):
        """
        Get the identity manager given to or created by the constructor.

        :return: The identity manager.
        :rtype: IdentityManager
        """
        return self._identityManager

    #
    # Policy Management
    #

    def getPolicyManager(self):
        """
        Get the policy manager given to or created by the constructor.

        :return: The policy manager.
        :rtype: PolicyManager
        """
        return self._policyManager

    #
    # Sign/Verify
    #

    def sign(self, target, certificateNameOrWireFormat = None, wireFormat = None):
        """
        Sign the target. If it is a Data or Interest object, set its signature.
        If it is an array, return a signature object. There are two forms of sign:
        sign(target, certificateName, wireFormat = None).
        sign(target, wireFormat = None).

        :param target: If this is a Data object, wire encode for signing,
          update its signature and key locator field and wireEncoding. If this
          is an Interest object, wire encode for signing, append a SignatureInfo
          to the Interest name, sign the name components and append a final name
          component with the signature bits. If it is an array, sign it and
          return a Signature object.
        :type target: Data, Interest or an array which implements the
          buffer protocol
        :param Name certificateName: (optional) The certificate name of the key
          to use for signing. If omitted, use the default identity in the
          identity storage.
        :param wireFormat: (optional) A WireFormat object used to encode the
           input. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The Signature object (only if the target is an array).
        :rtype: An object of a subclass of Signature
        """
        if isinstance(certificateNameOrWireFormat, Name):
            certificateName = certificateNameOrWireFormat
        else:
            certificateName = None

        if isinstance(certificateNameOrWireFormat, WireFormat):
            wireFormat = certificateNameOrWireFormat

        if certificateName == None:
            certificateName = self._prepareDefaultCertificateName()

        if isinstance(target, Interest):
            self._identityManager.signInterestByCertificate(
              target, certificateName, wireFormat)
        elif isinstance(target, Data):
            self._identityManager.signByCertificate(
              target, certificateName, wireFormat)
        else:
            return self._identityManager.signByCertificate(
              target, certificateName)

    def signByIdentity(self, target, identityName = None, wireFormat = None):
        """
        Sign the target. If it is a Data object, set its signature.
        If it is an array, return a signature object.

        :param target: If this is a Data object, wire encode for signing,
          update its signature and key locator field and wireEncoding. If it is
          an array, sign it and return a Signature object.
        :type target: Data or an array which implements the buffer protocol
        :param Name identityName: (optional) The identity name for the key to
          use for signing. If omitted, infer the signing identity from the data
          packet name.
        :param wireFormat: (optional) A WireFormat object used to encode the
           input. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The Signature object (only if the target is an array).
        :rtype: An object of a subclass of Signature
        """
        if identityName == None:
            identityName = Name()

        if isinstance(target, Data):
            if identityName.size() == 0:
                inferredIdentity = self._policyManager.inferSigningIdentity(
                  target.getName())
                if inferredIdentity.size() == 0:
                    signingCertificateName = self._identityManager.getDefaultCertificateName()
                else:
                    signingCertificateName = \
                      self._identityManager.getDefaultCertificateNameForIdentity(inferredIdentity)
            else:
                signingCertificateName = \
                  self._identityManager.getDefaultCertificateNameForIdentity(identityName)

            if signingCertificateName.size() == 0:
                raise SecurityException("No qualified certificate name found!")

            if not self._policyManager.checkSigningPolicy(
                  target.getName(), signingCertificateName):
                raise SecurityException(
                  "Signing Cert name does not comply with signing policy")

            self._identityManager.signByCertificate(
              target, signingCertificateName, wireFormat)
        else:
            signingCertificateName = \
              self._identityManager.getDefaultCertificateNameForIdentity(identityName)

            if signingCertificateName.size() == 0:
                raise SecurityException("No qualified certificate name found!")

            return self._identityManager.signByCertificate(
              target, signingCertificateName)

    def signWithSha256(self, target, wireFormat = None):
        """
        Sign the target using DigestSha256.

        :param target: If this is a Data object, wire encode for signing,
          digest it and set its SignatureInfo to a DigestSha256, updating its
          signature and wireEncoding. If this is an Interest object, wire encode
          for signing, append a SignatureInfo for DigestSha256 to the Interest
          name, digest the name components and append a final name component
          with the signature bits.
        :type target: Data or Interest
        :param wireFormat: (optional) A WireFormat object used to encode the
           input. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        """
        if isinstance(target, Interest):
            self._identityManager.signInterestWithSha256(target, wireFormat)
        else:
            self._identityManager.signWithSha256(target, wireFormat)

    def verifyData(self, data, onVerified, onValidationFailed, stepCount = 0):
        """
        Check the signature on the Data object and call either onVerify or
        onValidationFailed. We use callback functions because verify may fetch
        information to check the signature.

        :param Data data: The Data object with the signature to check.
        :param onVerified: If the signature is verified, this calls
          onVerified(data).
          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 or can't find
          the public key, this calls onValidationFailed(data, reason) with the
          Data object and reason string. This also supports the deprecated
          callback onValidationFailed(data) but you should use the callback with
          the reason string.
          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
        :param int stepCount: (optional) The number of verification steps that
          have been done. If omitted, use 0.
        """
        # If onValidationFailed is not a function nor a method assumes it is a
        # calleable object
        if (not inspect.isfunction(onValidationFailed) and
            not inspect.ismethod(onValidationFailed)):
            onValidationFailed = onValidationFailed.__call__
        # Use getcallargs to test if onValidationFailed accepts 2 args.
        try:
            inspect.getcallargs(onValidationFailed, None, None)
        except TypeError:
            # Assume onValidationFailed is old-style with 1 argument. Wrap it
            # with a function that takes and ignores the reason string.
            oldValidationFailed = onValidationFailed
            onValidationFailed = lambda d, reason: oldValidationFailed(d)

        if self._policyManager.requireVerify(data):
            nextStep = self._policyManager.checkVerificationPolicy(
              data, stepCount, onVerified, onValidationFailed)
            if nextStep != None:
                self._face.expressInterest(
                  nextStep.interest, self._makeOnCertificateData(nextStep),
                  self._makeOnCertificateInterestTimeout(
                    nextStep.retry, onValidationFailed, data, nextStep))
        elif self._policyManager.skipVerifyAndTrust(data):
            try:
                onVerified(data)
            except:
                logging.exception("Error in onVerified")
        else:
            try:
                onValidationFailed(
                  data,
                  "The packet has no verify rule but skipVerifyAndTrust is false")
            except:
                logging.exception("Error in onValidationFailed")

    def verifyInterest(
      self, interest, onVerified, onValidationFailed, stepCount = 0,
      wireFormat = None):
        """
        Check the signature on the signed interest and call either onVerify or
        onValidationFailed. We use callback functions because verify may fetch
        information to check the signature.

        :param Interest interest: The interest with the signature to check.
        :param onVerified: If the signature is verified, this calls
          onVerified(interest).
          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 or can't find
          the  public key, this calls onValidationFailed(interest, reason) with
          the Interest object and reason string. This also supports the
          deprecated callback onValidationFailed(interest) but you should use
          the callback with the reason string.
          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
        :param int stepCount: (optional) The number of verification steps that
          have been done. If omitted, use 0.
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        # If onValidationFailed is not a function nor a method assumes it is a
        # calleable object
        if (not inspect.isfunction(onValidationFailed) and
            not inspect.ismethod(onValidationFailed)):
            onValidationFailed = onValidationFailed.__call__
        # Use getcallargs to test if onValidationFailed accepts 2 args.
        try:
            inspect.getcallargs(onValidationFailed, None, None)
        except TypeError:
            # Assume onValidationFailed is old-style with 1 argument. Wrap it
            # with a function that takes and ignores the reason string.
            oldValidationFailed = onValidationFailed
            onValidationFailed = lambda i, reason: oldValidationFailed(i)

        if self._policyManager.requireVerify(interest):
            nextStep = self._policyManager.checkVerificationPolicy(
              interest, stepCount, onVerified, onValidationFailed, wireFormat)
            if nextStep != None:
                self._face.expressInterest(
                  nextStep.interest, self._makeOnCertificateData(nextStep),
                  self._makeOnCertificateInterestTimeout(
                    nextStep.retry, onValidationFailed, interest, nextStep))
        elif self._policyManager.skipVerifyAndTrust(interest):
            try:
                onVerified(interest)
            except:
                logging.exception("Error in onVerified")
        else:
            try:
                onValidationFailed(interest,
                  "The packet has no verify rule but skipVerifyAndTrust is false")
            except:
                logging.exception("Error in onValidationFailed")

    def setFace(self, face):
        """
        Set the Face which will be used to fetch required certificates.

        :param Face face: The Face object.
        """
        self._face = face

    @staticmethod
    def signWithHmacWithSha256(target, key, wireFormat = None):
        """
        Wire encode the target, compute an HmacWithSha256 and update the
        signature value.
        Note: This method is an experimental feature. The API may change.

        :param target: If this is a Data object, update its signature and wire
          encoding.
        :type target: Data
        :param Blob key: The key for the HmacWithSha256.
        :param wireFormat: (optional) The WireFormat for calling encodeData,
          etc., or WireFormat.getDefaultWireFormat() if omitted.
        :type wireFormat: A subclass of WireFormat
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if isinstance(target, Data):
            data = target
            # Encode once to get the signed portion.
            encoding = data.wireEncode(wireFormat)

            signer = hmac.HMAC(key.toBytes(), hashes.SHA256(),
              backend = default_backend())
            signer.update(encoding.toSignedBytes())
            data.getSignature().setSignature(
              Blob(bytearray(signer.finalize()), False))
        else:
            raise SecurityException("signWithHmacWithSha256: Unrecognized target type")

    @staticmethod
    def verifyDataWithHmacWithSha256(data, key, wireFormat = None):
        """
        Compute a new HmacWithSha256 for the target and verify it against the
        signature value.
        Note: This method is an experimental feature. The API may change.

        :param target: The Data object to verify.
        :type target: Data
        :param Blob key: The key for the HmacWithSha256.
        :param wireFormat: (optional) The WireFormat for calling encodeData,
          etc., or WireFormat.getDefaultWireFormat() if omitted.
        :type wireFormat: A subclass of WireFormat
        :return: True if the signature verifies, otherwise False.
        :rtype: bool
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        # wireEncode returns the cached encoding if available.
        encoding = data.wireEncode(wireFormat)

        signer = hmac.HMAC(key.toBytes(), hashes.SHA256(),
          backend = default_backend())
        signer.update(encoding.toSignedBytes())
        newSignatureBits = Blob(bytearray(signer.finalize()), False)

        # Use the flexible Blob.equals operator.
        return newSignatureBits == data.getSignature().getSignature()

    DEFAULT_KEY_PARAMS = RsaKeyParams()

    #
    # Private methods
    #

    def _makeOnCertificateData(self, nextStep):
        """
        Make and return an onData callback to use in expressInterest.
        """
        def onData(interest, data):
            # Try to verify the certificate (data) according to the parameters
            #   in nextStep.
            self.verifyData(data, nextStep.onVerified, nextStep.onValidationFailed,
                            nextStep.stepCount)
        return onData

    def _makeOnCertificateInterestTimeout(self, retry, onValidationFailed,
          originalDataOrInterest, nextStep):
        """
        Make and return an onTimeout callback to use in expressInterest.
        """
        def onTimeout(interest):
            if retry > 0:
                # Issue the same expressInterest as in verifyData except
                #   decrement retry.
                self._face.expressInterest(
                  interest, self._makeOnCertificateData(nextStep),
                     self._makeOnCertificateInterestTimeout(
                       retry - 1, onValidationFailed, originalDataOrInterest,
                       nextStep))
            else:
                try:
                    onValidationFailed(
                      originalDataOrInterest,
                      "The retry count is zero after timeout for fetching " +
                        interest.getName().toUri())
                except:
                    logging.exception("Error in onValidationFailed")
        return onTimeout

    def _prepareDefaultCertificateName(self):
        """
        Get the default certificate from the identity storage and return its name.
        If there is no default identity or default certificate, then create one.

        :return: The default certificate name.
        :rtype: Name
        """
        signingCertificate = self._identityManager.getDefaultCertificate()
        if signingCertificate == None:
          self._setDefaultCertificate()
          signingCertificate = self._identityManager.getDefaultCertificate()

        return signingCertificate.getName()

    def _setDefaultCertificate(self):
        """
        Create the default certificate if it is not initialized. If there is
        no default identity yet, creating a new tmp-identity.
        """
        if self._identityManager.getDefaultCertificate() == None:
            try:
                defaultIdentity = self._identityManager.getDefaultIdentity()
            except:
                # Create a default identity name.
                randomComponent = bytearray(4)
                for i in range(len(randomComponent)):
                    randomComponent[i] = _systemRandom.randint(0, 0xff)
                defaultIdentity = Name().append("tmp-identity").append(
                  Blob(randomComponent, False))

            self.createIdentityAndCertificate(defaultIdentity)
            self._identityManager.setDefaultIdentity(defaultIdentity)
Beispiel #13
0
class KeyChain(object):
    """
    Create a new KeyChain to use the optional identityManager and policyManager.

    :param IdentityManager identityManager: (optional) The identity manager as a
      subclass of IdentityManager. If omitted, use the default IdentityManager
      constructor.
    :param PolicyManager policyManager: (optional) The policy manager as a
      subclass of PolicyManager. If omitted, use NoVerifyPolicyManager.
    """
    def __init__(self, identityManager=None, policyManager=None):
        if identityManager == None:
            identityManager = IdentityManager()
        if policyManager == None:
            policyManager = NoVerifyPolicyManager()

        self._identityManager = identityManager
        self._policyManager = policyManager
        self._face = None
        self._maxSteps = 100

    def createIdentityAndCertificate(self, identityName, params=None):
        """
        Create an identity by creating a pair of Key-Signing-Key (KSK) for this
        identity and a self-signed certificate of the KSK. If a key pair or
        certificate for the identity already exists, use it.

        :param Name identityName: The name of the identity.
        :param KeyParams params: (optional) The key parameters if a key needs to
          be generated for the identity. If omitted, use DEFAULT_KEY_PARAMS.
        :return: The name of the default certificate of the identity.
        :rtype: Name
        """
        if params == None:
            params = KeyChain.DEFAULT_KEY_PARAMS
        return self._identityManager.createIdentityAndCertificate(
            identityName, params)

    def createIdentity(self, identityName, params=None):
        """
        Create an identity by creating a pair of Key-Signing-Key (KSK) for this
        identity and a self-signed certificate of the KSK. If a key pair or
        certificate for the identity already exists, use it.

        :deprecated: Use createIdentityAndCertificate which returns the
          certificate name instead of the key name. You can use
          IdentityCertificate.certificateNameToPublicKeyName to convert the
          certificate name to the key name.
        :param Name identityName: The name of the identity.
        :param KeyParams params: (optional) The key parameters if a key needs to
          be generated for the identity. If omitted, use DEFAULT_KEY_PARAMS.
        :return: The key name of the auto-generated KSK of the identity.
        :rtype: Name
        """
        return IdentityCertificate.certificateNameToPublicKeyName(
            self.createIdentityAndCertificate(identityName, params))

    def deleteIdentity(self, identityName):
        """
        Delete the identity from the public and private key storage. If the
        identity to be deleted is current default system default, the method
        will not delete the identity and will return immediately.
        :param Name identityName: The name of the identity to delete.
        """
        self._identityManager.deleteIdentity(identityName)

    def getDefaultIdentity(self):
        """
        Get the default identity.

        :return: The name of default identity.
        :rtype: Name
        :raises SecurityException: if the default identity is not set.
        """
        return self._identityManager.getDefaultIdentity()

    def getDefaultCertificateName(self):
        """
        Get the default certificate name of the default identity.

        :return: The requested certificate name.
        :rtype: Name
        :raises SecurityException: if the default identity is not set or the
          default key name for the identity is not set or the default
          certificate name for the key name is not set.
        """
        return self._identityManager.getDefaultCertificateName()

    def generateRSAKeyPair(self, identityName, isKsk=False, keySize=2048):
        """
        Generate a pair of RSA keys for the specified identity.

        :param Name identityName: The name of the identity.
        :param bool isKsk: (optional) true for generating a Key-Signing-Key
          (KSK), false for a Data-Signing-Key (DSK). If omitted, generate a
          Data-Signing-Key.
        :param int keySize: (optional) The size of the key. If omitted, use a
          default secure key size.
        :return: The generated key name.
        :rtype: Name
        """
        return self._identityManager.generateRSAKeyPair(
            identityName, isKsk, keySize)

    def setDefaultKeyForIdentity(self, keyName, identityName=None):
        """
        Set a key as the default key of an identity.

        :param Name keyName: The name of the key.
        :param Name identityName: (optional) the name of the identity. If not
          specified, the identity name is inferred from the keyName.
        """
        if identityName == None:
            identityName = Name()
        return self._identityManager.setDefaultKeyForIdentity(
            keyName, identityName)

    def generateRSAKeyPairAsDefault(self,
                                    identityName,
                                    isKsk=False,
                                    keySize=2048):
        """
        Generate a pair of RSA keys for the specified identity and set it as
        default key for the identity.

        :param NameidentityName: The name of the identity.
        :param bool isKsk: (optional) true for generating a Key-Signing-Key
          (KSK), false for a Data-Signing-Key (DSK). If omitted, generate a
          Data-Signing-Key.
        :param int keySize: (optional) The size of the key. If omitted, use a
          default secure key size.
        :return: The generated key name.
        :rtype: Name
        """
        return self._identityManager.generateRSAKeyPairAsDefault(
            identityName, isKsk, keySize)

    def createSigningRequest(self, keyName):
        """
        Create a public key signing request.

        :param Name keyName: The name of the key.
        :return: The signing request data.
        :rtype: Blob
        """
        return self._identityManager.getPublicKey(keyName).getKeyDer()

    def installIdentityCertificate(self, certificate):
        """
        Install an identity certificate into the public key identity storage.

        :param IdentityCertificate certificate: The certificate to to added.
        """
        self._identityManager.addCertificate(certificate)

    def setDefaultCertificateForKey(self, certificate):
        """
        Set the certificate as the default for its corresponding key.

        :param IdentityCertificate certificate: The certificate.
        """
        self._identityManager.setDefaultCertificateForKey(certificate)

    def getCertificate(self, certificateName):
        """
        Get a certificate with the specified name.

        :param Name certificateName: The name of the requested certificate.
        :return: The requested certificate which is valid.
        :rtype: IdentityCertificate
        """
        return self._identityManager.getCertificate(certificateName)

    def getAnyCertificate(self, certificateName):
        """
        Get a certificate even if the certificate is not valid anymore.

        :param Name certificateName: The name of the requested certificate.
        :return: The requested certificate.
        :rtype: IdentityCertificate
        """
        return self._identityManager.getAnyCertificate(certificateName)

    def getIdentityCertificate(self, certificateName):
        """
        Get an identity certificate with the specified name.

        :param Name certificateName: The name of the requested certificate.
        :return: The requested certificate which is valid.
        :rtype: IdentityCertificate
        """
        return self._identityManager.getCertificate(certificateName)

    def getAnyIdentityCertificate(self, certificateName):
        """
        Get an identity certificate even if the certificate is not valid anymore.

        :param Name certificateName: The name of the requested certificate.
        :return: The requested certificate.
        :rtype: IdentityCertificate
        """
        return self._identityManager.getAnyCertificate(certificateName)

    def revokeKey(self, keyName):
        """
        Revoke a key.

        :param Name keyName: The name of the key that will be revoked.
        """
        # TODO: Implement.
        pass

    def revokeCertificate(self, certificateName):
        """
        Revoke a certificate.

        :param Name certificateName: The name of the certificate that will be
          revoked.
        """
        # TODO: Implement.
        pass

    def getIdentityManager(self):
        """
        Get the identity manager given to or created by the constructor.

        :return: The identity manager.
        :rtype: IdentityManager
        """
        return self._identityManager

    #
    # Policy Management
    #

    def getPolicyManager(self):
        """
        Get the policy manager given to or created by the constructor.

        :return: The policy manager.
        :rtype: PolicyManager
        """
        return self._policyManager

    #
    # Sign/Verify
    #

    def sign(self, target, certificateName, wireFormat=None):
        """
        Sign the target. If it is a Data or Interest object, set its signature.
        If it is an array, return a signature object.

        :param target: If this is a Data object, wire encode for signing,
          update its signature and key locator field and wireEncoding. If this
          is an Interest object, wire encode for signing, append a SignatureInfo
          to the Interest name, sign the name components and append a final name
          component with the signature bits. If it is an array, sign it and
          return a Signature object.
        :type target: Data, Interest or an array which implements the
          buffer protocol
        :param Name certificateName: The certificate name of the key to use for
          signing.
        :param wireFormat: (optional) A WireFormat object used to encode the
           input. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The Signature object (only if the target is an array).
        :rtype: An object of a subclass of Signature
        """
        if isinstance(target, Interest):
            self._identityManager.signInterestByCertificate(
                target, certificateName, wireFormat)
        elif isinstance(target, Data):
            self._identityManager.signByCertificate(target, certificateName,
                                                    wireFormat)
        else:
            return self._identityManager.signByCertificate(
                target, certificateName)

    def signByIdentity(self, target, identityName=None, wireFormat=None):
        """
        Sign the target. If it is a Data object, set its signature.
        If it is an array, return a signature object.

        :param target: If this is a Data object, wire encode for signing,
          update its signature and key locator field and wireEncoding. If it is
          an array, sign it and return a Signature object.
        :type target: Data or an array which implements the buffer protocol
        :param Name identityName: (optional) The identity name for the key to
          use for signing. If omitted, infer the signing identity from the data
          packet name.
        :param wireFormat: (optional) A WireFormat object used to encode the
           input. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The Signature object (only if the target is an array).
        :rtype: An object of a subclass of Signature
        """
        if identityName == None:
            identityName = Name()

        if isinstance(target, Data):
            if identityName.size() == 0:
                inferredIdentity = self._policyManager.inferSigningIdentity(
                    target.getName())
                if inferredIdentity.size() == 0:
                    signingCertificateName = self._identityManager.getDefaultCertificateName(
                    )
                else:
                    signingCertificateName = \
                      self._identityManager.getDefaultCertificateNameForIdentity(inferredIdentity)
            else:
                signingCertificateName = \
                  self._identityManager.getDefaultCertificateNameForIdentity(identityName)

            if signingCertificateName.size() == 0:
                raise SecurityException("No qualified certificate name found!")

            if not self._policyManager.checkSigningPolicy(
                    target.getName(), signingCertificateName):
                raise SecurityException(
                    "Signing Cert name does not comply with signing policy")

            self._identityManager.signByCertificate(target,
                                                    signingCertificateName,
                                                    wireFormat)
        else:
            signingCertificateName = \
              self._identityManager.getDefaultCertificateNameForIdentity(identityName)

            if signingCertificateName.size() == 0:
                raise SecurityException("No qualified certificate name found!")

            return self._identityManager.signByCertificate(
                target, signingCertificateName)

    def signWithSha256(self, target, wireFormat=None):
        """
        Sign the target using DigestSha256.

        :param target: If this is a Data object, wire encode for signing,
          digest it and set its SignatureInfo to a DigestSha256, updating its
          signature and wireEncoding. If this is an Interest object, wire encode
          for signing, append a SignatureInfo for DigestSha256 to the Interest
          name, digest the name components and append a final name component
          with the signature bits.
        :type target: Data or Interest
        :param wireFormat: (optional) A WireFormat object used to encode the
           input. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        """
        if isinstance(target, Interest):
            self._identityManager.signInterestWithSha256(target, wireFormat)
        else:
            self._identityManager.signWithSha256(target, wireFormat)

    def verifyData(self, data, onVerified, onVerifyFailed, stepCount=0):
        """
        Check the signature on the Data object and call either onVerify or
        onVerifyFailed. We use callback functions because verify may fetch
        information to check the signature.

        :param Data data: The Data object with the signature to check.
        :param onVerified: If the signature is verified, this calls
          onVerified(data).
        :type onVerified: function object
        :param onVerifyFailed: If the signature check fails or can't find the
          public key, this calls onVerifyFailed(data).
        :type onVerifyFailed: function object
        :param int stepCount: (optional) The number of verification steps that
          have been done. If omitted, use 0.
        """
        if self._policyManager.requireVerify(data):
            nextStep = self._policyManager.checkVerificationPolicy(
                data, stepCount, onVerified, onVerifyFailed)
            if nextStep != None:
                self._face.expressInterest(
                    nextStep.interest, self._makeOnCertificateData(nextStep),
                    self._makeOnCertificateInterestTimeout(
                        nextStep.retry, onVerifyFailed, data, nextStep))
        elif self._policyManager.skipVerifyAndTrust(data):
            onVerified(data)
        else:
            onVerifyFailed(data)

    def verifyInterest(self,
                       interest,
                       onVerified,
                       onVerifyFailed,
                       stepCount=0,
                       wireFormat=None):
        """
        Check the signature on the signed interest and call either onVerify or
        onVerifyFailed. We use callback functions because verify may fetch
        information to check the signature.

        :param Interest interest: The interest with the signature to check.
        :param onVerified: If the signature is verified, this calls
          onVerified(interest).
        :type onVerified: function object
        :param onVerifyFailed: If the signature check fails or can't find the
          public key, this calls onVerifyFailed(interest).
        :type onVerifyFailed: function object
        :param int stepCount: (optional) The number of verification steps that
          have been done. If omitted, use 0.
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if self._policyManager.requireVerify(interest):
            nextStep = self._policyManager.checkVerificationPolicy(
                interest, stepCount, onVerified, onVerifyFailed, wireFormat)
            if nextStep != None:
                self._face.expressInterest(
                    nextStep.interest, self._makeOnCertificateData(nextStep),
                    self._makeOnCertificateInterestTimeout(
                        nextStep.retry, onVerifyFailed, interest, nextStep))
        elif self._policyManager.skipVerifyAndTrust(interest):
            onVerified(interest)
        else:
            onVerifyFailed(interest)

    def setFace(self, face):
        """
        Set the Face which will be used to fetch required certificates.

        :param Face face: The Face object.
        """
        self._face = face

    DEFAULT_KEY_PARAMS = RsaKeyParams()

    #
    # Private methods
    #

    def _makeOnCertificateData(self, nextStep):
        """
        Make and return an onData callback to use in expressInterest.
        """
        def onData(interest, data):
            # Try to verify the certificate (data) according to the parameters
            #   in nextStep.
            self.verifyData(data, nextStep.onVerified, nextStep.onVerifyFailed,
                            nextStep.stepCount)

        return onData

    def _makeOnCertificateInterestTimeout(self, retry, onVerifyFailed, data,
                                          nextStep):
        """
        Make and return an onTimeout callback to use in expressInterest.
        """
        def onTimeout(interest):
            if retry > 0:
                # Issue the same expressInterest as in verifyData except
                #   decrement retry.
                self._face.expressInterest(
                    interest, self._makeOnCertificateData(nextStep),
                    self._makeOnCertificateInterestTimeout(
                        retry, onVerifyFailed, data, nextStep))
            else:
                onVerifyFailed(data)

        return onTimeout