コード例 #1
0
 def create_identity(name):
     key_chain = KeyChain()
     try:
         cur_id = key_chain.getPib().getIdentity(Name(name))
         key_chain.createKey(cur_id)
     except Pib.Error:
         key_chain.createIdentityV2(Name(name))
コード例 #2
0
class IdentityManagementFixture(object):
    def __init__(self):
        self._keyChain = KeyChain("pib-memory:", "tpm-memory:")
        self._identityNames = set()
        self._certificateFiles = set()

    def saveCertificateToFile(self, data, filePath):
        """
        :param Data data: The certificate to save.
        :param str filePath: The file path, which should be writable.
        :return: True if successful.
        :rtype: bool
        """
        self._certificateFiles.add(filePath)

        try:
            encoding = data.wireEncode()
            encodedCertificate = Common.base64Encode(encoding.toBytes(), True)

            with open(filePath, 'w') as keyFile:
                keyFile.write(encodedCertificate)

            return True
        except Exception:
            return False

    def addIdentity(self, identityName, params = None):
        """
        Add an identity for the identityName.

        :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
          KeyChain.getDefaultKeyParams().
        :return: The created PibIdentity instance.
        :rtype: PibIdentity
        """
        if params == None:
            params = KeyChain.getDefaultKeyParams()

        identity = self._keyChain.createIdentityV2(identityName, params)
        self._identityNames.add(identityName)
        return identity

    def saveCertificate(identity, filePath):
        """
        Save the identity's certificate to a file.

        :param PibIdentity identity: The PibIdentity.
        :param str filePath: The file path, which should be writable.
        :return: True if successful.
        :rtype: str
        """
        try:
            certificate = identity.getDefaultKey().getDefaultCertificate()
            return self.saveCertificateToFile(certificate, filePath)
        except Pib.Error:
            return False

    def addSubCertificate(self, subIdentityName, issuer, params = None):
        """
        Issue a certificate for subIdentityName signed by issuer. If the
        identity does not exist, it is created. A new key is generated as the
        default key for the identity. A default certificate for the key is
        signed by the issuer using its default certificate.
        """
        if params == None:
            params = KeyChain.getDefaultKeyParams()

        subIdentity = self.addIdentity(subIdentityName, params)

        request = subIdentity.getDefaultKey().getDefaultCertificate()

        request.setName(request.getKeyName().append("parent").appendVersion(1))

        certificateParams = SigningInfo(issuer)
        # Validity period of 20 years.
        now = Common.getNowMilliseconds()
        certificateParams.setValidityPeriod(
          ValidityPeriod(now, now + 20 * 365 * 24 * 3600 * 1000.0))

        # Skip the AdditionalDescription.

        self._keyChain.sign(request, certificateParams)
        self._keyChain.setDefaultCertificate(subIdentity.getDefaultKey(), request)

        return subIdentity

    def addCertificate(self, key, issuerId):
        """
        Add a self-signed certificate made from the key and issuer ID.

        :param PibKey key: The key for the certificate.
        :param str issuerId: The issuer ID name component for the certificate
          name.
        :return: The new certificate.
        :rtype: CertificateV2
        """
        certificateName = Name(key.getName())
        certificateName.append(issuerId).appendVersion(3)
        certificate = CertificateV2()
        certificate.setName(certificateName)

        # Set the MetaInfo.
        certificate.getMetaInfo().setType(ContentType.KEY)
        # One hour.
        certificate.getMetaInfo().setFreshnessPeriod(3600 * 1000.0)

        # Set the content.
        certificate.setContent(key.getPublicKey())

        params = SigningInfo(key)
        # Validity period of 10 days.
        now = Common.getNowMilliseconds()
        params.setValidityPeriod(
          ValidityPeriod(now, now + 10 * 24 * 3600 * 1000.0))

        self._keyChain.sign(certificate, params)
        return certificate
