Пример #1
0
def prepareMetadataChunks(metadataTuple, privateHandle):
	"""Encrypts, signs and adds the necessary flags to the metadata chunks.
	
	Arguments:
		metadataTuple {tuple of {bytes}} -- Output of squashAndSplitMetadataChunk(), where every element of the tuple is a metadata chunk.
		privateHandle {bytes} -- Self-explanatory.
	
	Returns:
		list -- List of metadata chunks - in order - ready to be encoded into trytes and sent in an iota tx.
	"""

	encryptionKey = encryption.getEncryptionKey(privateHandle)
	signingKey, verifyingKey = encryption.getKeypair(privateHandle)
	metadataChunkList = []

	address_gen = datamap.createDatamapGenerator(verifyingKey, len(metadataTuple) + 2)
	next(address_gen) # first address is the treasure chunk's so we don't need it right now

	for i, metadataChunk in enumerate(metadataTuple):
		encryptedChunk, nonce, _ = encryption.encryptAES(metadataChunk, encryptionKey)
		preparedChunk = encryptedChunk+nonce
		address = encryption.trytesToBytes(next(address_gen)[:-1])
		if i == 0:
			preparedChunk = addMetadataFlags(preparedChunk, len(metadataTuple))
		signature = encryption.signChunk(preparedChunk + address, signingKey)
		finalMetadataChunk = b"".join([preparedChunk, signature])
		metadataChunkList.append(finalMetadataChunk)

	return metadataChunkList

	
Пример #2
0
def test_End_to_End():
	number_of_files = random.randint(4, 10)

	filenameList = ["testfile_" + str(i+1) for i in range(number_of_files)]
	initialize_multiple_files(filenameList)
	passwordFlagList = [bool(random.getrandbits(1)) for i in filenameList]
	passwordDict = {filename:"oyster" for filename, flag in zip(filenameList, passwordFlagList) if flag}

	privateHandle = encryption.getPrivateHandle()
	_, verifyingKey = encryption.getKeypair(privateHandle)
	encryptionKey = encryption.getEncryptionKey(privateHandle)

	rawMetadataChunk = fileprocessor.makeMetadataChunk(filenameList, passwordFlagList, verifyingKey)
	metadataChunkTuple = fileprocessor.squashAndSplitMetadataChunk(rawMetadataChunk)

	allChunksList = [b"TreasureChunkHere"] + fileprocessor.prepareMetadataChunks(metadataChunkTuple, privateHandle)

	for filename in filenameList:
		offsetHash = bytes.fromhex(rawMetadataChunk[filename]["offsetHash"])
		if filename in passwordDict: # This statement is only True if filename has been added to the keys in the dict, which means it has a password
			fileChunks = fileprocessor.fileToChunks(filename, privateHandle, offsetHash, password=passwordDict[filename])
		else:
			fileChunks = fileprocessor.fileToChunks(filename, privateHandle, offsetHash)
		allChunksList += fileChunks

	firstMetadataChunk = allChunksList[1]
	metadataChunkNumberFlag_bytes, _ = fileprocessor.stripMetadataFlags(firstMetadataChunk)
	numberFlag = int(np.fromstring(metadataChunkNumberFlag_bytes, dtype='uint8'))

	metadataArray = allChunksList[1:numberFlag+1]
	metadataJSON = fileprocessor.unpackMetadata(metadataArray, encryptionKey)

	decrypted_filenameList = list(metadataJSON.keys())

	for filename in decrypted_filenameList:
		startIdx = metadataJSON[filename]["startIdx"]
		endIdx = startIdx + metadataJSON[filename]["chunkCount"]
		passwordFlag = bool(metadataJSON[filename]["password"])
		decrypted_filename = "decrypted_"+filename
				
		fileList = allChunksList[startIdx:endIdx]
		if passwordFlag:
			fileprocessor.chunksToFile(fileList, encryptionKey, decrypted_filename, password=passwordDict[filename])
		else:
			fileprocessor.chunksToFile(fileList, encryptionKey, decrypted_filename)

		assert read_binary_file(filename) == read_binary_file(decrypted_filename)

		assert SHA256.new(read_binary_file(filename)).digest() == SHA256.new(read_binary_file(decrypted_filename)).digest()
	
	address_gen = datamap.createDatamapGenerator(verifyingKey, None, 1)
	for chunk in allChunksList[1:]: #first chunk is the treasure chunk and doesn't get signed when doing local simulations
		data_chunk, signature = encryption.splitChunkAndSignature(chunk)
		address = encryption.trytesToBytes(next(address_gen)[:-1])
		encryption.verifyChunk(data_chunk + address, signature, verifyingKey.hex())
	assert True

	cleanup()
Пример #3
0
 def test_verify_chunk_signatures(self):
     _, verifyingKey = encryption.getKeypair(self.privateHandle)
     address_gen = datamap.createDatamapGenerator(verifyingKey,
                                                  len(self.chunkList) + 1)
     for chunk in self.chunkList:
         datachunk, signature = encryption.splitChunkAndSignature(chunk)
         address = encryption.trytesToBytes(next(address_gen)[:-1])
         encryption.verifyChunk(datachunk + address, signature,
                                verifyingKey.hex())
     assert True
Пример #4
0
def fileToChunks(filename, privateHandle, startingHash, password = None):
	"""Takes a filename and returns the file converted to rev2 compliant chunks, already signed.
	
	Arguments:
		filename {str} -- Self-explanatory. Also needs to include the extension.
		privateHandle {bytes} -- Bytestring to use as the private handle. Can and should be generated using encryption.getPrivateHandle().
		startingHash {bytes} -- Hash on the main hashchain corresponding to the position of the first chunk of the file on the datamap.
	
	Keyword Arguments:
		password {str} -- Optional argument. Use it to password protect a particular file in a multi-file upload (default: {None})
	
	Returns:
		list -- Every element is a chunk, in the same order as the bytes are read from the file. 
	"""
	
	signingKey, _ = encryption.getKeypair(privateHandle)	
	encryptionKey = encryption.getEncryptionKey(privateHandle)

	f = open(filename, mode="rb")
	filesize = os.path.getsize(filename)
	chunksize = 1013
	numberOfChunks = math.ceil(filesize/chunksize)

	fileList = []

	if password is not None:
		encryptionKey = encryption.getEncryptionKey(encryptionKey + password.encode("utf-8"))
		numberOfChunks = math.ceil((filesize - 997)/chunksize) + 1
		chunksize = 997

	address_gen = datamap.createDatamapGenerator(startingHash, numberOfChunks + 1)

	for i in range(0, numberOfChunks):
		chunk = f.read(chunksize)
		encrypted_chunk, nonce, tag = encryption.encryptAES(chunk, encryptionKey)
		address_trytes = next(address_gen)[:-1] #the real address is 81 chars, but the byte conversion only works with even numbers, so we use the first 80 chars of the address to sign and check 
		address_bytes = encryption.trytesToBytes(address_trytes)
		
		if password is not None and i == 0:
			unsigned_chunk = b"".join([encrypted_chunk, nonce, tag])
			chunksize = 1013
		else:
			unsigned_chunk = b"".join([encrypted_chunk, nonce])
			
		signature = encryption.signChunk(unsigned_chunk + address_bytes, signingKey)
		completed_chunk = unsigned_chunk + signature
		fileList.append(completed_chunk)
	
	f.close()
	
	return fileList