示例#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
class TestChunkingFunctionsWithoutPassword(object):
    _path = "testfile_4"
    initialize_file(_path)
    privateHandle = encryption.getPrivateHandle()
    _, genesisHash = encryption.getKeypair(privateHandle)

    raw_file = read_binary_file(_path)
    chunkList = fileprocessor.fileToChunks(_path, privateHandle, genesisHash)

    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

    def test_decrypting_chunked_file(self):
        encryptionKey = encryption.getEncryptionKey(self.privateHandle)
        decrypted_path = self._path + "_decrypted"
        assert fileprocessor.chunksToFile(self.chunkList, encryptionKey,
                                          decrypted_path)

        decrypted_file = read_binary_file(decrypted_path)
        assert decrypted_file == self.raw_file

    #! Put functions here

    def test_clean_file(self):
        cleanup()
示例#3
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()
示例#4
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
示例#5
0
class TestEd25519Keys(object):
    signing_key, verifying_key = encryption.getKeypair(
        encryption.getPrivateHandle())

    def test_keys_are_bytes(self):
        assert type(self.signing_key) is bytes
        assert type(self.verifying_key) is bytes

    def test_signing_key_is_32_bytes(self):
        assert len(self.signing_key) == 32
示例#6
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
示例#7
0
class TestChunkEncryption(object):
    #setup
    uncrypted_chunk = b"THIS COULD BE ANYTHING"
    private_handle = encryption.getPrivateHandle()
    signing_key, verifying_key = encryption.getKeypair(private_handle)
    encryption_key = encryption.getEncryptionKey(private_handle)

    #actually encrypt the chunk
    encrypted_chunk, nonce, tag = encryption.encryptAES(
        uncrypted_chunk, encryption_key)

    def test_length_encrypted_is_equal_to_length_uncrypted(self):
        assert len(self.encrypted_chunk) == len(self.uncrypted_chunk)

    def test_nonce_and_tag_lengths_are_16_bytes(self):
        assert len(self.nonce) == 16 and type(self.nonce) is bytes
        assert len(self.tag) == 16 and type(self.tag) is bytes

    def test_decryption_without_verification(self):
        completed_chunk = b''.join([self.encrypted_chunk, self.nonce])
        decrypted_chunk = encryption.decryptAES(completed_chunk,
                                                self.encryption_key)
        assert decrypted_chunk == self.uncrypted_chunk

    def test_decryption_with_verification(self):
        completed_chunk = b''.join(
            [self.encrypted_chunk, self.nonce, self.tag])
        decrypted_chunk = encryption.decryptAndVerifyAES(
            completed_chunk, self.encryption_key)
        assert decrypted_chunk == self.uncrypted_chunk

    def test_chunk_signing_and_validation(self):
        signature = encryption.signChunk(self.uncrypted_chunk,
                                         self.signing_key)
        assert len(signature) == 64
        assert type(signature) is bytes

        encryption.verifyChunk(self.uncrypted_chunk, signature,
                               self.verifying_key.hex())