def test_register_prefix_response(self): # gotta sign it (WAT) prefixName = Name("/unittest") self.face_in.setCommandSigningInfo( self.keyChain, self.keyChain.getDefaultCertificateName()) failedCallback = Mock() interestCallback = Mock(side_effect=self.onInterestEffect) self.face_in.registerPrefix(prefixName, interestCallback, failedCallback) server = gevent.spawn(self.face_process_events, self.face_in, [interestCallback, failedCallback], 'h') gevent.sleep(1) # give the 'server' time to register the interest # express an interest on another face dataCallback = Mock() timeoutCallback = Mock() # now express an interest on this new face, and see if onInterest is called interestName = prefixName.append("hello") self.face_out.expressInterest(interestName, dataCallback, timeoutCallback) client = gevent.spawn(self.face_process_events, self.face_out, [dataCallback, timeoutCallback], 'c') gevent.joinall([server, client], timeout=10) self.assertEqual(failedCallback.call_count, 0, 'Failed to register prefix at all') self.assertEqual( interestCallback.call_count, 1, 'Expected 1 onInterest callback, got ' + str(interestCallback.call_count)) self.assertEqual( dataCallback.call_count, 1, 'Expected 1 onData callback, got ' + str(dataCallback.call_count)) onDataArgs = dataCallback.call_args[0] # check the message content data = onDataArgs[1] expectedBlob = Blob(bytearray("SUCCESS")) self.assertTrue( expectedBlob.equals(data.getContent()), 'Data received on face does not match expected format')
def handle_completion(self): content = bytearray() for i in sorted(self.segments): segment = self.segments[i] content.extend(segment.getContent().buf()) interest = Interest(Name(self.name)) blob = Blob(content) size = blob.size() Log.info( "Received all segments ({} bytes) for interest '{}':\n{}".format( size, Util.interest_to_string(interest), urllib.parse.unquote(blob.toRawStr()))) data = Data(interest.getName()) data.setContent(blob) self.on_data(self, data)
def on_generalized_obj(self, name: Name, meta_info: ContentMetaInfo, obj: Blob) -> None: self.storage.put( Name(name).append("_meta"), meta_info.wireEncode().toBytes()) self.storage.put(name, obj.toBytes()) self.on_payload(name)
def main(): backboneFace = Face() pibImpl = PibMemory() keyChain = KeyChain(pibImpl, TpmBackEndMemory(), SelfVerifyPolicyManager(pibImpl)) # This puts the public key in the pibImpl used by the SelfVerifyPolicyManager. keyChain.importSafeBag( SafeBag(Name("/testname/KEY/123"), Blob(DEFAULT_RSA_PRIVATE_KEY_DER, False), Blob(DEFAULT_RSA_PUBLIC_KEY_DER, False))) backboneFace.setCommandSigningInfo(keyChain, keyChain.getDefaultCertificateName()) prefix = Name("/farm1") backboneFace.registerPrefix(prefix, onInterest, onRegisterFailed) print("Ready to go...") while 1: try: backboneFace.processEvents() e.acquire() frame = ieee.wait_read_frame(0.01) e.release() if frame is not None: if frame['rf_data'][0] == b'\x06' or frame['rf_data'][ 0] == b'\x05': #if Data or Interest buffData[0] = frame['rf_data'][0] buffData[1] = ord(frame['rf_data'][1]) + lCP buffData[2] = frame['rf_data'][2] buffData[3] = ord(frame['rf_data'][3]) + lCP buffData[4:lCP + 4] = eCP buffData[lCP + 4:] = frame['rf_data'][4:] print(str(datetime.now().strftime('%X.%f'))) backboneFace.send(buffData) else: print(frame['rf_data'][:]) #time.sleep(0.1) gc.collect() except KeyboardInterrupt: backboneFace.shutdown() ser.close() break
def on_interest(self, _prefix, interest: Interest, face, _filter_id, _filter): name = interest.getName() if not self.storage.exists(str(name)): return raw_data = self.storage.get(str(name)) data = Data() data.wireDecode(Blob(pickle.loads(raw_data))) self.face.putData(data) logging.info('Read handle: serve data {}'.format(interest.getName()))
async def fetch_gobject(face: Face, prefix: Name, on_success: Callable[[Name, ContentMetaInfo, Blob], None], on_failure: Callable[[Name], None], semaphore: asyncio.Semaphore): async def retry_or_fail(): nonlocal interest result = None # retry for up to FETCHER_MAX_ATTEMPT_NUMBER times for _ in range(FETCHER_MAX_ATTEMPT_NUMBER): # express interest async with semaphore: response = await WaitForResponse(face, interest).run() if response.data is not None: # if succeeded, jump out result = response.data break else: # if failed, wait for next time # This will lead to an additional delay but okay await asyncio.sleep(FETCHER_RETRY_INTERVAL / 1000.0) return result # fetch and decode meta info interest = Interest(Name(prefix).append("_meta")) data_packet = await retry_or_fail() if data_packet is None: on_failure(prefix) return meta_info = ContentMetaInfo() try: meta_info.wireDecode(data_packet.content) except ValueError: on_failure(prefix) return # fetch and attach data data = bytes("", "utf-8") final_id = FETCHER_FINAL_BLOCK_ID cur_id = 0 while cur_id <= final_id: interest = Interest(Name(prefix).appendSegment(cur_id)) data_packet = await retry_or_fail() if data_packet is None: on_failure(prefix) return data += data_packet.content.toBytes() final_id_component = data_packet.metaInfo.getFinalBlockId() if final_id_component.isSegment(): final_id = final_id_component.toSegment() cur_id += 1 on_success(prefix, meta_info, Blob(data))
def test_register_prefix_response(self): # gotta sign it (WAT) prefixName = Name("/test") self.face_in.setCommandSigningInfo(self.keyChain, self.keyChain.getDefaultCertificateName()) failedCallback = Mock() interestCallback = Mock(side_effect=self.onInterestEffect) self.face_in.registerPrefix(prefixName, interestCallback, failedCallback) server = gevent.spawn(self.face_process_events, self.face_in, [interestCallback, failedCallback], 'h') gevent.sleep(1) # give the 'server' time to register the interest # express an interest on another face dataCallback = Mock() timeoutCallback = Mock() # now express an interest on this new face, and see if onInterest is called interestName = prefixName.append("hello") self.face_out.expressInterest(interestName, dataCallback, timeoutCallback) client = gevent.spawn(self.face_process_events, self.face_out, [dataCallback, timeoutCallback], 'c') gevent.joinall([server, client], timeout=10) self.assertEqual(failedCallback.call_count, 0, 'Failed to register prefix at all') self.assertEqual(interestCallback.call_count, 1, 'Expected 1 onInterest callback, got '+str(interestCallback.call_count)) self.assertEqual(dataCallback.call_count, 1, 'Expected 1 onData callback, got '+str(dataCallback.call_count)) onDataArgs = dataCallback.call_args[0] # check the message content data = onDataArgs[1] expectedBlob = Blob(bytearray("SUCCESS")) self.assertTrue(expectedBlob.equals(data.getContent()), 'Data received on face does not match expected format')
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 __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 fetch_gobject(face, prefix, on_success, on_failure, semaphore): def retry_or_fail(interest): # use a nonlocal var for "return in generator" data_packet = None # retry for up to FETCHER_MAX_ATTEMPT_NUMBER times for _ in range(FETCHER_MAX_ATTEMPT_NUMBER): # express interest with (yield semaphore.require()): response = yield WaitForResponse(face, interest) if response.data is not None: # if succeeded, jump out data_packet = response.data break else: # if failed, wait for next time # This will lead to an additional delay but okay yield Delay(FETCHER_RETRY_INTERVAL) if data_packet is None: # if we used up all attempts, fail on_failure(prefix) yield Finished() return data_packet # fetch and decode meta info interest = Interest(Name(prefix).append("_meta")) data_packet = yield from retry_or_fail(interest) meta_info = ContentMetaInfo() try: meta_info.wireDecode(data_packet.content) except ValueError: on_failure(prefix) yield Finished() # fetch and attach data data = bytes("", "utf-8") final_id = FETCHER_FINAL_BLOCK_ID cur_id = 0 while cur_id <= final_id: interest = Interest(Name(prefix).appendSegment(cur_id)) data_packet = yield from retry_or_fail(interest) data += data_packet.content.toBytes() final_id_component = data_packet.metaInfo.getFinalBlockId() if final_id_component.isSegment(): final_id = final_id_component.toSegment() cur_id += 1 on_success(prefix, meta_info, Blob(data))
def publish_temp_packet(self): tp = int(time.time()) tp = tp - (tp % 5) self.latest_tp = tp data_name = Name(self.prefix).append(str(self.latest_tp)) data = Data(data_name) temp = self.get_temp() content_blob = Blob(temp.to_bytes(2, byteorder='little')) data.setContent(content_blob) data.metaInfo.setFreshnessPeriod(1000000) logging.info('Publish temp data {}, {} degree'.format(data.getName(), temp)) self.keychain.sign(data) self.name_str_to_data[str(data.getName())] = data if use_repo is True: event_loop = asyncio.get_event_loop() event_loop.create_task(self.send_cmd_interest()) logging.info("send repo insertion command")
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 test_register_prefix_response(self): prefixName = Name("/test") self.face_in.setCommandSigningInfo(self.keyChain, self.keyChain.getDefaultCertificateName()) interestCallbackCount = [0] def onInterest(prefix, interest, face, interestFilterId, filter): interestCallbackCount[0] += 1 data = Data(interest.getName()) data.setContent("SUCCESS") self.keyChain.sign(data, self.keyChain.getDefaultCertificateName()) face.putData(data) failedCallback = Mock() self.face_in.registerPrefix(prefixName, onInterest, failedCallback) # Give the 'server' time to register the interest. timeout = 1000 startTime = getNowMilliseconds() while True: if getNowMilliseconds() - startTime >= timeout: break self.face_in.processEvents() time.sleep(0.01) # express an interest on another face dataCallback = Mock() timeoutCallback = Mock() # now express an interest on this new face, and see if onInterest is called # Add the timestamp so it is unique and we don't get a cached response. interestName = prefixName.append("hello" + repr(time.time())) self.face_out.expressInterest(interestName, dataCallback, timeoutCallback) # Process events for the in and out faces. timeout = 10000 startTime = getNowMilliseconds() while True: if getNowMilliseconds() - startTime >= timeout: break self.face_in.processEvents() self.face_out.processEvents() done = True if interestCallbackCount[0] == 0 and failedCallback.call_count == 0: # Still processing face_in. done = False if dataCallback.call_count == 0 and timeoutCallback.call_count == 0: # Still processing face_out. done = False if done: break time.sleep(0.01) self.assertEqual(failedCallback.call_count, 0, 'Failed to register prefix at all') self.assertEqual(interestCallbackCount[0], 1, 'Expected 1 onInterest callback, got '+str(interestCallbackCount[0])) self.assertEqual(dataCallback.call_count, 1, 'Expected 1 onData callback, got '+str(dataCallback.call_count)) onDataArgs = dataCallback.call_args[0] # check the message content data = onDataArgs[1] expectedBlob = Blob("SUCCESS") self.assertTrue(expectedBlob == data.getContent(), 'Data received on face does not match expected format')
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
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)