コード例 #3
0
class Experiment:

    _maxSegmentPayloadLength = 8192

    def __init__(self, absPath, maxAttributes):
        self.keyChain = KeyChain("pib-memory:", "tpm-memory:")
        self.keyChain.createIdentityV2("/test/identity")
        self.validator = Validator(
            ValidationPolicyFromPib(self.keyChain.getPib()))
        # , filename, groupSize, nAttributes, absPath, keepData = False):

        # sys.stderr.write ("Using NDN-ABS authority, signer, and verifier database from %s\n" % absPath)
        self.db = ndnabs.PickleDb(absPath)

        self.signer = ndnabs.Signer(self.db)
        self.verifier = ndnabs.Verifier(self.db)

        try:
            info = self.signer.get_public_params_info()
            if info.getName().getPrefix(
                    -2).toUri() != "/icn2019/test/authority":
                raise RuntimeError(
                    'NDN-ABS authority exists, but not setup for experiment. Use `ndnabs setup -f /icn2019/test/authority` to force-setup the authority'
                )
        except:
            raise RuntimeError(
                "Public parameters are not properly installed for the signer/verifier"
            )

        maxAttributes = [
            b'attribute%d' % i for i in range(1, maxAttributes + 1)
        ]

        for attr in maxAttributes:
            if not attr in self.signer.get_attributes():
                raise RuntimeError(
                    "%s attribute missing. Generate attributes for the experiment using `ndnabs gen-secret %s | ndnabs install-secret`"
                    % (str(attr, 'utf-8'), ' '.join(
                        [str(i, 'utf-8') for i in maxAttributes])))

    #     self.attributes = [b'attribute%d' % i for i in range(1, nAttributes + 1)]
    #     self._setupAbs(absPath)
    #     self._readDataAndCreateManifests(filename, groupSize, keepData)

    def setupAbs(self, nAttributes):
        self.attributes = [
            b'attribute%d' % i for i in range(1, nAttributes + 1)
        ]

    def _createManifest(self, name, manifestBuffer, nManifests):
        manifest = Data(name)
        manifest.setContent(manifestBuffer[0:nManifests * SHA256_DIGEST_SIZE])
        return manifest

    def readDataAndCreateManifests(self, filename, groupSize, keepData):
        if groupSize < 1:
            raise RuntimeError("Group size cannot be less than 1")

        self.allChunks = [
        ]  # for holding the generated data packets, including unsigned manifests
        self.allManifests = [
        ]  # for storing first unsigned manifest packets, which are then signed in-place
        self.rawDataCount = 0
        self.ndnChunkCount = 0

        seqNo = 0  # sequence number of data packets
        chunkNo = 0  # number of the chunk in the group

        with open(filename, 'rb') as f:

            # prepare space to store all manifests of the group (last manifest will not use all the space)
            def allocateBufferForDigests():
                return bytearray(groupSize * SHA256_DIGEST_SIZE)

            digests = allocateBufferForDigests()

            while f.readable():
                chunkPayload = f.read(self._maxSegmentPayloadLength)
                if len(chunkPayload) == 0:
                    break
                self.rawDataCount = self.rawDataCount + len(chunkPayload)

                chunk = Data(
                    Name("/icn2019/test/data").appendSequenceNumber(seqNo))
                seqNo = seqNo + 1
                chunk.setContent(chunkPayload)

                digestSignature = DigestSha256Signature()
                digestSignature.setSignature(
                    Blob(bytearray(SHA256_DIGEST_SIZE))
                )  # not real a valid signature, but ok for the experiment
                chunk.setSignature(digestSignature)

                if keepData:
                    self.allChunks.append(chunk)

                # only data chunks; manifest sizes counted separatedly, as they are signed
                self.ndnChunkCount = self.ndnChunkCount + chunk.wireEncode(
                ).size()

                # For storing data packet to a file
                # with open(writepath + "-1.txt", "wb") as dataf
                #     dataf.write(dpacket_bytes)

                implicitDigest = chunk.getFullName()[-1].getValue()

                offset = chunkNo * SHA256_DIGEST_SIZE
                digests[offset:offset +
                        SHA256_DIGEST_SIZE] = implicitDigest.toBytes()[:]

                chunkNo = chunkNo + 1

                if chunkNo == groupSize:
                    manifest = self._createManifest(
                        Name("/icn2019/test/data").appendSequenceNumber(seqNo),
                        digests, groupSize)  # full group
                    seqNo = seqNo + 1
                    self.allChunks.append(manifest)
                    self.allManifests.append(manifest)
                    chunkNo = 0
                    digests = allocateBufferForDigests()

            if chunkNo != 0:
                manifest = self._createManifest(
                    Name("/icn2019/test/data").appendSequenceNumber(seqNo),
                    digests, groupSize)  # partial group
                self.allChunks.append(manifest)
                self.allManifests.append(manifest)

            self.nDataChunks = seqNo - len(
                self.allManifests
            )  # number of data packets, excluding the manifests

    def signManifestsABS(self):
        self.manifestCount = 0
        self.signatureCounts = []
        for manifest in self.allManifests:
            self.signer.sign(manifest, self.attributes)
            self.manifestCount = self.manifestCount + manifest.wireEncode(
            ).size()
            self.signatureCounts.append(
                manifest.getSignature().getSignature().size())

    def verifyManifestsABS(self):
        for manifest in self.allManifests:
            if not self.signer.verify(manifest.wireEncode()):
                sys.stderr.write("Failed to verify %s\n" % manifest.getName())

    def signManifestsRSA(self):
        self.manifestCount = 0
        self.signatureCounts = []
        for manifest in self.allManifests:
            self.keyChain.sign(manifest)
            self.manifestCount = self.manifestCount + manifest.wireEncode(
            ).size()
            self.signatureCounts.append(
                manifest.getSignature().getSignature().size())

    def verifyManifestsRSA(self):
        def onSuccess(*k, **kw):
            pass

        def onFailure(data, *k, **kw):
            sys.stderr.write("Failed to verify %s\n" % manifest.getName())

        for manifest in self.allManifests:
            self.validator.validate(manifest, onSuccess, onFailure)
