def onInterest(self, prefix, interest, face, interestFilterId, filter): self._callbackCount = 0 # log.debug("prefix: '{}'".format(prefix)) # log.debug("interest: '{}'".format(interest)) # log.debug("face: '{}'".format(face)) # log.debug("interestFilterId: '{}'".format(interestFilterId)) # log.debug("filter: '{}'".format(filter)) data = Data() # # log.debug("----") # for n in self.db: # log.debug(n) # log.debug(self.db[n].value) # log.debug("----") # n = str(prefix).split("/")[-1] log.debug("{} value '{}' ({})".format(prefix, self.db[n].value, self.freshnessPeriod)) data.setContent(str(self.db[n].value)) # TODO: Why does this need to be converted to string? data.setName(prefix) meta = MetaInfo() meta.setFreshnessPeriod(self.freshnessPeriod) data.setMetaInfo(meta) self.keyChain.sign(data) face.putData(data)
def _onObjectNeeded(self, namespace, neededNamespace, callbackId): """ This is called for object needed at the Handler's namespace. If neededNamespace is the Handler's Namespace (called by the appliction), then fetch the _latest packet. If neededNamespace is for the _latest packet (from an incoming Interest), produce the _latest packet for the current sequence number. """ if neededNamespace == self.namespace: # Assume this is called by a consumer. Fetch the _latest packet. self._latestNamespace.objectNeeded(True) return True if (neededNamespace == self._latestNamespace and self._producedSequenceNumber >= 0): # Produce the _latest Data packet. sequenceName = Name(self.namespace.name).append( Name.Component.fromSequenceNumber( self._producedSequenceNumber)) delegations = DelegationSet() delegations.add(1, sequenceName) versionedLatest = self._latestNamespace[Name.Component.fromVersion( Common.getNowMilliseconds())] metaInfo = MetaInfo() metaInfo.setFreshnessPeriod(self._latestPacketFreshnessPeriod) versionedLatest.setNewDataMetaInfo(metaInfo) # Make the Data packet and reply to outstanding Interests. versionedLatest.serializeObject(delegations.wireEncode()) return True return False
def main(): # The default Face will connect using a Unix socket, or to "localhost". face = Face() # Create an in-memory key chain with default keys. keyChain = KeyChain() face.setCommandSigningInfo(keyChain, keyChain.getDefaultCertificateName()) streamNamespace = Namespace(Name("/example-data"), keyChain) dump("Register prefix", streamNamespace.name) # Set the face and register to receive Interests. streamNamespace.setFace(face, lambda prefixName: dump("Register failed for prefix", prefixName)) # /example-data/2~3 for sequenceNumber in range(2, 4): sequenceNamespace = streamNamespace[str(sequenceNumber)] dump("Preparing data for", sequenceNamespace.name) # Prepare the _meta packet. contentMetaInfo = ContentMetaInfo() contentMetaInfo.setContentType("jpeg") contentMetaInfo.setTimestamp(Common.getNowMilliseconds()) contentMetaInfo.setHasSegments(True) sequenceNamespace["_meta"].serializeObject(contentMetaInfo.wireEncode()) # Read jpeg file img_path = os.path.join(root_path, "sample420x236.jpg") with open(img_path, "rb") as f: data = f.read() segment_size = face.getMaxNdnPacketSize() // 2 segment_cnt = (len(data) + segment_size - 1) // segment_size # We know the content has two segments. metaInfo = MetaInfo() metaInfo.setFinalBlockId(Name().appendSegment(segment_cnt - 1)[0]) sequenceNamespace.setNewDataMetaInfo(metaInfo) for i in range(segment_cnt): start_offset = i * segment_size end_offset = start_offset + segment_size sequenceNamespace[Name.Component.fromSegment(i)].serializeObject( Blob(bytearray(data[start_offset:end_offset]))) while True: face.processEvents() # We need to sleep for a few milliseconds so we don't use 100% of the CPU. time.sleep(0.01)
def main(): # The default Face will connect using a Unix socket, or to "localhost". face = Face() # Use the system default key chain and certificate name to sign. keyChain = KeyChain() face.setCommandSigningInfo(keyChain, keyChain.getDefaultCertificateName()) prefix = Namespace("/ndn/test/status", keyChain) dump("Register prefix", prefix.name) # Set the face and register to receive Interests. prefix.setFace(face, lambda prefixName: dump("Register failed for prefix", prefixName)) handler = GeneralizedObjectHandler() # Each generalized object will have a 1000 millisecond freshness period. metaInfo = MetaInfo() metaInfo.setFreshnessPeriod(1000.0) # This is called when the library receives an Interest which is not # satisfied by Data already in the Namespace tree. def onObjectNeeded(namespace, neededNamespace, callbackId): if not (neededNamespace is prefix): # This is not the expected Namespace. return False # Make a version from the current time. versionNamespace = prefix[ Name.Component.fromVersion(Common.getNowMilliseconds())] # The metaInfo has the freshness period. versionNamespace.setNewDataMetaInfo(metaInfo) dump("Producing the generalized object for", versionNamespace.name) handler.setObject( versionNamespace, Blob("Status as of " + str(datetime.datetime.now())), "text/html") return True prefix.addOnObjectNeeded(onObjectNeeded) while True: face.processEvents() # We need to sleep for a few milliseconds so we don't use 100% of the CPU. time.sleep(0.01)
def main(args): face = Face() keyChain = KeyChain() face.setCommandSigningInfo(keyChain, keyChain.getDefaultCertificateName()) gobj = Namespace(args['<prefix>'], keyChain) gobj.setFace( face, lambda prefixName: dump("Register failed for prefix", prefixName)) handler = GeneralizedObjectHandler() metaInfo = MetaInfo() if args['--freshness']: metaInfo.setFreshnessPeriod(float(args['--freshness'])) else: metaInfo.setFreshnessPeriod(1000.0) def onObjectNeeded(namespace, neededNamespace, callbackId): if not (neededNamespace is gobj): # This is not the expected Namespace. return False # Make a version from the current time. versionNamespace = gobj[Name.Component.fromVersion( Common.getNowMilliseconds())] # The metaInfo has the freshness period. versionNamespace.setNewDataMetaInfo(metaInfo) with open(args['<file>'], 'r') as f: handler.setObject(versionNamespace, Blob(f.read()), "text/html") return True gobj.addOnObjectNeeded(onObjectNeeded) while True: face.processEvents() time.sleep(0.01)
def nodata_reply(self, name, code, retry_after=0.0): # type: (Name, int, float) -> None logging.info("Reply with code: %s", code) data = Data(name) metainfo = MetaInfo() msg = ServerResponseMessage() msg.server_response.ret_code = code if code != RET_OK: metainfo.type = ContentType.NACK else: metainfo.type = ContentType.BLOB if retry_after > 0.1: metainfo.freshnessPeriod = int(retry_after / 10) msg.server_response.retry_after = int(retry_after) else: metainfo.freshnessPeriod = 600 data.setMetaInfo(metainfo) data.setContent(ProtobufTlv.encode(msg)) self.keychain.sign(data) self.face.putData(data)
def onInterest(self, prefix, interest, transport, registeredPrefixId): """ Interest: Name: /ndn/no/ntnu/<device>/sensorPull/<nonce> Selector: KeyLocator = ID The ID of the requesting Device is stored in KeyLocator in the Interest, and the TemporaryMasterPublicKey to the device is sent in the Interest Name as shown above. Encrypt a symmetric key with the MasterPublicKey and the ID. Encrypt the SensorData with symmetric encryption, using the symmetric key. Data: Content: master_public_key to PKG ibeKey = ibe(randomKey) cipher = encrypt(sensorData, randomKey) Sign the Data and send. :param Name prefix: :param Interest interest: :param Transport transport: An object of a subclass of Transport to use for communication. :param Name registeredPrefixId: """ self.ibs_scheme.verifyInterest(self.signature_master_public_key, interest, self.onVerifiedInterest, self.onVerifyInterestFailed) ID = "" if interest.getKeyLocator().getType() == KeyLocatorType.KEYNAME: ID = interest.getKeyLocator().getKeyName().toUri() keyName = interest.getName() session = keyName.get(keyName.size() - 1).toEscapedString() data = Data(interest.getName()) contentData = "This should be sensordata blablabla" # Symmetric key for encryption self.key = self.ibe_scheme.getRandomKey() # Identity-Based Encryption of symmetric key identityBasedEncryptedKey = self.ibe_scheme.encryptKey( self.master_public_key, ID, self.key) identityBasedEncryptedKey = str( serializeObject(identityBasedEncryptedKey, self.ibe_scheme.group)) # Master Public Key identityBasedMasterPublicKey = str( serializeObject(self.master_public_key, self.ibe_scheme.group)) # Signature Master Public Key identityBasedSignatureMasterPublicKey = str( serializeObject(self.signature_master_public_key, self.ibs_scheme.group)) # Symmetric AES encryption of contentData a = SymmetricCryptoAbstraction(extractor(self.key)) encryptedMessage = a.encrypt(contentData) message = messageBuf_pb2.Message() message.identityBasedMasterPublicKey = identityBasedMasterPublicKey message.identityBasedSignatureMasterPublicKey = identityBasedSignatureMasterPublicKey message.identityBasedEncryptedKey = identityBasedEncryptedKey message.encryptedMessage = encryptedMessage message.encAlgorithm = messageBuf_pb2.Message.AES message.ibeAlgorithm = self.ibe_scheme.algorithm message.ibsAlgorithm = self.ibs_scheme.algorithm message.nonce = session message.timestamp = int(round(util.getNowMilliseconds() / 1000.0)) message.type = messageBuf_pb2.Message.SENSOR_DATA content = message.SerializeToString() metaInfo = MetaInfo() metaInfo.setFreshnessPeriod(30000) # 30 seconds data.setContent(Blob(content)) data.setMetaInfo(metaInfo) self.ibs_scheme.signData(self.signature_master_public_key, self.signature_private_key, self.deviceName, data) #self.keyChain.sign(data, self.certificateName) encodedData = data.wireEncode() logging.info("Encrypting with ID: " + ID) transport.send(encodedData.toBuffer()) logging.info("Sent encrypted Data")
def main(): # The default Face will connect using a Unix socket, or to "localhost". face = Face() # Create an in-memory key chain with default keys. keyChain = KeyChain("pib-memory:", "tpm-memory:") keyChain.importSafeBag( SafeBag(Name("/testname/KEY/123"), Blob(DEFAULT_RSA_PRIVATE_KEY_DER, False), Blob(DEFAULT_RSA_PUBLIC_KEY_DER, False))) face.setCommandSigningInfo(keyChain, keyChain.getDefaultCertificateName()) # Enable Interest loopback so that the EncryptorV2 can fetch Data packets # from the AccessManagerV2. face.setInterestLoopbackEnabled(True) contentPrefix = Name("/testname/content") contentNamespace = Namespace(contentPrefix, keyChain) # We know the content has two segments. metaInfo = MetaInfo() metaInfo.setFinalBlockId(Name().appendSegment(1)[0]) contentNamespace.setNewDataMetaInfo(metaInfo) ckPrefix = Name("/some/ck/prefix") encryptor = prepareData(ckPrefix, keyChain, face) # Make the callback to produce a Data packet for a content segment. def onObjectNeeded(namespace, neededNamespace, id): if not (len(neededNamespace.name) == len(contentPrefix) + 1 and contentPrefix.isPrefixOf(neededNamespace.name) and neededNamespace.name[-1].isSegment()): # Not a content segment, ignore. return False # Get the segment number. segment = neededNamespace.name[-1].toSegment() if not (segment >= 0 and segment <= 1): # An invalid segment was requested. return False segmentContent = ("This test message was decrypted" if segment == 0 else " from segments.") # Now call serializeObject which will answer the pending incoming Interest. dump("Producing Data", neededNamespace.name) neededNamespace.serializeObject( encryptor.encrypt(Blob(segmentContent)).wireEncodeV2()) return True contentNamespace.addOnObjectNeeded(onObjectNeeded) dump("Register prefix", contentNamespace.name) # Set the face and register to receive Interests. contentNamespace.setFace( face, lambda prefixName: dump("Register failed for prefix", prefixName)) while True: face.processEvents() # We need to sleep for a few milliseconds so we don't use 100% of the CPU. time.sleep(0.01)
def on_result_interest(self, _prefix, interest, face, _interest_filter_id, _filter_obj): # type: (Name, Interest, Face, int, InterestFilter) -> bool prefix = Name(SERVER_PREFIX).append(RESULT_PREFIX) if not prefix.isPrefixOf(interest.name): # Wrong prefix return False data_name = interest.name[prefix.size():] logging.info("On result interest: %s", data_name.toUri()) # key, stat = self._result_set_prefix_match(data_name) status = self.load_status(data_name) if status is None: # No such request self.nodata_reply(interest.name, RET_NO_REQUEST) return True if data_name[-1].isSegment(): # Segment no suffix seg_no = data_name[-1].toSegment() result = self.storage.get(data_name.getPrefix(-1)) elif data_name[-1] == Name("_meta")[0]: # MetaInfo suffix seg_no = -1 result = self.storage.get(data_name.getPrefix(-1)) else: # No suffix seg_no = None result = self.storage.get(data_name) if result is not None: # There are data segment_cnt = (len(result) + self.segment_size - 1) // self.segment_size # Note: I don't understand why namespace keep all data in memory metainfo = MetaInfo() # metainfo.setFinalBlockId(segment_cnt - 1) # WHY this doesn't work? metainfo.setFinalBlockId(Name().appendSegment(segment_cnt - 1)[0]) if segment_cnt > 1 and seg_no is None: # Fetch segmented data with no suffix will get only first segment seg_no = 0 data_name.appendSequenceNumber(seg_no) data = Data(Name(prefix).append(data_name)) data.setMetaInfo(metainfo) if seg_no == -1: # _meta data.content = self.storage.get(data_name) else: # data if segment_cnt > 1: # Segmented if seg_no < segment_cnt: start_offset = seg_no * self.segment_size end_offset = start_offset + self.segment_size data.content = Blob(bytearray(result[start_offset:end_offset])) else: data.content = None else: # No segmentation data.content = Blob(bytearray(result)) self.keychain.sign(data) face.putData(data) return True else: # Data are not ready if status.status == STATUS_NO_INPUT: self.nodata_reply(interest.name, RET_NO_INPUT) elif status.status == STATUS_FAILED: self.nodata_reply(interest.name, RET_EXECUTION_FAILED) else: self.nodata_reply(interest.name, RET_RETRY_AFTER, status.estimated_time - Common.getNowMilliseconds()) return True