コード例 #4
0
class Server:
    def __init__(self, emit_func):
        self.emit = emit_func
        self.running = True
        self.event_list = []

        # 1. If you use default constructor, when NFD is not started,
        # TcpTransport will be used instead of UnixTransport.
        # 2. Both TcpTransport and UnixTransport are not connected
        # before the first Interest is sent.
        # file_path = Face._getUnixSocketFilePathForLocalhost()
        # transport = UnixTransport()
        # connection_info = UnixTransport.ConnectionInfo(file_path)
        # self.face = Face(transport, connection_info)

        self.keychain = KeyChain()
        self.face = None

    def start_reconnection(self):
        """
        Start reconnection process.
        NOT thread safe.
        """
        self.face.shutdown()
        self.face = None

    def get_or_create_certificate(self):
        id_name = Name('/ndncc')
        cur_id = self.keychain.createIdentityV2(id_name)
        return cur_id.getDefaultKey().getDefaultCertificate().name

    def connection_test(self):
        interest = Interest("/localhost/nfd/faces/events")
        interest.mustBeFresh = True
        interest.canBePrefix = True
        interest.interestLifetimeMilliseconds = 1000
        try:
            def empty(*_args, **_kwargs):
                pass

            self.face.expressInterest(interest, empty, empty, empty)
            return True
        except (ConnectionRefusedError, BrokenPipeError, OSError):
            return False

    async def run(self):
        while self.running:
            logging.info("Restarting face...")
            self.face = Face()
            self.face.setCommandSigningInfo(self.keychain, self.get_or_create_certificate())
            if self.connection_test():
                logging.info("Face creation succeeded")
                face_event = asyncio.get_event_loop().create_task(self.face_event())
                while self.running and self.face is not None:
                    try:
                        self.face.processEvents()
                    except AttributeError:
                        logging.info("Attribute error.")
                        self.start_reconnection()
                    await asyncio.sleep(0.01)
                await face_event
            else:
                logging.info("Face creation failed")
            await asyncio.sleep(3)

    @staticmethod
    def face_event_to_dict(msg):
        ret = {}
        if msg.face_event_kind == 1:
            ret['face_event_kind'] = "CREATED"
        elif msg.face_event_kind == 2:
            ret['face_event_kind'] = "DESTROYED"
        elif msg.face_event_kind == 3:
            ret['face_event_kind'] = "UP"
        elif msg.face_event_kind == 4:
            ret['face_event_kind'] = "DOWN"
        else:
            ret['face_event_kind'] = "unknown"

        ret['face_id'] = str(msg.face_id)
        ret['local_uri'] = msg.local_uri.decode("utf-8")
        ret['remote_uri'] = msg.uri.decode("utf-8")

        if msg.face_scope == 1:
            ret['face_scope'] = "local"
        else:
            ret['face_scope'] = "non-local"

        if msg.face_persistency == 0:
            ret['face_persistency'] = "persistent"
        elif msg.face_event_kind == 1:
            ret['face_persistency'] = "on-demand"
        elif msg.face_persistency == 2:
            ret['face_persistency'] = "permanent"
        else:
            ret['face_persistency'] = "unknown"

        if msg.link_type == 0:
            ret['link_type'] = "point-to-point"
        elif msg.link_type == 1:
            ret['link_type'] = "multi-access"
        elif msg.link_type == 2:
            ret['link_type'] = "ad-hoc"
        else:
            ret['link_type'] = "unknown"

        ret['flags'] = str(msg.flags)
        return ret

    @staticmethod
    def response_to_dict(msg):
        ret = {'st_code': msg.st_code, 'st_text': msg.st_text.decode('utf-8')}
        return ret

    async def face_event(self):
        last_seq = -1
        retry_time = 3000
        retry_count_limit = 60000 // retry_time
        retry_count = 0
        while self.running and self.face:
            name = Name("/localhost/nfd/faces/events")
            face_interest = Interest()
            if last_seq >= 0:
                name.appendSequenceNumber(last_seq + 1)
                face_interest.canBePrefix = False
            else:
                face_interest.mustBeFresh = True
                face_interest.canBePrefix = True
            logging.info("Face event notification stream %s", name.toUri())
            face_interest.name = name
            # face_interest.interestLifetimeMilliseconds = 60000
            face_interest.interestLifetimeMilliseconds = retry_time

            ret = await fetch_data_packet(self.face, face_interest)
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

            if isinstance(ret, Data):
                retry_count = 0
                last_seq = ret.name[-1].toSequenceNumber()
                face_event = FaceEventNotificationMessage()
                try:
                    ProtobufTlv.decode(face_event, ret.content)

                    dic = self.face_event_to_dict(face_event.face_event_notification)
                    dic['seq'] = str(last_seq)
                    dic['time'] = timestamp
                    self.emit('face event', dic)
                    self.event_list.append(dic)
                except RuntimeError as exc:
                    logging.fatal('Decode failed %s', exc)
                    last_seq = -1
            elif ret is None:
                if retry_count >= retry_count_limit:
                    logging.info("No response: face event")
                    last_seq = -1
                    retry_count = 0
                else:
                    retry_count += 1
            else:
                logging.info("NFD is not running: start reconnection")
                self.start_reconnection()
                return

            await asyncio.sleep(0.1)

    async def issue_command_interest(self, interest):
        ret = await fetch_data_packet(self.face, interest)
        if isinstance(ret, Data):
            response = ControlResponseMessage()
            try:
                ProtobufTlv.decode(response, ret.content)

                dic = self.response_to_dict(response.control_response)
                logging.info("Issue command Interest with %s", dic)
                return dic
            except RuntimeError as exc:
                logging.fatal('Decode failed %s', exc)
        return None

    async def add_face(self, uri):
        # It's not easy to distinguish udp4://127.0.0.1 and udp4://spurs.cs.ucla.edu
        # if reduce(lambda a, b: a or b, (x.isalpha() for x in uri)):
        #     uri = socket.gethostbyname(uri)
        if uri[-1] == "/":
            uri = uri[:-1]
        if uri.find("://") < 0:
            uri = "udp4://" + uri
        if len(uri.split(":")) < 3:
            uri = uri + ":6363"

        interest = self.make_command('faces', 'create', uri=uri)
        return await self.issue_command_interest(interest)
    
    async def remove_face(self, face_id: int):
        interest = self.make_command('faces', 'destroy', face_id=face_id)
        return await self.issue_command_interest(interest)

    async def add_route(self, name: str, face_id: int):
        interest = self.make_command('rib', 'register',
                                     name=Name(name), face_id=face_id)
        return await self.issue_command_interest(interest)

    async def remove_route(self, name: str, face_id: int):
        interest = self.make_command('rib', 'unregister', 
                                     name=Name(name), face_id=face_id)
        return await self.issue_command_interest(interest)

    async def set_strategy(self, name: str, strategy: str):
        interest = self.make_command('strategy-choice', 'set',
                                     name=Name(name), strategy=Name(strategy))
        return await self.issue_command_interest(interest)

    async def unset_strategy(self, name: str):
        interest = self.make_command('strategy-choice', 'unset', name=Name(name))
        return await self.issue_command_interest(interest)

    def run_server(self, work_loop):
        asyncio.set_event_loop(work_loop)
        try:
            work_loop.run_until_complete(self.run())
        finally:
            work_loop.close()

    @staticmethod
    def start_server(emit_func):
        done = threading.Event()
        server = None

        def create_and_run():
            nonlocal server, done
            server = Server(emit_func)
            work_loop = asyncio.new_event_loop()
            asyncio.set_event_loop(work_loop)
            done.set()
            try:
                work_loop.run_until_complete(server.run())
            finally:
                work_loop.close()

        thread = threading.Thread(target=create_and_run)
        thread.setDaemon(True)
        thread.start()
        done.wait()
        return server

    def make_command(self, module, verb, **kwargs):
        name = Name('/localhost/nfd').append(module).append(verb)

        # Command Parameters
        cmd_param = ControlCommandMessage()
        if 'name' in kwargs:
            name_param = kwargs['name']
            for compo in name_param:
                cmd_param.control_parameters.name.component.append(compo.getValue().toBytes())
        if 'strategy' in kwargs:
            name_param = kwargs['strategy']
            for compo in name_param:
                cmd_param.control_parameters.strategy.name.component.append(compo.getValue().toBytes())
        for key in ['uri', 'local_uri']:
            if key in kwargs:
                setattr(cmd_param.control_parameters, key, kwargs[key].encode('utf-8'))
        for key in ['face_id', 'origin', 'cost', 'capacity', 'count', 'base_cong_mark', 'def_cong_thres',
                    'mtu', 'flags', 'mask', 'exp_period']:
            if key in kwargs:
                setattr(cmd_param.control_parameters, key, kwargs[key])
        param_blob = ProtobufTlv.encode(cmd_param)
        name.append(Name.Component(param_blob))

        # Command Interest Components
        ret = Interest(name)
        ret.canBePrefix = True
        self.face.makeCommandInterest(ret)

        return ret

    @staticmethod
    def list_key_tree():
        """
        Return the id-key-cert tree in a JSON like dict object.
        """
        pib = KeyChain().getPib()
        identities = pib._identities._identityNames
        ret = {}
        try:
            default_id = pib.getDefaultIdentity().getName()
        except Pib.Error:
            default_id = Name('/')
        for id_name in identities:
            id_obj = pib.getIdentity(Name(id_name))
            cur_id = {'default': '*' if id_name == default_id else ' '}
            try:
                default_key = id_obj.getDefaultKey().getName()
            except Pib.Error:
                default_key = Name('/')

            keys = id_obj._getKeys()._keyNames
            cur_id['keys'] = {}
            for key_name in keys:
                key_obj = id_obj.getKey(Name(key_name))
                cur_key = {'default': '*' if key_name == default_key else ' '}
                try:
                    default_cert = key_obj.getDefaultCertificate().getName()
                except Pib.Error:
                    default_cert = Name('/')

                key_type = key_obj.getKeyType()
                if key_type <= 4:
                    cur_key['key_type'] = ['NONE', 'RSA', 'EC', 'AES', 'HMAC'][key_type]
                else:
                    cur_key['key_type'] = 'unknown'

                certs = key_obj._getCertificates()._certificateNames
                cur_key['certs'] = {}
                for cert_name in certs:
                    cert_obj = key_obj.getCertificate(Name(cert_name))
                    signature = cert_obj.getSignature()
                    cur_cert = {
                        'default': '*' if cert_name == default_cert else ' ',
                        'not_before': str(cert_obj.getValidityPeriod().getNotBefore()),
                        'not_after': str(cert_obj.getValidityPeriod().getNotAfter()),
                        'issuer_id': cert_obj.getIssuerId().toEscapedString(),
                        'key_locator': signature.getKeyLocator().getKeyName().toUri(),
                        'signature_type': cert_obj.getSignature().__class__.__name__,
                    }
                    cur_key['certs'][cert_name.toUri()] = cur_cert
                cur_id['keys'][key_name.toUri()] = cur_key
            ret[id_name.toUri()] = cur_id
        return ret

    @staticmethod
    def create_identity(name):
        key_chain = KeyChain()
        try:
            cur_id = key_chain.getPib().getIdentity(Name(name))
            key_chain.createKey(cur_id)
        except Pib.Error:
            key_chain.createIdentityV2(Name(name))

    @staticmethod
    def delete_security_object(name, kind):
        key_chain = KeyChain()
        logging.info("Delete security object %s %s", name, kind)
        if kind == "c":
            id_name = CertificateV2.extractIdentityFromCertName(Name(name))
            key_name = CertificateV2.extractKeyNameFromCertName(Name(name))
            cur_id = key_chain.getPib().getIdentity(id_name)
            cur_key = cur_id.getKey(key_name)
            key_chain.deleteCertificate(cur_key, Name(name))
        elif kind == "k":
            id_name = PibKey.extractIdentityFromKeyName(Name(name))
            cur_id = key_chain.getPib().getIdentity(id_name)
            cur_key = cur_id.getKey(Name(name))
            key_chain.deleteKey(cur_id, cur_key)
        else:
            key_chain.deleteIdentity(Name(name))

    async def query_face_id(self, uri):
        query_filter = FaceQueryFilterMessage()
        query_filter.face_query_filter.uri = uri.encode('utf-8')
        query_filter_msg = ProtobufTlv.encode(query_filter)
        name = Name("/localhost/nfd/faces/query").append(Name.Component(query_filter_msg))
        interest = Interest(name)
        interest.mustBeFresh = True
        interest.canBePrefix = True
        ret = await fetch_data_packet(self.face, interest)
        if not isinstance(ret, Data):
            return None
        msg = FaceStatusMessage()
        try:
            ProtobufTlv.decode(msg, ret.content)
        except RuntimeError as exc:
            logging.fatal("Decoding Error %s", exc)
            return None
        if len(msg.face_status) <= 0:
            return None
        return msg.face_status[0].face_id

    async def autoconf(self):
        """
        Automatically connect to ndn testbed.
        Add route /ndn and /localhop/nfd.
        """
        uri = urllib.request.urlopen("http://ndn-fch.named-data.net/").read().decode('utf-8')
        uri = socket.gethostbyname(uri)
        uri = "udp4://" + uri + ":6363"

        interest = self.make_command('faces', 'create', uri=uri)
        ret = await fetch_data_packet(self.face, interest)
        if not isinstance(ret, Data):
            return False, "Create face failed"
        response = ControlResponseMessage()
        try:
            ProtobufTlv.decode(response, ret.content)
        except RuntimeError as exc:
            logging.info('Decode failed %s', exc)
            return False, "Create face failed"

        # # Ignore duplicated face
        # if response.control_response.st_code not in {200, 409}:
        #     return False, "Create face failed"

        face_id = await self.query_face_id(uri)
        if face_id is None:
            return False, "Create face failed"

        route = Name("/ndn")
        interest = self.make_command('rib', 'register', name=route, face_id=face_id, origin=66, cost=100)
        await fetch_data_packet(self.face, interest)

        route = Name("/localhop/nfd")
        interest = self.make_command('rib', 'register', name=route, face_id=face_id, origin=66, cost=100)
        await fetch_data_packet(self.face, interest)

        return True, "Auto-configuration finished"
コード例 #5
0
class IdentityManagementFixture(object):
    def __init__(self):
        self._keyChain = KeyChain("pib-memory:", "tpm-memory:")
        self._identityNames = set()
        self._certificateFiles = set()

    def saveCertificateToFile(self, data, filePath):
        """
        :param Data data: The certificate to save.
        :param str filePath: The file path, which should be writable.
        :return: True if successful.
        :rtype: bool
        """
        self._certificateFiles.add(filePath)

        try:
            encoding = data.wireEncode()
            encodedCertificate = Common.base64Encode(encoding.toBytes(), True)

            with open(filePath, 'w') as keyFile:
                keyFile.write(encodedCertificate)

            return True
        except Exception:
            return False

    def addIdentity(self, identityName, params = None):
        """
        Add an identity for the identityName.

        :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
          KeyChain.getDefaultKeyParams().
        :return: The created PibIdentity instance.
        :rtype: PibIdentity
        """
        if params == None:
            params = KeyChain.getDefaultKeyParams()

        identity = self._keyChain.createIdentityV2(identityName, params)
        self._identityNames.add(identityName)
        return identity

    def saveCertificate(identity, filePath):
        """
        Save the identity's certificate to a file.

        :param PibIdentity identity: The PibIdentity.
        :param str filePath: The file path, which should be writable.
        :return: True if successful.
        :rtype: str
        """
        try:
            certificate = identity.getDefaultKey().getDefaultCertificate()
            return self.saveCertificateToFile(certificate, filePath)
        except Pib.Error:
            return False

    def addSubCertificate(self, subIdentityName, issuer, params = None):
        """
        Issue a certificate for subIdentityName signed by issuer. If the
        identity does not exist, it is created. A new key is generated as the
        default key for the identity. A default certificate for the key is
        signed by the issuer using its default certificate.
        """
        if params == None:
            params = KeyChain.getDefaultKeyParams()

        subIdentity = self.addIdentity(subIdentityName, params)

        request = subIdentity.getDefaultKey().getDefaultCertificate()

        request.setName(request.getKeyName().append("parent").appendVersion(1))

        certificateParams = SigningInfo(issuer)
        # Validity period of 20 years.
        now = Common.getNowMilliseconds()
        certificateParams.setValidityPeriod(
          ValidityPeriod(now, now + 20 * 365 * 24 * 3600 * 1000.0))

        # Skip the AdditionalDescription.

        self._keyChain.sign(request, certificateParams)
        self._keyChain.setDefaultCertificate(subIdentity.getDefaultKey(), request)

        return subIdentity

    def addCertificate(self, key, issuerId):
        """
        Add a self-signed certificate made from the key and issuer ID.

        :param PibKey key: The key for the certificate.
        :param str issuerId: The issuer ID name component for the certificate
          name.
        :return: The new certificate.
        :rtype: CertificateV2
        """
        certificateName = Name(key.getName())
        certificateName.append(issuerId).appendVersion(3)
        certificate = CertificateV2()
        certificate.setName(certificateName)

        # Set the MetaInfo.
        certificate.getMetaInfo().setType(ContentType.KEY)
        # One hour.
        certificate.getMetaInfo().setFreshnessPeriod(3600 * 1000.0)

        # Set the content.
        certificate.setContent(key.getPublicKey())

        params = SigningInfo(key)
        # Validity period of 10 days.
        now = Common.getNowMilliseconds()
        params.setValidityPeriod(
          ValidityPeriod(now, now + 10 * 24 * 3600 * 1000.0))

        self._keyChain.sign(certificate, params)
        return certificate
コード例 #6
0
class ClientModule():
    def __init__(self, caPrefix):
        self.ecdh = ECDHState()
        self.face = Face()
        self.keyChain = KeyChain()
        self.key = None
        self.caPrefix = caPrefix
        self.anchor = CertificateV2()
        self.anchor.wireDecode(
            Blob(
                b64decode(
                    "Bv0DgQc7CANuZG4IA2VkdQgHbWVtcGhpcwgIYWdhd2FuZGUIA0tFWQgIo6cuGT4GVKEIAk5BCAn9AAABbQxT3hEUCRgBAhkEADbugBX9ASYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDII1sLOE7cCQVTKoGjeM5o/mxWqhMx0siLHJ81Ee/eUCNAMxA0w1oxAoTGQ8HbNP3vShZfvMJ/11Jiqus2wAWlNjRWvQShNv5MueU8kYtOGTbiqr/I1EpSRQ2aJX3s49CoskoWMzf6knK4ELleH3/EBUPGJK0cpHHdFOjwlzO3Y3Rtc/DhHVTVsBWvPS1wKgnzBFO36k73gAQJi4bOc0ggPPcK3UfVzpz8XTe+IcS2N9jew+kDqoZaL+HHz26PIAwQvXQFXPhE6y/nH/4yes24DlK3u+vHTQHXRKcLNSpYvmS6KrHvt2t01Fk0hXxeFkbh4XaE73eXB9AzNw+AccovAgMBAAEW/QEHGwEBHCQHIggDbmRuCANlZHUIB21lbXBoaXMIA0tFWQgI9bIQPIJIGTf9AP0m/QD+DzIwMTkwOTA2VDE1MjQ0Nf0A/w8yMDIwMDkwNlQxNTI0NDX9AQKw/QIAD/0CAQdhZHZpc29y/QICAP0CACH9AgEFZW1haWz9AgIUYWdhd2FuZGVAbWVtcGhpcy5lZHX9AgAf/QIBCGZ1bGxuYW1l/QICD0FzaGxlc2ggR2F3YW5kZf0CAA39AgEFZ3JvdXD9AgIA/QIAD/0CAQdob21ldXJs/QICAP0CAC39AgEMb3JnYW5pemF0aW9u/QICGVRoZSBVbml2ZXJzaXR5IG9mIE1lbXBoaXMX/QEAMZ4XLBqFjABr/k58Gq6GrNfaDMb+NLyJYF5X2mDwKnUgp1is83eg/90LqO8AVGYdyirKfr23HP4565iJXhOmFgRbP+faN++0oUTXdUSvDm43Rp+OCHr9uGPPYjUjUeNhrD7Fxfq5m3EHNMxQqnVJOODpVrF3D0EYJ4Q4IETmxrSmuDpH9I92fs7rU/51aNAZbU7DewPmcq/IrY4RO5G9pfYR+gu/gyO/L8gN39EhBbsOYWOh3EYOdAJlSktP1evL/5yRdQq7bVLyG6dZSsYQ1x4XDJ9epUesZ+TbCK/lXfRrmFG9uk8TI/rZNAYfUiQifnsNvRu34PcyELiFJ/h2xA=="
                )))
        self.identityName = ""
        self.status = None
        self.requestId = None
        self.challenges = None

    def sendProbeInterest(self):
        probeInterest = Interest(
            Name(self.caPrefix).append("CA").append("_PROBE"))

        probeInterest.setMustBeFresh(True)
        probeInterest.setCanBePrefix(False)

        probeInterest.setApplicationParameters(
            json.dumps({"email": "*****@*****.**"}, indent=4))
        probeInterest.appendParametersDigestToName()

        print("Expressing interest: {}".format(probeInterest.getName()))
        self.face.expressInterest(probeInterest, self.onProbeData,
                                  self.onTimeout)

    def onProbeData(self, interest, data):
        """ Content:
          {
              "email": "*****@*****.**",
              "UID": "",
              "name: "\/ndn\/edu\/memphis\/agawande\/6046888920342781294"
          }
          1) Verify signature
          2) Extract name component from the json to use as identity
        """
        if not VerificationHelpers.verifyDataSignature(data, self.anchor):
            print("Cannot verify signature from: {}".format(self.caPrefix))
        else:
            print("Successfully verified data with hard-coded certificate")

        try:
            self.identityName = Name(
                json.loads(data.getContent().__str__())['name'])
            if self.identityName == "":
                print("Name received from server is empty")
                sys.exit(0)
        except Exception as e:
            print(e)

        print("Got namespace {} from server".format(self.identityName))
        self.generateKeyAndSendNewInterest(data)

    def generateKeyAndSendNewInterest(self, probeTokenData):
        """
        """
        pib = self.keyChain.getPib()
        try:
            identity = pib.getIdentity(self.identityName)
            self.key = self.keyChain.createKey(identity)
        except Exception as e:
            identity = self.keyChain.createIdentityV2(self.identityName)
            self.key = identity.getDefaultKey()

        cert = CertificateV2()
        cert.setName(
            Name(self.key.getName()).append("cert-request").appendVersion(
                int(time.time())))
        cert.getMetaInfo().setType(ContentType.KEY)
        cert.getMetaInfo().setFreshnessPeriod(24 * 3600)
        cert.setContent(self.key.getPublicKey())

        signingInfo = SigningInfo(self.key)
        now = Common.getNowMilliseconds()
        signingInfo.setValidityPeriod(
            ValidityPeriod(now, now + 24 * 3600 * 1000.0))
        self.keyChain.sign(cert, signingInfo)
        #cert = self.keyChain.selfSign(self.key) # Does not work because validity period is greater than certserver default

        interestName = Name(self.caPrefix).append("CA").append("_NEW")
        newInterest = Interest(interestName)
        newInterest.setMustBeFresh(True)
        newInterest.setCanBePrefix(False)

        ecdhPub = "{}\n".format(self.ecdh.getBase64PubKey())
        ecdhCertReq = "{}\n".format(
            b64encode(cert.wireEncode().toBytes()).decode('utf-8'))
        probeToken = "{}\n".format(
            b64encode(probeTokenData.wireEncode().toBytes()).decode('utf-8'))

        jsonDump = json.dumps(
            {
                "ecdh-pub": ecdhPub,
                "cert-request": ecdhCertReq,
                "probe-token": probeToken
            },
            indent=4)
        print(jsonDump)
        newInterest.setApplicationParameters(jsonDump)
        newInterest.appendParametersDigestToName()

        self.keyChain.sign(newInterest, SigningInfo(self.key))

        print(newInterest.getName())

        self.face.expressInterest(newInterest, self.onNewData, self.onTimeout)

    def onNewData(self, interest, data):
        """
        !! Again \n in public key??
        Got data:  {
            "ecdh-pub": "Aqxofe3QdsAfgbtS8TMxv31oudNKoSV307ci5gNXm88h\n",
            "salt": "12935684137560555161",
            "request-id": "14275252044236690531",
            "status": "0",
            "challenges": [
                {
                    "challenge-id": "Email"
                }
            ]
        }
        1. Verify data
        2. Derive shared secret
        """
        content = data.getContent()
        print("Got data: ", content)
        if not VerificationHelpers.verifyDataSignature(data, self.anchor):
            print("Cannot verify signature from: {}".format(self.caPrefix))
        else:
            print("Successfully verified data with hard-coded certificate")

        contentJson = json.loads(content.__str__())
        peerKeyBase64 = contentJson['ecdh-pub']
        self.status = contentJson['status']
        self.requestId = contentJson['request-id']
        self.challenges = contentJson['challenges']

        print(peerKeyBase64)

        serverPubKey = ec.EllipticCurvePublicKey.from_encoded_point(
            ec.SECP256R1(), b64decode(peerKeyBase64))

        shared_key = self.ecdh.private_key.exchange(ec.ECDH(), serverPubKey)
        derived_key = HKDF(algorithm=hashes.SHA256(),
                           length=32,
                           salt=contentJson['salt'].encode(),
                           info=b'handshake data',
                           backend=default_backend()).derive(shared_key)

        self.ecdh.derived_key = derived_key
        print(shared_key)
        for t in shared_key:
            print(t)

        challengeInterestName = Name(
            self.caPrefix).append("CA").append("_CHALLENGE").append(
                self.requestId)
        challengeInterest = Interest(challengeInterestName)
        challengeInterest.setMustBeFresh(True)
        challengeInterest.setCanBePrefix(False)

        # Encrypt the interest parameters
        challengeJson = json.dumps(
            {
                "selected-challenge": "Email",
                "email": "*****@*****.**"
            },
            indent=4)
        raw = self.pad(challengeJson, 16)
        print("raw", raw)
        iv = Random.new().read(AES.block_size)
        #cipher = AES.new(self.ecdh.derived_key, AES.MODE_CBC, iv)
        cipher = AES.new(shared_key, AES.MODE_CBC, iv)
        print(iv)
        xx = cipher.encrypt(raw)

        print(cipher.decrypt(xx))

        print("Printing iv:")
        for t in iv:
            print(t)

        encoder = TlvEncoder(256)
        saveLength = len(encoder)
        encoder.writeBlobTlv(632, iv)
        encoder.writeBlobTlv(630, cipher.encrypt(raw))
        #encoder.writeTypeAndLength(36, len(encoder) - saveLength)

        challengeInterest.setApplicationParameters(Blob(encoder.getOutput()))
        challengeInterest.appendParametersDigestToName()

        self.keyChain.sign(challengeInterest, SigningInfo(self.key))

        with open('foobar.tlv', 'wb') as f:
            f.write(challengeInterest.wireEncode().buf())
        self.face.expressInterest(challengeInterest, self.onChallengeData,
                                  self.onTimeout)

    def onChallengeData(self, interest, data):
        print("Got data: ", data)

    def pad(self, s, blocksize):
        return s + (blocksize - len(s) % blocksize) * ' '

    def onTimeout(self, interest):
        print("Got timeout for interest: {}".format(interest.getName()))

    def start(self):
        while True:
            self.face.processEvents()
            # We need to sleep for a few milliseconds so we don't use 100% of the CPU.
            time.sleep(0.01)